ast::Expr *parseExpr(TokenIt &it, const TokenIt &end) { ast::Expr *lhs = parsePrimary(it, end); if(!lhs) return NULL; return parseBinOpRHS(NULL, lhs, it, end); }
ast::Expr *parseBinOpRHS(int exprPrecendence, ast::Expr *lhs, TokenIt &it, const TokenIt &end) { while(1) { Token *current = currentToken(it, end); char binOp = current ? current->value.c_str()[0] : 0; int precendence = opPrecedence(binOp); if(precendence < exprPrecendence) return lhs; nextToken(it, end); ast::Expr *rhs = parsePrimary(it, end); if(!rhs) return NULL; current = currentToken(it, end); int nextPrecedence = opPrecedence(current ? current->value.c_str()[0] : 0); if(precendence < nextPrecedence) { rhs = parseBinOpRHS(precendence + 1, rhs, it, end); if(!rhs) return NULL; } lhs = new ast::BinaryExpr(binOp, lhs, rhs); } }
std::unique_ptr<ExprAST> Parser::parseBinOpRHS(int prec, std::unique_ptr<ExprAST> lhs, s_cursor_t &it, const s_cursor_t &end) { while (true) { int prec_ = currentTokPrecedence(); if (prec_ < prec) { return lhs; } int binOp = _curTok; getNextToken(it, end); auto rhs = parsePrimary(it, end); if (!rhs) return nullptr; int nextPrec = currentTokPrecedence(); if (prec_ < nextPrec) { rhs = parseBinOpRHS(prec_ + 1, std::move(rhs), it, end); if (!rhs) return nullptr; } lhs = llvm::make_unique<BinaryExprAST>(&_builder, binOp, std::move(lhs), std::move(rhs)); } }
std::unique_ptr<ExprAST> Parser::parseExpression(s_cursor_t &it, const s_cursor_t &end) { auto lhs = parsePrimary(it, end); if (!lhs) return nullptr; return parseBinOpRHS(0, std::move(lhs), it, end); }
// Parse a complete expression ExprAST *Parser::parseExpression () { ExprAST *LHS = parsePrimary (); if (!LHS) return NULL; return parseBinOpRHS (0, LHS); }
ExprAST* Parser::parseBinOpRHS(int exprPrecedence, ExprAST* LHS) { while (1) { int TokPrec = getOpPrecedence(); if (TokPrec < exprPrecedence) return LHS; int binOp = lexer->token; lexer->NextToken(); ExprAST* RHS = parsePrimary(); if (!RHS) return 0; int NextPrec = getOpPrecedence(); if (TokPrec < NextPrec) { RHS = parseBinOpRHS(TokPrec + 1, RHS); if (!RHS) return 0; } LHS = new BinaryExprAST(LHS, RHS, binOp); } }
ExprAST *Parser::parseBinOpRHS (int exprPrecedence, ExprAST *LHS) { while (1) { // This should be either an operator, a close-paren, comma, // or the end of the formula. if (currentToken != TOKEN_OPERATOR && currentToken != TOKEN_PAREN_CLOSE && currentToken != TOKEN_COMMA && currentToken != TOKEN_END) { error (boost::format ("Attempting to parse the RHS of a binary operator, " "and got %1%!") % formatToken ()); return NULL; } // Get the precedence int tokenPrecedence = -1; for (int i = 0 ; i < NUM_OPERATORS ; i++) { if (strToken == operators[i].name) { tokenPrecedence = operators[i].precedence; break; } } // We're done if we run into an equivalent or lower-precedence binary // operator (or, notably, something that's not an operator at all, like // the end of the formula) if (tokenPrecedence < exprPrecedence) return LHS; // Pull off the operator std::string binOp = strToken; getNextToken (); // Parse the primary after the operator ExprAST *RHS = parsePrimary (); if (!RHS) return NULL; // We've now parsed a full binary operator pair, "A op B". If the next // thing is a binary operator (which it should be, or it should be // nothing at all), we need to see whether we want "(A op B) op2 ..." or // "A op (B op2 ...)" by precedence rules. Look ahead: int nextPrecedence = -1; for (int i = 0 ; i < NUM_OPERATORS ; i++) { if (strToken == operators[i].name) { nextPrecedence = operators[i].precedence; break; } } if (tokenPrecedence < nextPrecedence) { // Next precedence is greater, we want "A op (B op2 ...)". Do that by // parsing B op2 ... into a new RHS. RHS = parseBinOpRHS (tokenPrecedence + 1, RHS); if (RHS == NULL) return NULL; } // Next precedence is lower, we want "(A op B) op2 ...", so make a new LHS LHS = new BinaryExprAST (binOp, LHS, RHS); // And loop back to the beginning } }