⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nodes.cpp

📁 表达式计算expression evaluate expression evaluate expression evaluate
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/******************************************************************************
文件名          :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 + -