const double Parser::Evaluate () // get result { pWord_ = program_.c_str (); type_ = NONE; double v = CommaList (true); if (type_ != END) throw std::runtime_error ("Inaspettato testo al termine dell'espressione: " + std::string (pWordStart_)); return v; }
/*! \brief \fn Parser::Evaluate \return const double */ const double Parser::Evaluate () // get result { pWord_ = program_.c_str (); type_ = NONE; double v = CommaList (true); if (type_ != END) { // throw std::runtime_error ("Unexpected text at end of expression: " + std::string (pWordStart_)); } return v; }
/*! \brief \fn Parser::Primary \param get \return const double */ const double Parser::Primary (const bool get) // primary (base) tokens { if (get) GetToken (); // one-token lookahead switch (type_) { case NUMBER: { double v = value_; GetToken (true); // get next one (one-token lookahead) return v; } case NAME: { std::string word = word_; GetToken (true); if (type_ == LHPAREN) { // might be single-argument function (eg. abs (x) ) std::map<std::string, OneArgFunction>::const_iterator si; si = OneArgumentFunctions.find (word); if (si != OneArgumentFunctions.end ()) { double v = Expression (true); // get argument CheckToken (RHPAREN); GetToken (true); // get next one (one-token lookahead) return si->second (v); // evaluate function } // might be double-argument function (eg. roll (6, 2) ) std::map<std::string, TwoArgFunction>::const_iterator di; di = TwoArgumentFunctions.find (word); if (di != TwoArgumentFunctions.end ()) { double v1 = Expression (true); // get argument 1 (not commalist) CheckToken (COMMA); double v2 = Expression (true); // get argument 2 (not commalist) CheckToken (RHPAREN); GetToken (true); // get next one (one-token lookahead) return di->second (v1, v2); // evaluate function } // might be double-argument function (eg. roll (6, 2) ) std::map<std::string, ThreeArgFunction>::const_iterator ti; ti = ThreeArgumentFunctions.find (word); if (ti != ThreeArgumentFunctions.end ()) { double v1 = Expression (true); // get argument 1 (not commalist) CheckToken (COMMA); double v2 = Expression (true); // get argument 2 (not commalist) CheckToken (COMMA); double v3 = Expression (true); // get argument 3 (not commalist) CheckToken (RHPAREN); GetToken (true); // get next one (one-token lookahead) return ti->second (v1, v2, v3); // evaluate function } //throw std::runtime_error ("Function '" + word + "' not implemented."); } // not a function? must be a symbol in the symbol table double & v = symbols_ [word]; // get REFERENCE to symbol table entry // change table entry with expression? (eg. a = 22, or a = 22) switch (type_) { // maybe check for NaN or Inf here (see: isinf, isnan functions) case ASSIGN: v = Expression (true); break; case ASSIGN_ADD: v += Expression (true); break; case ASSIGN_SUB: v -= Expression (true); break; case ASSIGN_MUL: v *= Expression (true); break; case ASSIGN_DIV: { double d = Expression (true); if (d == 0.0) { //throw std::runtime_error ("Divide by zero"); } v /= d; break; // change table entry with expression } // end of ASSIGN_DIV default: break; // do nothing for others } // end of switch on type_ return v; // and return new value } case MINUS: // unary minus return - Primary (true); case NOT: // unary not return (Primary (true) == 0.0) ? 1.0 : 0.0;; case LHPAREN: { double v = CommaList (true); // inside parens, you could have commas CheckToken (RHPAREN); GetToken (true); // eat the ) return v; } default: break; //throw std::runtime_error ("Unexpected token: " + word_); } // end of switch on type } // end of Parser::Primary