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 | |
| 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')
| -rw-r--r-- | lib/Parser/Parser.cc | 484 | ||||
| -rw-r--r-- | lib/Parser/ParserControlFlow.cc | 146 | ||||
| -rw-r--r-- | lib/Parser/ParserExpression.cc | 237 | ||||
| -rw-r--r-- | lib/Parser/ParserType.cc | 115 |
4 files changed, 498 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; diff --git a/lib/Parser/ParserControlFlow.cc b/lib/Parser/ParserControlFlow.cc new file mode 100644 index 0000000..cb32466 --- /dev/null +++ b/lib/Parser/ParserControlFlow.cc @@ -0,0 +1,146 @@ +#include "cps/Parser.h" +#include "cps/FunctionAST.h" +#include <cstdio> + +using namespace cps; + +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)); +} diff --git a/lib/Parser/ParserExpression.cc b/lib/Parser/ParserExpression.cc new file mode 100644 index 0000000..3e2665f --- /dev/null +++ b/lib/Parser/ParserExpression.cc @@ -0,0 +1,237 @@ +#include "cps/Parser.h" +#include "cps/FunctionAST.h" +#include <cstdio> + +using namespace cps; + +int Parser::GetTokPrecedence() { + if (BinopPrecedence.find(CurTok) == BinopPrecedence.end()) return -1; + int TokPrec = BinopPrecedence[CurTok]; + if (TokPrec <= 0) return -1; + return TokPrec; +} + + +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::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::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; +} diff --git a/lib/Parser/ParserType.cc b/lib/Parser/ParserType.cc index de1f3ea..6c7703c 100644 --- a/lib/Parser/ParserType.cc +++ b/lib/Parser/ParserType.cc @@ -182,3 +182,118 @@ bool Parser::ParseRecordField(std::vector<RecordFieldDecl> &Out, bool IsPublic) Out.push_back({FieldName, TypeName, IsPublic}); 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<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); + } +} |
