📄 nodes.cpp
字号:
/******************************************************************************
文件名 :Nodes.cpp
版本号 : 1.0
作者 : Amos Peng
生成日期 :2008-07-08
最近修改 :
功能描述 :CNode基类与CNode派生出的子类
函数列表 :
*******************************************************************************/
#include "Nodes.h"
// Includes
using namespace ExprEval;
// Node
//------------------------------------------------------------------------------
// Constructor
CNode::CNode(CExpression *expr) : m_expr(expr)
{
if(expr == 0)
throw(CNullPointerException("CNode::CNode"));
}
// Destructor
CNode::~CNode()
{
}
// Evaluate
double CNode::Evaluate()
{
m_expr->TestAbort();
return DoEvaluate();
}
// Function node
//------------------------------------------------------------------------------
// Constructor
CFunctionNode::CFunctionNode(CExpression *expr) :
CNode(expr), m_argMin(0), m_argMax(0), m_refMin(0), m_refMax(0)
{
}
// Destructor
CFunctionNode::~CFunctionNode()
{
// Delete child nodes
::std::vector<CNode*>::size_type pos;
for(pos = 0; pos < m_nodes.size(); pos++)
{
delete m_nodes[pos];
}
}
// Get name
::std::string CFunctionNode::GetName() const
{
return m_factory->GetName();
}
// Set argument count
void CFunctionNode::SetArgumentCount(long argMin, long argMax, long refMin, long refMax)
{
m_argMin = argMin;
m_argMax = argMax;
m_refMin = refMin;
m_refMax = refMax;
}
// Parse expression
void CFunctionNode::Parse(CParser &parser, CParser::size_type start, CParser::size_type end, CParser::size_type v1)
{
CParser::size_type pos, last;
int plevel = 0;
// Sanity check (start/end are function parenthesis)
if(start >= end)
throw(CSyntaxException());
// Look
last = start + 1;
for(pos = start + 1; pos <= end && start + 1 != end; pos++)
{
switch(parser[pos].GetType())
{
case CToken::TypeOpenParenthesis:
{
plevel++;
break;
};
case CToken::TypeComma:
case CToken::TypeCloseParenthesis:
{
// Handle Close parenthesis for all but the last one at the end
if(parser[pos].GetType() == CToken::TypeCloseParenthesis && pos != end)
{
plevel--;
if(plevel < 0)
{
CUnmatchedParenthesisException e;
e.SetStart(parser[pos].GetStart());
e.SetEnd(parser[pos].GetEnd());
throw(e);
}
break;
}
// Handle comma, or if it was the ending parenthesis treat it like comma
if(plevel == 0)
{
if(pos > last)
{
// reference parameter?
if(parser[last].GetType() == CToken::TypeAmpersand)
{
// Reference parameter, check position and type of next parameter
if(last == pos - 2 && parser[last + 1].GetType() == CToken::TypeIdentifier)
{
// Get value list
CValueList *vlist = m_expr->GetValueList();
if(vlist == 0)
{
CNoValueListException e;
e.SetStart(parser[last + 1].GetStart());
e.SetEnd(parser[last + 1].GetEnd());
throw(e);
}
// Get name
::std::string ident = parser[last + 1].GetIdentifier();
// Make sure it is not a constant
if(vlist->IsConstant(ident))
{
CConstantReferenceException e(ident);
e.SetStart(parser[last + 1].GetStart());
e.SetEnd(parser[last + 1].GetEnd());
throw(e);
}
// Get address
double *vaddr = vlist->GetAddress(ident);
if(vaddr == 0)
{
// Try to add it and get again
vlist->Add(ident);
vaddr = vlist->GetAddress(ident);
}
if(vaddr == 0)
{
CNotFoundException e(ident);
e.SetStart(parser[last + 1].GetStart());
e.SetEnd(parser[last + 1].GetEnd());
throw(e);
}
// Add it
m_refs.push_back(vaddr);
}
else
{
CSyntaxException e;
e.SetStart(parser[last].GetStart());
e.SetEnd(parser[pos].GetEnd());
throw(e);
}
} // TypeAmpersand
else
{
// Create node
auto_ptr<CNode> n(parser.ParseRegion(last, pos - 1));
m_nodes.push_back(n.get());
n.release();
}
}
else
{
CSyntaxException e;
e.SetStart(parser[pos].GetStart());
e.SetEnd(parser[pos].GetEnd());
throw(e);
}
last = pos + 1;
}
break;
}
}
}
// plevel should be zero
if(plevel != 0)
{
CUnmatchedParenthesisException e;
e.SetStart(parser[end].GetStart());
e.SetEnd(parser[end].GetEnd());
throw(e);
}
// Check argument count
if(m_argMin != -1 && m_nodes.size() < (::std::vector<CNode*>::size_type)m_argMin)
{
CInvalidArgumentCountException e(GetName());
e.SetStart(parser[start].GetStart());
e.SetEnd(parser[end].GetEnd());
throw(e);
}
if(m_argMax != -1 && m_nodes.size() > (::std::vector<CNode*>::size_type)m_argMax)
{
CInvalidArgumentCountException e(GetName());
e.SetStart(parser[start].GetStart());
e.SetEnd(parser[end].GetEnd());
throw(e);
}
if(m_refMin != -1 && m_refs.size() < (::std::vector<double*>::size_type)m_refMin)
{
CInvalidArgumentCountException e(GetName());
e.SetStart(parser[start].GetStart());
e.SetEnd(parser[end].GetEnd());
throw(e);
}
if(m_refMax != -1 && m_refs.size() > (::std::vector<double*>::size_type)m_refMax)
{
CInvalidArgumentCountException e(GetName());
e.SetStart(parser[start].GetStart());
e.SetEnd(parser[end].GetEnd());
throw(e);
}
}
// Multi node
//------------------------------------------------------------------------------
// Constructor
CMultiNode::CMultiNode(CExpression *expr) : CNode(expr)
{
}
// Destructor
CMultiNode::~CMultiNode()
{
// Free child nodes
::std::vector<CNode*>::size_type pos;
for(pos = 0; pos < m_nodes.size(); pos++)
{
delete m_nodes[pos];
}
}
// Evaluate
double CMultiNode::DoEvaluate()
{
::std::vector<CNode*>::size_type pos;
double result = 0.0;
for(pos = 0; pos < m_nodes.size(); pos++)
{
result = m_nodes[pos]->Evaluate();
}
return result;
}
// Parse
void CMultiNode::Parse(CParser &parser, CParser::size_type start, CParser::size_type end, CParser::size_type v1)
{
CParser::size_type pos, last;
int plevel = 0;
// Sanity check
if(start >= end)
throw(CSyntaxException());
// Look
last = start;
for(pos = start; pos <= end; pos++)
{
switch(parser[pos].GetType())
{
case CToken::TypeOpenParenthesis:
{
plevel++;
break;
};
case CToken::TypeCloseParenthesis:
{
plevel--;
if(plevel < 0)
{
CUnmatchedParenthesisException e;
e.SetStart(parser[pos].GetStart());
e.SetEnd(parser[pos].GetEnd());
throw(e);
}
break;
}
case CToken::TypeSemicolon:
{
if(plevel == 0)
{
if(pos > last)
{
// Everything from last to pos - 1
auto_ptr<CNode> n(parser.ParseRegion(last, pos - 1));
m_nodes.push_back(n.get());
n.release();
}
else
{
CSyntaxException e;
e.SetStart(parser[last].GetStart());
e.SetEnd(parser[pos].GetEnd());
throw(e);
}
last = pos + 1;
}
break;
}
}
}
// plevel should be zero
if(plevel != 0)
{
CUnmatchedParenthesisException e;
e.SetStart(parser[pos].GetStart());
e.SetEnd(parser[pos].GetEnd());
throw(e);
}
// If the end was not a semicolon, test it as well
if(last < end + 1)
{
auto_ptr<CNode> n(parser.ParseRegion(last, end));
m_nodes.push_back(n.get());
n.release();
}
}
// Assign node
//------------------------------------------------------------------------------
// Constructor
CAssignNode::CAssignNode(CExpression *expr) : CNode(expr), m_var(0), m_rhs(0)
{
}
// Destructor
CAssignNode::~CAssignNode()
{
// Free child node
delete m_rhs;
}
// Evaluate
double CAssignNode::DoEvaluate()
{
return (*m_var = m_rhs->Evaluate());
}
// Parse
void CAssignNode::Parse(CParser &parser, CParser::size_type start, CParser::size_type end, CParser::size_type v1)
{
// Check some basic syntax
if(v1 != start + 1 || v1 >= end)
{
CSyntaxException e;
e.SetStart(parser[start].GetStart());
e.SetEnd(parser[end].GetEnd());
throw(e);
}
// Get the value list
CValueList *vlist = m_expr->GetValueList();
if(vlist == 0)
{
NoValueListException e;
e.SetStart(parser[start].GetStart());
e.SetEnd(parser[start].GetEnd());
throw(e);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -