Result Calculator::run(Expression expr) { auto rpn = _parser.toRPN(expr); RPNStack calcStack; while (!rpn.empty()) { auto element = rpn.top(); if (!_parser.isOperator(element)) { calcStack.push(element); rpn.pop(); continue; } auto rhs = BigInteger(calcStack.top()); calcStack.pop(); auto lhs = BigInteger(calcStack.top()); calcStack.pop(); BigInteger result; if (element == "*") { result = lhs * rhs; } else if (element == "+") { result = lhs + rhs; } else if (element == "-") { result = lhs - rhs; } calcStack.push(result.value()); rpn.pop(); } return calcStack.top(); }
void RPNFunction::evaluate(RPNScript & scr, RPNStack & st) const { RPNConst * res = evaluateFun(st); if (res != 0) st.push(res); scr.nextCmd(); }
void RPNGo::evaluate(RPNScript & scr, RPNStack & st) const { RPNElem * op = st.pop(); RPNLabel * label = dynamic_cast<RPNLabel *>(op); if (label == 0) throw RPNError("Operand is not label"); scr.goToCmd(label->get()); delete op; }
void RPNGoFalse::evaluate(RPNScript & scr, RPNStack & st) const { RPNConst * opl = st.pop(); RPNConst * ope = st.pop(); RPNLabel * label = dynamic_cast<RPNLabel *>(opl); RPNInt * exp = dynamic_cast<RPNInt *>(ope); if (exp == 0) throw RPNError("Operand 1 is not integer"); if (label == 0) throw RPNError("Operand 2 is not label"); if (exp->get() == 0) scr.goToCmd(label->get()); else scr.nextCmd(); delete opl; delete ope; }
void TokenListToRPN(TokenList &a_list, RPNStack &a_rpn) { // Shunting yard algorithm std::vector<Token*> opStack; Token *c_token = a_list.head; while (c_token) { switch (c_token->type) { case Token::Type::Name: if (isalllower(c_token->name, true) && isvalidname(c_token->name)) { if (G::functions.Exists(c_token->name)) { opStack.push_back(c_token); c_token->type = Token::Type::E_Function; } else if (G::variables.Exists(c_token->name)) { a_rpn.push_back({ ExprNode::Type::Number, G::variables.Get(c_token->name) }); } else throw ExpressionError("Undefined reference", c_token); } else if (isallupper(c_token->name, true) && isvalidname(c_token->name)) { if (G::constants.Exists(c_token->name)) a_rpn.push_back({ ExprNode::Type::Number, G::constants.Get(c_token->name) }); else throw ExpressionError("Undefined constant", c_token); } else throw ExpressionError("Invalid value name", c_token); break; case Token::Type::Number: a_rpn.push_back({ ExprNode::Type::Number, c_token->value }); break; case Token::Type::Operator: if (opStack.size() > 0) { if (c_token->optype == Token::OpType::RPar) { Token *tos = opStack.back(); if (opStack.size() == 0) throw ExpressionError("#1 Mismatched parenthesis", c_token); while (tos->optype != Token::OpType::LPar) { a_rpn.push_back({ ExprNode::Type::Operator, 0, tos->optype }); opStack.pop_back(); tos = opStack.back(); if (opStack.size() == 0) throw ExpressionError("#2 Mismatched parenthesis", c_token); } opStack.pop_back(); // pop opening parantheses if (opStack.size() > 0) { tos = opStack.back(); if (tos->type == Token::Type::E_Function) { a_rpn.push_back({ ExprNode::Type::Function, 0, Token::OpType::None, HashFunc(tos->name) }); opStack.pop_back(); } } } else if (c_token->optype == Token::OpType::Comma) { Token *tos = opStack.back(); if (opStack.size() == 0) throw ExpressionError("Invalid separator", c_token); while (tos->optype != Token::OpType::LPar) { a_rpn.push_back({ ExprNode::Type::Operator, 0, tos->optype }); opStack.pop_back(); tos = opStack.back(); if (opStack.size() == 0) throw ExpressionError("Invalid separator", c_token); } } else { if (c_token->optype != Token::OpType::LPar) { while (opStack.size() > 0 && opStack.back()->optype != Token::OpType::LPar) { Token *tos = opStack.back(); if ((is_la(c_token->optype) && precedence(c_token->optype) <= precedence(tos->optype)) || (is_ra(c_token->optype) && precedence(c_token->optype) < precedence(tos->optype))) { opStack.pop_back(); a_rpn.push_back({ ExprNode::Type::Operator, 0, tos->optype }); } else break; } } opStack.push_back(c_token); } } else if (c_token->optype != Token::OpType::RPar || c_token->optype != Token::OpType::Comma) opStack.push_back(c_token); break; case Token::Type::Special: a_rpn.push_back({ ExprNode::Type::Special, 0, ExprNode::OpType::None, 0, c_token->sptype }); break; } c_token = c_token->next; } for (unsigned i = opStack.size(); i-- > 0; ) { if (opStack[i]->optype == Token::OpType::LPar || opStack[i]->optype == Token::OpType::RPar) throw ExpressionError("#3 Mismatched parenthesis", opStack[i]); a_rpn.push_back({ ExprNode::Type::Operator, 0, opStack[i]->optype }); } }
void RPNConst::evaluate(RPNScript & scr, RPNStack & st) const { st.push(clone()); scr.nextCmd(); }