std::unique_ptr<AST::Asignment> Parser_Ast::Impl::parseAsignment() { auto lhs = parseLHS(); if (lhs == nullptr) { return nullptr; } if (not parseEqualsign()) { throw std::logic_error("failed to parse ="); } auto rhs = parseRHS(); if (rhs == nullptr) { throw std::logic_error("failed to parse rhs"); } if (not parseSemicolon()) { throw std::logic_error("failed to parse ;"); } return std::make_unique<AST::Asignment>(std::move(lhs), std::move(rhs)); }
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 Parser::parseAssignmentExpr() { /* LHS = */parseUnaryExpr(); parseRHS(/* LHS, */ Precedence::Assignment); }
void Parser::parseExpression() { /* LHS = */parseUnaryExpr(); parseRHS(/* LHS, */ Precedence::Comma); }