void Parser::parseRHS(/* ASTNode* LHS, */ unsigned MinPrec) { unsigned NextTokPrec = getOperatorPrecedence(lex.peek()); while (1) { // If this token has a lower precedence than we are allowed to parse (e.g. // because we are called recursively, or because the token is not a binop), // then we are done! if (NextTokPrec < MinPrec) return /* LHS */; // Consume the operator, saving the operator token for error reporting. Token OpToken = lex.peek(); lex.consume(); // Special case handling for the ternary operator /* ASTNode* TernaryMiddle = 0 */ if (NextTokPrec == Precedence::Conditional) { if (lex.peek().type != Token::COLON) /* TernaryMiddle = */ parseExpression(); // Eat the colon lex.consume(Token::COLON); } // Parse another leaf here for the RHS of the operator. /* ASTNode* RHS = */ parseUnaryExpr(); // Remember the precedence of this operator and get the precedence of the // operator immediately to the right of the RHS. unsigned ThisPrec = NextTokPrec; NextTokPrec = getOperatorPrecedence(lex.peek()); // Assignment and conditional expressions are right-associative. bool isRightAssoc = ThisPrec == Precedence::Conditional || ThisPrec == Precedence::Assignment; // Get the precedence of the operator to the right of the RHS. If it binds // more tightly with RHS than we do, evaluate it completely first. if (ThisPrec < NextTokPrec || (ThisPrec == NextTokPrec && isRightAssoc)) { // If this is left-associative, only parse things on the RHS that bind // more tightly than the current operator. If it is left-associative, it // is okay, to bind exactly as tightly. For example, compile A=B=C=D as // A=(B=(C=D)), where each paren is a level of recursion here. /* RHS =*/ parseRHS(/* RHS, */ ThisPrec + !isRightAssoc); NextTokPrec = getOperatorPrecedence(lex.peek()); } assert(NextTokPrec <= ThisPrec && "Recursion didn't work!"); /* if (TernaryMiddle) LHS = new TernaryASTNode(LHS, TernaryMiddle, RHS); else LHS = new ASTNode(OpToken, LHS, RHS); */ } }
void RecreatorImpl::recreateUnaryOperator() { auto operand = moveTopString(); appendUnaryOperator(); auto operator_precedence = getOperatorPrecedence(); appendUnaryOperand(std::move(operand), operator_precedence); setTopPrecedence(operator_precedence); setTopUnaryOperatorPrecedence(operator_precedence); }
void RecreatorImpl::recreateBinaryOperator() { auto rhs = stack.top(); pop(); auto operator_precedence = getOperatorPrecedence(); appendLeftOperand(operator_precedence); appendBinaryOperator(); appendRightOperand(rhs, operator_precedence); setTopPrecedence(operator_precedence); setTopUnaryOperatorPrecedence(rhs.unary_operator_precedence); }
std::queue<std::string> Parser::createPostFix(const std::string &input, bool& failed) { std::queue<std::string> output; std::stack<std::string> operators; std::vector<std::string> tokens = parseStringToToken(input, failed); if(!failed) { for(unsigned int i = 0; i < tokens.size(); i++) { if(isdigit(tokens[i][0]) || tokens[i][0] == '#') { output.push(tokens[i]); } //TO DO //If functions (sin,cos,log...) else if(tokens[i] != "(" && tokens[i] != ")") //assume token is an operator (Functions not implemented) { if(!operators.empty()) { int tokensPrecedence = getOperatorPrecedence(tokens[i]); int topTokenPrecedence = getOperatorPrecedence(operators.top()); bool isLeftAssociative = testLeftAssociativity(tokens[i]); bool isOperator = (operators.top() != "(" && operators.top() != ")"); bool isEmpty = false; while(isOperator && !isEmpty && ((isLeftAssociative && tokensPrecedence >= topTokenPrecedence) || (!isLeftAssociative && tokensPrecedence > topTokenPrecedence))) { output.push(operators.top()); operators.pop(); isEmpty = operators.empty(); if(!isEmpty) { isOperator = (operators.top() != "(" && operators.top() != ")"); topTokenPrecedence = getOperatorPrecedence(operators.top()); } } } operators.push(tokens[i]); } else if(tokens[i] == "(") { operators.push(tokens[i]); } else if(tokens[i] == ")") { if(!operators.empty()) { while(operators.top() != "(") { output.push(operators.top()); operators.pop(); } operators.pop(); } else { failed = true; errorCode_ = ERR_SYNTAX; } } else { failed = true; errorCode_ = ERR_SYNTAX; } } while(!operators.empty()) { output.push(operators.top()); operators.pop(); } } if(!operators.empty()) { failed = true; errorCode_ = ERR_SYNTAX; } return output; }
double in_eval(char *exp) { int exp_length = strlen(exp), numOfVars = 0; struct operator_stack *os = create_operator_stack(exp_length / 2); char *token, *copy, *vars[10] = {NULL}, rpn_exp[1024] = ""; double value = 0; copy = (char *) malloc(sizeof(char) * exp_length); strcpy(copy, exp); token = strtok(copy, " "); bool previousIsOperator = false, previousIsLeftParenthese = false, varsSet = false; while (token != NULL) { errorOccurs = true; varsSet = false; if (isNumeric(token) && sscanf(token, "%lf", &value) > 0) { if (!(strlen(rpn_exp) == 0 || previousIsOperator || previousIsLeftParenthese)) return value; for (int i = 0; i < numOfVars; i++) { setVariable(vars[i], value); vars[i] = NULL; varsSet = true; } numOfVars = 0; errorOccurs = false; previousIsOperator = false; previousIsLeftParenthese = false; concat_double(rpn_exp, value); } else if (variableValid(token)) { if (!(strlen(rpn_exp) == 0 || previousIsOperator || previousIsLeftParenthese)) return value; char operator = *(token + strlen(token) + 1); if (operator == '=') { vars[numOfVars++] = token; errorOccurs = false; } else { value = getVariable(token); errorOccurs = !variableExists(token); concat_double(rpn_exp, value); } previousIsOperator = false; previousIsLeftParenthese = false; } else if (isOperator(token) || isParenthese(token)) { if ((isOperator(token) && previousIsOperator) || (strcmp(token, ")") == 0 && strlen(rpn_exp) == 0)) return value; if (numOfVars > 0) return value; char *op = NULL; if (strcmp(token, "(") == 0) { push_operator(os, token); previousIsLeftParenthese = true; } else if (strcmp(token, ")") == 0) { op = peek_operator(os); if (strcmp(op, "(") == 0) return value; op = pop_operator(os); while (strcmp(op, "(") != 0) { if (strcmp(op, ")") == 0) return value; concat_operator(rpn_exp, op); op = pop_operator(os); } previousIsLeftParenthese = false; } else { int pre1 = -1, pre2 = getOperatorPrecedence(token); if (os->top > -1) pre1 = getOperatorPrecedence(peek_operator(os)); while (pre2 > pre1 && pre1 > 0 && os->top > -1) { concat_operator(rpn_exp, pop_operator(os)); if (os->top > -1) pre1 = getOperatorPrecedence(peek_operator(os)); } push_operator(os, token); previousIsOperator = true; previousIsLeftParenthese = false; } errorOccurs = false; } else if (strcmp(token, "=") == 0) { errorOccurs = false; } else { return value; } if (errorOccurs) return value; token = strtok(NULL, " "); } while (os->top > -1) concat_operator(rpn_exp, pop_operator(os)); free(copy); free_operator_stack(os); if (!(varsSet || errorOccurs)) value = rpn_eval(rpn_exp); return value; }