// Parse a primary expression. // // primary-expr -> literal | identifier | '(' expr ')' // // literal -> integer-literal // | boolean-literal // | character-literal // | string-literal Expr* Parser::primary_expr() { // identifier if (Token tok = match_if(identifier_tok)) return on_id(tok); // boolean-literal if (Token tok = match_if(boolean_tok)) return on_bool(tok); // integer-literal if (Token tok = match_if(integer_tok)) return on_int(tok); // character-literal if (Token tok = match_if(character_tok)) return on_char(tok); // string-literal if (Token tok = match_if(string_tok)) return on_str(tok); // paren-expr if (match_if(lparen_tok)) { Expr* e = expr(); match(rparen_tok); return e; } // FIXME: Is this definitely an error? Or can we // actually return nullptr and continue? error("expected primary expression"); }
// Parse a postfix expression. // // postfix-expression -> postfix-expression '(' argument-list ')' // | postfix-expression '[' expression ']' // | postfix-expression . identifier // | primary-expression Expr* Parser::postfix_expr() { Expr* e1 = primary_expr(); while (true) { // dot-expr if (match_if(dot_tok)) { Token tok = match(identifier_tok); Expr* e2 = on_id(tok); e1 = on_dot(e1, e2); } // call-expr else if (match_if(lparen_tok)) { Expr_seq args; while (lookahead() != rparen_tok) { args.push_back(expr()); if (match_if(comma_tok)) continue; else break; } match(rparen_tok); e1 = on_call(e1, args); } // index-expr else if (match_if(lbrack_tok)) { Expr* e2 = expr(); match(rbrack_tok); e1 = on_index(e1, e2); } // anything else else { break; } } return e1; }
Expr const* Parser::id() { Token tok = require(identifier_tok); return on_id(tok); }