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

📄 parser.cpp

📁 表达式计算expression evaluate expression evaluate expression evaluate
💻 CPP
📖 第 1 页 / 共 2 页
字号:
        else
        {
            CSyntaxException e;
            
            e.SetStart(m_tokens[fgopen].GetStart());
            if(fgclose == (size_type)-1)
            {
                e.SetEnd(m_tokens[fgopen].GetEnd());
            }                
            else
            {
                e.SetEnd(m_tokens[fgclose].GetEnd());
            }                
            throw(e);
        }
    }
    else if(fgopen == start + 1)
    {
        // Function
        if(fgclose == end)
        {
            // Find function list
            CFunctionList *flist = m_expr->GetFunctionList();
            
            if(flist == 0)
            {
                CNoFunctionListException e;
        
                e.SetStart(m_tokens[start].GetStart());
                e.SetEnd(m_tokens[start].GetEnd());
                throw(e);
            }
                
            // Get name
            ::std::string ident = m_tokens[start].GetIdentifier();
            
            // Create function node
            ::std::auto_ptr<CFunctionNode> n(flist->Create(ident, m_expr));
            
            if(n.get())
            {
                n->Parse(*this, fgopen, fgclose);
            }
            else
            {
                CNotFoundException e(ident);
        
                e.SetStart(m_tokens[start].GetStart());
                e.SetEnd(m_tokens[start].GetEnd());
                throw(e);                
            }
                
            return n.release();
        }
        else
        {
            CSyntaxException e;
        
            e.SetStart(m_tokens[fgopen].GetStart());
            if(fgclose == (size_type)-1)
            {
                e.SetEnd(m_tokens[fgopen].GetEnd());
            }                
            else
            {
                e.SetEnd(m_tokens[fgclose].GetEnd()); 
            }                
            throw(e);
        }
    }
    else if(start == end)
    {
        // Value, variable, or constant
        
        if(m_tokens[start].GetType() == CToken::TypeIdentifier)
        {
            // Variable/constant
            ::std::auto_ptr<CNode> n(new CVariableNode(m_expr));
            n->Parse(*this, start, end);
            return n.release();    
        }
        else
        {
            // Value
            ::std::auto_ptr<CNode> n(new CValueNode(m_expr));
            n->Parse(*this, start, end);
            return n.release();
        }
    }
    else
    {
        // Unknown, syntax
        CSyntaxException e;
        
        e.SetStart(m_tokens[pos].GetStart());
        e.SetEnd(m_tokens[pos].GetEnd());
        
        throw(e);
    }
}
    
// Get a token
const CToken& CParser::operator[] (CParser::size_type pos) const
{
    return m_tokens[pos];
}
    
