// src/parser.cpp #include "parser.hpp" #include "ast.hpp" #include #include #include #include #include Parser::Parser(std::vector toks) : tokens(std::move(toks)) , position(0) , error_flag(false) , defs() {} const std::unordered_map>& Parser::definitions() const { return defs; } const Token& Parser::peek() const { if (position >= tokens.size()) throw std::runtime_error("parser: unexpected end of file"); return tokens[position]; } const Token& Parser::get() { if (position >= tokens.size()) throw std::runtime_error("parser: unexpected end of file"); return tokens[position++]; } bool Parser::accept(TokenType t) { if (position < tokens.size() && tokens[position].type == t) { ++position; return true; } return false; } void Parser::expect(TokenType t) { if (!accept(t)) { std::cout << display_tokentype(t) << std::endl; throw std::runtime_error("parser: unexpected token at position " + std::to_string(peek().start)); } } // Try to parse a definition of the form: // '=' ';' // Returns true if a definition was parsed and stored in defs. bool Parser::tryParseDefinition() { if (peek().type == TokenType::VARIABLE && position+1 < tokens.size() && tokens[position+1].type == TokenType::EQUALS) { std::string name = get().lexeme; // consume VARIABLE expect(TokenType::EQUALS); // consume '=' // parse the right-hand term std::unique_ptr value = parseTerm(); // require a semicolon (EOL token) expect(TokenType::EOL); // store in definitions map defs.emplace(std::move(name), std::move(value)); return true; } return false; } // ::= '\' + '.' // | // | '(' ')' std::unique_ptr Parser::parseSimple() { // abstraction with one-or-more parameters if (accept(TokenType::LAMBDA)) { std::vector params; while (peek().type == TokenType::VARIABLE) { params.push_back(get().lexeme); } expect(TokenType::DOT); std::unique_ptr body = parseTerm(); // right-nest them: \p1.\p2.…body for (auto it = params.rbegin(); it != params.rend(); ++it) { body = std::make_unique(*it, std::move(body)); } return body; } // variable if (peek().type == TokenType::VARIABLE) { const auto &tok = get(); return std::make_unique(tok.lexeme); } // parenthesized term if (accept(TokenType::LPAREN)) { std::unique_ptr e = parseTerm(); expect(TokenType::RPAREN); return e; } throw std::runtime_error("parser: expected \\, variable, or '(' at position " + std::to_string(peek().start)); } // ::= { } std::unique_ptr Parser::parseApplication() { std::unique_ptr expr = parseSimple(); while (true) { TokenType t = peek().type; if (t == TokenType::VARIABLE || t == TokenType::LAMBDA || t == TokenType::LPAREN) { std::unique_ptr rhs = parseSimple(); expr = std::make_unique(std::move(expr), std::move(rhs)); } else { break; } } return expr; } // ::= std::unique_ptr Parser::parseTerm() { return parseApplication(); } // parse exactly one term and expect EOC std::unique_ptr Parser::parse() { std::unique_ptr root = parseTerm(); expect(TokenType::EOC); return root; } // ::= { | EOL } EOC std::vector> Parser::parseProgram() { std::vector> results; while (peek().type != TokenType::EOC) { // first try a definition if (tryParseDefinition()) continue; // otherwise a bare term ending in EOL results.push_back(parseTerm()); expect(TokenType::EOL); } expect(TokenType::EOC); return results; }