#include "parser.hh" #include "expr.hh" #include "../error_handler.hh" #include "../tokenizer.hh" #include extern ErrorHandler error_handler; std::optional Parser::parse() { try { return expression(); } catch (ParseException e) { return std::nullopt; } } Expr Parser::expression() { return equality(); } Expr Parser::equality() { Expr expr = comparison(); while (match({TokenType::BANG_EQUAL, TokenType::EQUAL_EQUAL})) { Token op = previous(); Expr right = comparison(); expr = Binary(expr, op, right); } return expr; } Expr Parser::comparison() { Expr expr = term(); while (match({TokenType::GREATER, TokenType::GREATER_EQUAL, TokenType::LESS, TokenType::LESS_EQUAL})) { Token op = previous(); Expr right = term(); expr = Binary(expr, op, right); } return expr; } Expr Parser::term() { Expr expr = factor(); while (match({TokenType::MINUS, TokenType::PLUS})) { Token op = previous(); Expr right = factor(); expr = Binary(expr, op, right); } return expr; } Expr Parser::factor() { Expr expr = unary(); while (match({TokenType::SLASH, TokenType::STAR})) { Token op = previous(); Expr right = unary(); expr = Binary(expr, op, right); } return expr; } Expr Parser::unary() { if (match({TokenType::BANG, TokenType::MINUS})) { Token op = previous(); Expr right = unary(); return Unary(op, right); } return primary(); } Expr Parser::primary() { if (match({TokenType::FALSE})) { return Literal(false); } if (match({TokenType::TRUE})) { return Literal(true); } if (match({TokenType::NIL})) { return Literal(Object{}); } if (match({TokenType::NUMBER, TokenType::STRING})) { return Literal(previous().literal); } if (match({TokenType::LEFT_PAREN})) { Expr expr = expression(); consume(TokenType::RIGHT_PAREN, "Expect ')' after expression."); return Grouping(expr); } throw error(peek(), "Expect expression."); } Token Parser::advance() { if (!is_at_end()) { ++current; } return previous(); } Token Parser::peek() { return tokens.at(current); } Token Parser::previous() { return tokens.at(current - 1); } Token Parser::consume(TokenType type, std::string &&message) { if (check(type)) { return advance(); } throw error(peek(), message); } bool Parser::match(std::vector types) { for (const auto &type : types) { if (check(type)) { advance(); return true; } } return false; } bool Parser::check(TokenType type) { if (is_at_end()) { return false; } return peek().type == type; } bool Parser::is_at_end() { return peek().type == TokenType::EOFILE; } ParseException Parser::error(Token token, std::string &message) { error_handler.error(token, message); return ParseException{}; } ParseException Parser::error(Token token, std::string &&message) { return error(token, message); } void Parser::synchronize() { advance(); while (!is_at_end()) { if (previous().type == TokenType::SEMICOLON) { return; } switch (peek().type) { case TokenType::CLASS: case TokenType::FUN: case TokenType::VAR: case TokenType::FOR: case TokenType::IF: case TokenType::WHILE: case TokenType::PRINT: case TokenType::RETURN: return; default: break; } advance(); } }