diff options
| author | _ov4 <ov4@ov4.org> | 2026-10-16 09:41:13 +0000 |
|---|---|---|
| committer | _ov4 <ov4@ov4.org> | 2026-10-16 09:41:13 +0000 |
| commit | db6ac29d0ac769ff780f3901ed987b97965f3f5e (patch) | |
| tree | c7d5f4b06712aefa2a885f338143aec9fe68e322 /lib/Parser/Parser.cc | |
| parent | 7ee2b877cf396e680582b4a2d6094d4f3ad89abb (diff) | |
refactor(parser): split expression and control flow parsing
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Diffstat (limited to 'lib/Parser/Parser.cc')
| -rw-r--r-- | lib/Parser/Parser.cc | 484 |
1 files changed, 0 insertions, 484 deletions
diff --git a/lib/Parser/Parser.cc b/lib/Parser/Parser.cc index db2790b..3e8a096 100644 --- a/lib/Parser/Parser.cc +++ b/lib/Parser/Parser.cc @@ -28,258 +28,10 @@ Parser::Parser(Lexer &L) : Lex(L) { 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<ExprAST> Parser::ParseNumberExpr() { - if (CurTok == tok_number_real) { - auto Result = std::make_unique<RealExprAST>(Lex.RealVal); - getNextToken(); - return Result; - } - auto Result = std::make_unique<IntegerExprAST>(Lex.NumVal); - getNextToken(); - return Result; -} - -std::unique_ptr<ExprAST> Parser::ParseIdentifierExpr() { - std::string IdName = Lex.IdentifierStr; - int Line = Lex.getLine(); - getNextToken(); - - if (CurTok == '(') { - getNextToken(); - auto Args = ParseExprList(')', true); - if (!Args) return nullptr; - if (CurTok == '[' || CurTok == '.' || CurTok == '^') { - fprintf(stderr, "error: record/array/pointer access on a function result is not supported at line %d\n", - Lex.getLine()); - return nullptr; - } - return std::make_unique<CallExprAST>(IdName, std::move(*Args), Line); - } - - std::vector<DesignatorAccess> Accesses; - if (!ParseDesignatorSuffix(Accesses)) return nullptr; - - // Degrade rule: shapes that existed before designators keep their nodes. - if (Accesses.empty()) - return std::make_unique<VariableExprAST>(IdName); - if (Accesses.size() == 1 && Accesses[0].Kind == AccessKind::Index) - return std::make_unique<ArrayAccessExprAST>(IdName, std::move(Accesses[0].Indices), Line); - return std::make_unique<DesignatorExprAST>(IdName, std::move(Accesses), Line); -} - -// Postfix accessor chain after an identifier: '[' exprs ']' | '.' IDENT | '^' -bool Parser::ParseDesignatorSuffix(std::vector<DesignatorAccess> &Out) { - while (true) { - if (CurTok == '[') { - getNextToken(); - auto Indices = ParseExprList(']', false); - if (!Indices) return false; - DesignatorAccess A; - A.Kind = AccessKind::Index; - A.Indices = std::move(*Indices); - Out.push_back(std::move(A)); - } else if (CurTok == '.') { - getNextToken(); - if (CurTok != tok_identifier) { - fprintf(stderr, "error: Expected field name after '.' at line %d\n", Lex.getLine()); - return false; - } - DesignatorAccess A; - A.Kind = AccessKind::Field; - A.FieldName = Lex.IdentifierStr; - Out.push_back(std::move(A)); - getNextToken(); - } else if (CurTok == '^') { - getNextToken(); - DesignatorAccess A; - A.Kind = AccessKind::Deref; - Out.push_back(std::move(A)); - } else { - return true; - } - } -} - -std::string Parser::ParseTypeName(bool AllowVoid) { - switch (CurTok) { - case tok_c_int: getNextToken(); return "C_INT"; - case tok_c_char: getNextToken(); return "C_CHAR"; - case tok_c_string: getNextToken(); return "C_STRING"; - case tok_c_double: getNextToken(); return "C_DOUBLE"; - default: break; - } - if (CurTok == tok_integer_kw) { - getNextToken(); - return "INTEGER"; - } - if (CurTok == tok_real_kw) { - getNextToken(); - return "REAL"; - } - if (CurTok == tok_boolean_kw) { - getNextToken(); - return "BOOLEAN"; - } - if (CurTok == tok_string_kw) { - getNextToken(); - return "STRING"; - } - if (CurTok == tok_char_kw) { - getNextToken(); - return "CHAR"; - } - if (CurTok == tok_identifier) { - std::string TypeName = Lex.IdentifierStr; - if (!AllowVoid && TypeName == "VOID") { - fprintf(stderr, "error: VOID is not allowed here\n"); - return ""; - } - getNextToken(); - return TypeName; - } - - fprintf(stderr, "error: Unknown type name\n"); - return ""; -} - -std::unique_ptr<ExprAST> Parser::ParseParenExpr() { - getNextToken(); - bool IsType = CurTok == tok_integer_kw || CurTok == tok_real_kw || - CurTok == tok_boolean_kw || CurTok == tok_string_kw || CurTok == tok_char_kw || - CurTok == tok_c_int || CurTok == tok_c_char || CurTok == tok_c_string || - CurTok == tok_c_double || - (CurTok == tok_identifier && TypeNames.count(Lex.IdentifierStr)); - if (IsType) { - std::string TypeName = ParseTypeName(); - if (TypeName.empty()) return nullptr; - if (CurTok != ')') { - fprintf(stderr, "error: Expected ')' after cast type at line %d\n", Lex.getLine()); - return nullptr; - } - getNextToken(); - auto Operand = ParseUnary(); - if (!Operand) return nullptr; - return std::make_unique<CastExprAST>(TypeName, std::move(Operand)); - } - auto V = ParseExpression(); - if (!V) return nullptr; - if (CurTok != ')') { - fprintf(stderr, "error: expected ')'\n"); - return nullptr; - } - getNextToken(); - return V; -} - -std::unique_ptr<ExprAST> 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<StringExprAST>(Lex.StringVal); - getNextToken(); - return Res; - } - case tok_char_literal: { - auto Res = std::make_unique<CharExprAST>(Lex.CharVal); - getNextToken(); - return Res; - } - case tok_true: { - getNextToken(); - return std::make_unique<BooleanExprAST>(true); - } - case tok_false: { - getNextToken(); - return std::make_unique<BooleanExprAST>(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<ExprAST> Parser::ParseUnary() { - if (CurTok == tok_not) { - getNextToken(); - auto Operand = ParseUnary(); - if (!Operand) return nullptr; - return std::make_unique<UnaryExprAST>(tok_not, std::move(Operand)); - } - - // ^<designator> — address-of; the operand must be an lvalue shape. - if (CurTok == '^') { - int Line = Lex.getLine(); - getNextToken(); - if (CurTok != tok_identifier) { - fprintf(stderr, "error: '^' (address-of) requires a variable, array element or record field at line %d\n", - Line); - return nullptr; - } - std::string BaseName = Lex.IdentifierStr; - getNextToken(); - if (CurTok == '(') { - fprintf(stderr, "error: cannot take the address of a function result at line %d\n", Line); - return nullptr; - } - std::vector<DesignatorAccess> Accesses; - if (!ParseDesignatorSuffix(Accesses)) return nullptr; - auto Target = std::make_unique<DesignatorExprAST>(BaseName, std::move(Accesses), Line); - return std::make_unique<AddrOfExprAST>(std::move(Target)); - } - - if (CurTok == '-') { - getNextToken(); - auto Operand = ParseUnary(); - if (!Operand) return nullptr; - return std::make_unique<UnaryExprAST>('-', std::move(Operand)); - } - - return ParsePrimary(); -} - -std::unique_ptr<ExprAST> Parser::ParseBinOpRHS(int ExprPrec, std::unique_ptr<ExprAST> 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<BinaryExprAST>(BinOp, std::move(LHS), std::move(RHS), Line); - } -} - -std::unique_ptr<ExprAST> Parser::ParseExpression() { - auto LHS = ParseUnary(); - if (!LHS) return nullptr; - return ParseBinOpRHS(0, std::move(LHS)); -} - std::vector<std::unique_ptr<StmtAST>> Parser::Parse() { return ParseBlock({}); } @@ -327,242 +79,6 @@ std::vector<std::unique_ptr<StmtAST>> Parser::ParseBlock(std::initializer_list<i return Body; } -std::optional<std::vector<std::unique_ptr<ExprAST>>> Parser::ParseExprList(char CloseDelim, bool AllowEmpty) { - std::vector<std::unique_ptr<ExprAST>> Elems; - if (AllowEmpty && CurTok == CloseDelim) { - getNextToken(); - return Elems; - } - - while (true) { - auto E = ParseExpression(); - if (!E) return std::nullopt; - Elems.push_back(std::move(E)); - - if (CurTok == CloseDelim) break; - if (CurTok != ',') { - fprintf(stderr, "error: Expected ',' or '%c' at line %d\n", CloseDelim, Lex.getLine()); - return std::nullopt; - } - getNextToken(); - } - getNextToken(); - return Elems; -} - -std::unique_ptr<StmtAST> Parser::ParseDeclare() { - getNextToken(); - if (CurTok != tok_identifier) { - fprintf(stderr, "error: Expected identifier after DECLARE at line %d\n", Lex.getLine()); - return nullptr; - } - std::string Name = Lex.IdentifierStr; - getNextToken(); - - if (CurTok != tok_colon) { - fprintf(stderr, "error: Expected ':' after variable name '%s' at line %d\n", Name.c_str(), Lex.getLine()); - return nullptr; - } - getNextToken(); - - if (CurTok == tok_array) { - getNextToken(); - if (CurTok != '[') { - fprintf(stderr, "error: Expected '[' after ARRAY\n"); - return nullptr; - } - getNextToken(); - - std::vector<std::pair<std::unique_ptr<ExprAST>, std::unique_ptr<ExprAST>>> 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(); - - std::string TypeStr = ParseTypeName(false); - if (TypeStr.empty()) { - return nullptr; - } - - return std::make_unique<ArrayDeclareStmtAST>(Name, std::move(Bounds), TypeStr); - } - else { - std::string TypeStr = ParseTypeName(false); - if (TypeStr.empty()) { - return nullptr; - } - return std::make_unique<DeclareStmtAST>(Name, TypeStr); - } -} - -std::unique_ptr<StmtAST> Parser::ParseTryStmt() { - getNextToken(); - auto Body = ParseBlock({tok_catch, tok_endtry}); - if (CurTok != tok_catch) { - fprintf(stderr, "error: Expected CATCH in TRY at line %d\n", Lex.getLine()); - return nullptr; - } - getNextToken(); - auto CatchBody = ParseBlock({tok_endtry, tok_catch}); - if (CurTok != tok_endtry) { - fprintf(stderr, "error: Expected ENDTRY after CATCH at line %d\n", Lex.getLine()); - return nullptr; - } - getNextToken(); - return std::make_unique<TryStmtAST>(std::move(Body), std::move(CatchBody)); -} - -std::unique_ptr<StmtAST> 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<std::unique_ptr<StmtAST>> ThenStmts = ParseBlock({tok_else, tok_endif}); - - std::vector<std::unique_ptr<StmtAST>> ElseStmts; - if (CurTok == tok_else) { - getNextToken(); - ElseStmts = ParseBlock({tok_endif}); - } - - if (CurTok != tok_endif) { - fprintf(stderr, "error: expected ENDIF\n"); - return nullptr; - } - getNextToken(); - - return std::make_unique<IfStmtAST>(std::move(Cond), std::move(ThenStmts), std::move(ElseStmts)); -} - -std::unique_ptr<StmtAST> 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<std::unique_ptr<StmtAST>> Body = ParseBlock({tok_endwhile}); - - if (CurTok != tok_endwhile) { - fprintf(stderr, "error: expected ENDWHILE\n"); - return nullptr; - } - getNextToken(); - - return std::make_unique<WhileStmtAST>(std::move(Cond), std::move(Body)); -} - -std::unique_ptr<StmtAST> Parser::ParseRepeatStmt() { - getNextToken(); - - std::vector<std::unique_ptr<StmtAST>> Body = ParseBlock({tok_until}); - - if (CurTok != tok_until) { - fprintf(stderr, "error: expected UNTIL\n"); - return nullptr; - } - getNextToken(); - - auto Cond = ParseExpression(); - if (!Cond) return nullptr; - - return std::make_unique<RepeatStmtAST>(std::move(Body), std::move(Cond)); -} - -std::unique_ptr<StmtAST> 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<ExprAST> Step = nullptr; - if (CurTok == tok_step) { - getNextToken(); - Step = ParseExpression(); - if (!Step) return nullptr; - } - - std::vector<std::unique_ptr<StmtAST>> Body = ParseBlock({tok_next}); - - 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<ForStmtAST>(VarName, std::move(Start), std::move(End), std::move(Step), std::move(Body)); -} - std::unique_ptr<StmtAST> Parser::ParseStatement() { auto Stmt = ParseStatementImpl(); if (!Stmt) ++NumErrors; |
