#include "cps/Parser.h" #include "cps/FunctionAST.h" using namespace cps; Parser::Parser(Lexer &L) : Lex(L) { getNextToken(); BinopPrecedence[tok_or] = 3; BinopPrecedence[tok_and] = 5; BinopPrecedence[tok_eq] = 10; BinopPrecedence[tok_ne] = 10; BinopPrecedence[tok_le] = 10; BinopPrecedence[tok_ge] = 10; BinopPrecedence['<'] = 10; BinopPrecedence['>'] = 10; BinopPrecedence['+'] = 20; BinopPrecedence['-'] = 20; BinopPrecedence['&'] = 20; BinopPrecedence['*'] = 40; BinopPrecedence['/'] = 40; BinopPrecedence[tok_div] = 40; BinopPrecedence[tok_mod] = 40; } int Parser::GetTokPrecedence() { if (BinopPrecedence.find(CurTok) == BinopPrecedence.end()) return -1; int TokPrec = BinopPrecedence[CurTok]; if (TokPrec <= 0) return -1; return TokPrec; } int Parser::getNextToken() { return CurTok = Lex.gettok(); } std::unique_ptr Parser::ParseNumberExpr() { if (CurTok == tok_number_real) { auto Result = std::make_unique(Lex.RealVal); getNextToken(); return Result; } auto Result = std::make_unique(Lex.NumVal); getNextToken(); return Result; } std::unique_ptr Parser::ParseIdentifierExpr() { std::string IdName = Lex.IdentifierStr; int Line = Lex.getLine(); getNextToken(); if (CurTok == '(') { getNextToken(); std::vector> Args; if (CurTok != ')') { while (true) { if (auto Arg = ParseExpression()) Args.push_back(std::move(Arg)); else return nullptr; if (CurTok == ')') break; if (CurTok != ',') { fprintf(stderr, "Error: Expected ')' or ',' in function call.\n"); return nullptr; } getNextToken(); } } getNextToken(); return std::make_unique(IdName, std::move(Args)); } if (CurTok == '[') { getNextToken(); std::vector> Indices; while (true) { auto Exp = ParseExpression(); if (!Exp) return nullptr; Indices.push_back(std::move(Exp)); if (CurTok == ']') break; if (CurTok == ',') { getNextToken(); continue; } fprintf(stderr, "Error: Expected ',' or ']'\n"); return nullptr; } getNextToken(); return std::make_unique(IdName, std::move(Indices), Line); } return std::make_unique(IdName); } std::unique_ptr Parser::ParseStringBuiltin(const std::string &FuncName) { getNextToken(); if (CurTok != '(') { fprintf(stderr, "Error: Expected '(' after %s\n", FuncName.c_str()); return nullptr; } getNextToken(); std::vector> Args; if (CurTok != ')') { while (true) { if (auto Arg = ParseExpression()) Args.push_back(std::move(Arg)); else return nullptr; if (CurTok == ')') break; if (CurTok != ',') { fprintf(stderr, "Error: Expected ',' or ')' in %s\n", FuncName.c_str()); return nullptr; } getNextToken(); } } getNextToken(); return std::make_unique(FuncName, std::move(Args)); } std::unique_ptr Parser::ParseParenExpr() { getNextToken(); auto V = ParseExpression(); if (!V) return nullptr; if (CurTok != ')') { fprintf(stderr, "Error: expected ')'\n"); return nullptr; } getNextToken(); return V; } std::unique_ptr Parser::ParsePrimary() { switch (CurTok) { case tok_identifier: return ParseIdentifierExpr(); case tok_number_int: return ParseNumberExpr(); case tok_number_real: return ParseNumberExpr(); case tok_string_literal: { auto Res = std::make_unique(Lex.StringVal); getNextToken(); return Res; } case tok_length: return ParseStringBuiltin("LENGTH"); case tok_mid: return ParseStringBuiltin("MID"); case tok_right: return ParseStringBuiltin("RIGHT"); case tok_left: return ParseStringBuiltin("LEFT"); case tok_lcase: return ParseStringBuiltin("LCASE"); case tok_ucase: return ParseStringBuiltin("UCASE"); case tok_true: { getNextToken(); return std::make_unique(true); } case tok_false: { getNextToken(); return std::make_unique(false); } case '(': return ParseParenExpr(); default: fprintf(stderr, "Error: unknown token '%c' (%d) at line %d when expecting an expression\n", (char)CurTok, CurTok, Lex.getLine()); return nullptr; } } std::unique_ptr Parser::ParseUnary() { if (CurTok == tok_not) { getNextToken(); auto Operand = ParseUnary(); if (!Operand) return nullptr; return std::make_unique(tok_not, std::move(Operand)); } return ParsePrimary(); } std::unique_ptr Parser::ParseBinOpRHS(int ExprPrec, std::unique_ptr LHS) { while (true) { int TokPrec = GetTokPrecedence(); if (TokPrec < ExprPrec) return LHS; int BinOp = CurTok; int Line = Lex.getLine(); getNextToken(); auto RHS = ParseUnary(); if (!RHS) return nullptr; int NextPrec = GetTokPrecedence(); if (TokPrec < NextPrec) { RHS = ParseBinOpRHS(TokPrec + 1, std::move(RHS)); if (!RHS) return nullptr; } LHS = std::make_unique(BinOp, std::move(LHS), std::move(RHS), Line); } } std::unique_ptr Parser::ParseExpression() { auto LHS = ParseUnary(); if (!LHS) return nullptr; return ParseBinOpRHS(0, std::move(LHS)); } std::vector> Parser::Parse() { std::vector> Statements; while (CurTok != tok_eof) { if (auto Stmt = ParseStatement()) { Statements.push_back(std::move(Stmt)); } else { if (CurTok != tok_eof) getNextToken(); } } return Statements; } std::unique_ptr Parser::ParseDeclare() { getNextToken(); if (CurTok != tok_identifier) return nullptr; std::string Name = Lex.IdentifierStr; getNextToken(); if (CurTok != tok_colon) return nullptr; getNextToken(); if (CurTok == tok_array) { getNextToken(); if (CurTok != '[') { fprintf(stderr, "Error: Expected '[' after ARRAY\n"); return nullptr; } getNextToken(); std::vector, std::unique_ptr>> Bounds; while (true) { auto Lower = ParseExpression(); if (!Lower) return nullptr; if (CurTok != tok_colon) { fprintf(stderr, "Error: Expected ':' in array range (e.g. 1:10)\n"); return nullptr; } getNextToken(); auto Upper = ParseExpression(); if (!Upper) return nullptr; Bounds.push_back({std::move(Lower), std::move(Upper)}); if (CurTok == ']') break; if (CurTok == ',') { getNextToken(); continue; } fprintf(stderr, "Error: Expected ',' or ']' in array dims\n"); return nullptr; } getNextToken(); if (CurTok != tok_of) { fprintf(stderr, "Error: Expected OF after array dims\n"); return nullptr; } getNextToken(); if (CurTok != tok_integer_kw) { fprintf(stderr, "Error: Only INTEGER arrays supported currently\n"); return nullptr; } getNextToken(); return std::make_unique(Name, std::move(Bounds), "INTEGER"); } else { std::string TypeStr; if (CurTok == tok_integer_kw) TypeStr = "INTEGER"; else if (CurTok == tok_real_kw) TypeStr = "REAL"; else if (CurTok == tok_boolean_kw) TypeStr = "BOOLEAN"; else if (CurTok == tok_string_kw) TypeStr = "STRING"; else { fprintf(stderr, "Error: Unknown type in declaration\n"); return nullptr; } getNextToken(); return std::make_unique(Name, TypeStr); } } std::unique_ptr Parser::ParseIfStmt() { getNextToken(); auto Cond = ParseExpression(); if (!Cond) return nullptr; if (CurTok != tok_then) { fprintf(stderr, "Error: expected THEN\n"); return nullptr; } getNextToken(); std::vector> ThenStmts; while (CurTok != tok_else && CurTok != tok_endif && CurTok != tok_eof) { auto Stmt = ParseStatement(); if (Stmt) ThenStmts.push_back(std::move(Stmt)); else if (CurTok != tok_eof && CurTok != tok_else && CurTok != tok_endif) getNextToken(); } std::vector> ElseStmts; if (CurTok == tok_else) { getNextToken(); while (CurTok != tok_endif && CurTok != tok_eof) { auto Stmt = ParseStatement(); if (Stmt) ElseStmts.push_back(std::move(Stmt)); else if (CurTok != tok_eof && CurTok != tok_endif) getNextToken(); } } if (CurTok != tok_endif) { fprintf(stderr, "Error: expected ENDIF\n"); return nullptr; } getNextToken(); return std::make_unique(std::move(Cond), std::move(ThenStmts), std::move(ElseStmts)); } std::unique_ptr Parser::ParseWhileStmt() { getNextToken(); auto Cond = ParseExpression(); if (!Cond) return nullptr; if (CurTok != tok_do) { fprintf(stderr, "Error: expected DO after WHILE condition\n"); return nullptr; } getNextToken(); std::vector> Body; while (CurTok != tok_endwhile && CurTok != tok_eof) { auto Stmt = ParseStatement(); if (Stmt) Body.push_back(std::move(Stmt)); else if (CurTok != tok_eof && CurTok != tok_endwhile) getNextToken(); } if (CurTok != tok_endwhile) { fprintf(stderr, "Error: expected ENDWHILE\n"); return nullptr; } getNextToken(); return std::make_unique(std::move(Cond), std::move(Body)); } std::unique_ptr Parser::ParseRepeatStmt() { getNextToken(); std::vector> Body; while (CurTok != tok_until && CurTok != tok_eof) { auto Stmt = ParseStatement(); if (Stmt) Body.push_back(std::move(Stmt)); else if (CurTok != tok_eof && CurTok != tok_until) getNextToken(); } if (CurTok != tok_until) { fprintf(stderr, "Error: expected UNTIL\n"); return nullptr; } getNextToken(); auto Cond = ParseExpression(); if (!Cond) return nullptr; return std::make_unique(std::move(Body), std::move(Cond)); } std::unique_ptr Parser::ParseForStmt() { getNextToken(); if (CurTok != tok_identifier) { fprintf(stderr, "Error: expected identifier after FOR\n"); return nullptr; } std::string VarName = Lex.IdentifierStr; getNextToken(); if (CurTok != tok_assign) { fprintf(stderr, "Error: expected '<-' in FOR loop\n"); return nullptr; } getNextToken(); auto Start = ParseExpression(); if (!Start) return nullptr; if (CurTok != tok_to) { fprintf(stderr, "Error: expected TO in FOR loop\n"); return nullptr; } getNextToken(); auto End = ParseExpression(); if (!End) return nullptr; std::unique_ptr Step = nullptr; if (CurTok == tok_step) { getNextToken(); Step = ParseExpression(); if (!Step) return nullptr; } std::vector> Body; while (CurTok != tok_next && CurTok != tok_eof) { auto Stmt = ParseStatement(); if (Stmt) Body.push_back(std::move(Stmt)); else if (CurTok != tok_eof && CurTok != tok_next) getNextToken(); } if (CurTok != tok_next) { fprintf(stderr, "Error: expected NEXT\n"); return nullptr; } getNextToken(); if (CurTok != tok_identifier) { fprintf(stderr, "Error: expected identifier after NEXT (e.g., NEXT %s)\n", VarName.c_str()); return nullptr; } if (Lex.IdentifierStr != VarName) { fprintf(stderr, "Error: NEXT identifier '%s' does not match FOR variable '%s'\n", Lex.IdentifierStr.c_str(), VarName.c_str()); return nullptr; } getNextToken(); return std::make_unique(VarName, std::move(Start), std::move(End), std::move(Step), std::move(Body)); } std::unique_ptr Parser::ParseStatement() { if (CurTok == tok_declare) { return ParseDeclare(); } else if (CurTok == tok_identifier) { std::string Name = Lex.IdentifierStr; int Line = Lex.getLine(); getNextToken(); if (CurTok == '[') { getNextToken(); std::vector> Indices; while (true) { auto Exp = ParseExpression(); if (!Exp) return nullptr; Indices.push_back(std::move(Exp)); if (CurTok == ']') break; if (CurTok == ',') getNextToken(); } getNextToken(); if (CurTok != tok_assign) { fprintf(stderr, "Error: Expected '<-' after array access in assignment\n"); return nullptr; } getNextToken(); auto Expr = ParseExpression(); if (!Expr) return nullptr; return std::make_unique(Name, std::move(Indices), std::move(Expr), Line); } if (CurTok != tok_assign) return nullptr; getNextToken(); auto Expr = ParseExpression(); if (!Expr) return nullptr; return std::make_unique(Name, std::move(Expr)); } else if (CurTok == tok_input) { getNextToken(); if (CurTok != tok_identifier) return nullptr; std::string Name = Lex.IdentifierStr; getNextToken(); return std::make_unique(Name); } else if (CurTok == tok_output) { getNextToken(); auto Expr = ParseExpression(); if (!Expr) return nullptr; return std::make_unique(std::move(Expr)); } else if (CurTok == tok_if) { return ParseIfStmt(); } else if (CurTok == tok_while) { return ParseWhileStmt(); } else if (CurTok == tok_repeat) { return ParseRepeatStmt(); } else if (CurTok == tok_for) { return ParseForStmt(); } else if (CurTok == tok_function) { return ParseFunction(); } else if (CurTok == tok_procedure) { return ParseProcedure(); } else if (CurTok == tok_call) { return ParseCallStmt(); } else if (CurTok == tok_return) { return ParseReturnStmt(); } return nullptr; }