// Build tokens
void CParser::BuildTokens(const ::std::string &exstr)
{
    m_tokens.clear();
    
    // Test zero-length expression
    if(exstr.length() == 0)
    {
        throw(CEmptyExpressionException());
    }
        
    // Search through list
    ::std::string::size_type pos;
    bool comment = false;
    
    for(pos = 0; pos < exstr.length(); pos++)
    {
        // Take action based on character
        switch(exstr[pos])
        {
            // Comment
            case '#':
            {
                comment = true;
                    
                break;
            }
                
            // Newline ends comment
            case '\r':
            case '\n':
            {
                comment = false;
                
                break;
            }
                
            // Open parenthesis
            case '(':
            {
                if(comment == false)
                {
                    m_tokens.push_back(CToken(CToken::TypeOpenParenthesis, pos, pos));
                }
                break;
            }
                
            // Close parenthesis
            case ')':
            {
                if(comment == false)
                {
                    m_tokens.push_back(CToken(CToken::TypeCloseParenthesis, pos, pos));
                }
                break;
            }
                
            // Equal
            case '=':
            {
                if(comment == false)
                {
                    m_tokens.push_back(CToken(CToken::TypeEqual, pos, pos));
                }
                break;
            }
                
            // Plus
            case '+':
            {
                if(comment == false)
                {
                    m_tokens.push_back(CToken(CToken::TypePlus, pos, pos));
                }
                break;
            }
                
            // Hyphen
            case '-':
            {
                if(comment == false)
                {
                    m_tokens.push_back(CToken(CToken::TypeHyphen, pos, pos));
                }
                break;
            }
                
            // Asterisk
            case '*':
            {
                if(comment == false)
                {
                    m_tokens.push_back(CToken(CToken::TypeAsterisk, pos, pos));
                }
                break;
            }
                
            // Forward slash
            case '/':
            {
                if(comment == false)
                {
                    m_tokens.push_back(CToken(CToken::TypeForwardSlash, pos, pos));
                }
                break;
            }
                
            // Hat (exponent)
            case '^':
            {
                if(comment == false)
                {
                    m_tokens.push_back(CToken(CToken::TypeHat, pos, pos));
                }
                break;
            }
                
            // Ampersand
            case '&':
            {
                if(comment == false)
                {
                    m_tokens.push_back(CToken(CToken::TypeAmpersand, pos, pos));
                }
                break;
            }
                
            // Comma
            case ',':
            {
                if(comment == false)
                {
                    m_tokens.push_back(CToken(CToken::TypeComma, pos, pos));
                }
                break;
            }
                
            // Semicolon
            case ';':
            {
                if(comment == false)
                {
                    m_tokens.push_back(CToken(CToken::TypeSemicolon, pos, pos));
                }
                break;
            }
                
            // None of the above, but it may be an identifier or value
            default:
            {
                if(comment == false)
                {
                    // First, test for value
                    if(exstr[pos] == '.' || expreval_isdigit(exstr[pos]))
                    {
                        // We are a value
                        ::std::string::size_type start = pos;
                        
                        // Digits before period
                        while(expreval_isdigit(exstr[pos]))
                        {
                            pos++;
                        }                            
                            
                        // Period
                        if(exstr[pos] == '.')
                        {
                            pos++;
                        }                            
                            
                        // Digits after period
                        while(expreval_isdigit(exstr[pos]))
                        {
                            pos++;
                        }
                            
                            
                        // Create token
                        ::std::string ident = exstr.substr(start, pos - start);
                        m_tokens.push_back(CToken(expreval_atof(ident.c_str()), start, pos - 1));
                        
                        // Move pos back so pos++ will set it right
                        pos--;
                    }
                    else if(exstr[pos] == '_' || expreval_isalpha(exstr[pos]))
                    {
                        // We are an identifier
                        ::std::string::size_type start = pos;
                        bool foundname = true; // Found name part
                        
                        // Search for name, then period, etc
                        // An identifier can be multiple parts.  Each part
                        // is formed as an identifier and seperated by a period,
                        // An identifier can not end in a period
                        //
                        // color1.red : 1 identifier token
                        // color1. : color1 is identifier, . begins new token
                        // color1.1red : Not value (part 2 is not right)
                        while(foundname)
                        {
                            // Part before period
                            while(exstr[pos] == '_' || expreval_isalnum(exstr[pos]))
                            {
                                pos++;
                            }                               
                                
                            // Is there a period
                            if(exstr[pos] == '.')
                            {
                                pos++;
                                
                                // There is a period, look for the name again
                                if(exstr[pos] == '_' || expreval_isalpha(exstr[pos]))
                                {
                                    foundname = true;
                                }
                                else
                                {
                                    // No name after period
                                    foundname = false;
                                    
                                    // Remove period from identifier
                                    pos--;
                                }
                            }
                            else
                            {
                                // No period after name, so no new name
                                foundname = false;
                            }
                        }
                            
                        // Create token
                        m_tokens.push_back(CToken(exstr.substr(start, pos - start), start, pos - 1));
                        
                        // Move pos back so pos++ will set it right
                        pos--;
                    }
                    else if(expreval_isspace(exstr[pos]))
                    {
                        // Do nothing, just ignore white space, but it still
                        // seperates tokens
                    }
                    else
                    {
                        // Unknown token
                        CUnknownTokenException e;
                        e.SetStart(pos);
                        e.SetEnd(pos);
                        
                        throw(e);
                    }
                }
                break;
            }
        }
    }
}    

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -