From cad64c865ae517a1d2925544e5f99ec3c414690b Mon Sep 17 00:00:00 2001 From: _ov4 Date: Thu, 22 Oct 2026 03:49:29 +0000 Subject: refactor(parser): extract INCLUDE/GLOBAL, DELETE, INPUT and OUTPUT parsing Move the self-contained arms of ParseStatementImpl into ParseIncludeOrGlobal, ParseDeleteStmt, ParseInputStmt and ParseOutputStmt without changing their bodies. Co-Authored-By: Claude Opus 5.5 --- include/cps/Parser.h | 4 ++ lib/Parser/Parser.cc | 161 ++++++++++++++++++++++++++++----------------------- 2 files changed, 93 insertions(+), 72 deletions(-) diff --git a/include/cps/Parser.h b/include/cps/Parser.h index 9bf8afb..cf27234 100644 --- a/include/cps/Parser.h +++ b/include/cps/Parser.h @@ -58,6 +58,10 @@ class Parser { std::unique_ptr ParseStatement(); std::unique_ptr ParseStatementImpl(); + std::unique_ptr ParseIncludeOrGlobal(); + std::unique_ptr ParseDeleteStmt(); + std::unique_ptr ParseInputStmt(); + std::unique_ptr ParseOutputStmt(); std::vector> ParseBlock(std::initializer_list Terminators, bool CaseBody = false); bool isCaseLabel(); bool atCaseBoundary(); diff --git a/lib/Parser/Parser.cc b/lib/Parser/Parser.cc index b81bf55..37fe8ec 100644 --- a/lib/Parser/Parser.cc +++ b/lib/Parser/Parser.cc @@ -104,54 +104,14 @@ std::unique_ptr Parser::ParseStatementImpl() { } return ParseExternDecl(); } - if (CurTok == tok_include || CurTok == tok_include_obj || CurTok == tok_global) { - const char *Keyword = CurTok == tok_include ? "INCLUDE" : CurTok == tok_include_obj ? "INCLUDE_OBJ" : "GLOBAL"; - bool Object = CurTok == tok_include_obj; - bool Include = Object || CurTok == tok_include; - int Line = Lex.getLine(); - getNextToken(); - if (BlockDepth != 1) { - sourceError(Line, "%s is only allowed at top level", Keyword); - return nullptr; - } - if (Include) { - if (CurTok != tok_string_literal) { - sourceError(Line, "%s requires a string literal", Keyword); - return nullptr; - } - std::unique_ptr Stmt; - if (Object) Stmt = std::make_unique(Lex.StringVal); - else Stmt = std::make_unique(Lex.StringVal); - getNextToken(); - return Stmt; - } - auto Body = ParseBlock({tok_endglobal}); - if (CurTok != tok_endglobal) { - sourceError(Lex.getLine(), "Expected ENDGLOBAL"); - return nullptr; - } - getNextToken(); - return std::make_unique(std::move(Body)); - } + if (CurTok == tok_include || CurTok == tok_include_obj || CurTok == tok_global) + return ParseIncludeOrGlobal(); if (CurTok == tok_endglobal) { sourceError(Lex.getLine(), "ENDGLOBAL without matching GLOBAL"); getNextToken(); return nullptr; } - if (CurTok == tok_delete) { - int Line = Lex.getLine(); - getNextToken(); - if (CurTok != tok_identifier) { - cps::sourceError(Line, "DELETE requires an object designator"); - return nullptr; - } - std::string Name = Lex.IdentifierStr; - getNextToken(); - std::vector Accesses; - if (!ParseDesignatorSuffix(Accesses)) return nullptr; - auto Target = std::make_unique(Name, std::move(Accesses), Line); - return std::make_unique(std::move(Target)); - } + if (CurTok == tok_delete) return ParseDeleteStmt(); if (CurTok == tok_case) return ParseCaseStmt(); if (CurTok == tok_endcase || CurTok == tok_otherwise) { cps::sourceError(Lex.getLine(), "Unexpected CASE terminator"); @@ -166,37 +126,10 @@ std::unique_ptr Parser::ParseStatementImpl() { return ParseAssignStmt(); } else if (CurTok == tok_input) { - getNextToken(); - if (CurTok != tok_identifier) { - cps::sourceError(Lex.getLine(), "Expected variable name after INPUT"); - return nullptr; - } - std::string Name = Lex.IdentifierStr; - int Line = Lex.getLine(); - getNextToken(); - std::vector Accesses; - if (!ParseDesignatorSuffix(Accesses)) return nullptr; - std::unique_ptr Target; - if (Accesses.empty()) - Target = std::make_unique(Name); - else if (Accesses.size() == 1 && Accesses[0].Kind == AccessKind::Index) - Target = std::make_unique(Name, std::move(Accesses[0].Indices), Line); - else - Target = std::make_unique(Name, std::move(Accesses), Line); - Target->setLine(Line); - return std::make_unique(std::move(Target)); + return ParseInputStmt(); } else if (CurTok == tok_output) { - getNextToken(); - std::vector> Exprs; - while (true) { - auto Expr = ParseExpression(); - if (!Expr) return nullptr; - Exprs.push_back(std::move(Expr)); - if (CurTok != ',') break; - getNextToken(); - } - return std::make_unique(std::move(Exprs)); + return ParseOutputStmt(); } else if (CurTok == tok_if) { return ParseIfStmt(); @@ -279,6 +212,90 @@ std::unique_ptr Parser::ParseStatementImpl() { return nullptr; } +// INCLUDE "" | INCLUDE_OBJ "" | GLOBAL ENDGLOBAL +std::unique_ptr Parser::ParseIncludeOrGlobal() { + const char *Keyword = CurTok == tok_include ? "INCLUDE" : CurTok == tok_include_obj ? "INCLUDE_OBJ" : "GLOBAL"; + bool Object = CurTok == tok_include_obj; + bool Include = Object || CurTok == tok_include; + int Line = Lex.getLine(); + getNextToken(); + if (BlockDepth != 1) { + sourceError(Line, "%s is only allowed at top level", Keyword); + return nullptr; + } + if (Include) { + if (CurTok != tok_string_literal) { + sourceError(Line, "%s requires a string literal", Keyword); + return nullptr; + } + std::unique_ptr Stmt; + if (Object) Stmt = std::make_unique(Lex.StringVal); + else Stmt = std::make_unique(Lex.StringVal); + getNextToken(); + return Stmt; + } + auto Body = ParseBlock({tok_endglobal}); + if (CurTok != tok_endglobal) { + sourceError(Lex.getLine(), "Expected ENDGLOBAL"); + return nullptr; + } + getNextToken(); + return std::make_unique(std::move(Body)); +} + +// DELETE +std::unique_ptr Parser::ParseDeleteStmt() { + int Line = Lex.getLine(); + getNextToken(); + if (CurTok != tok_identifier) { + cps::sourceError(Line, "DELETE requires an object designator"); + return nullptr; + } + std::string Name = Lex.IdentifierStr; + getNextToken(); + std::vector Accesses; + if (!ParseDesignatorSuffix(Accesses)) return nullptr; + auto Target = std::make_unique(Name, std::move(Accesses), Line); + return std::make_unique(std::move(Target)); +} + +// INPUT +std::unique_ptr Parser::ParseInputStmt() { + getNextToken(); + if (CurTok != tok_identifier) { + cps::sourceError(Lex.getLine(), "Expected variable name after INPUT"); + return nullptr; + } + std::string Name = Lex.IdentifierStr; + int Line = Lex.getLine(); + getNextToken(); + std::vector Accesses; + if (!ParseDesignatorSuffix(Accesses)) return nullptr; + std::unique_ptr Target; + if (Accesses.empty()) + Target = std::make_unique(Name); + else if (Accesses.size() == 1 && Accesses[0].Kind == AccessKind::Index) + Target = std::make_unique(Name, std::move(Accesses[0].Indices), Line); + else + Target = std::make_unique(Name, std::move(Accesses), Line); + Target->setLine(Line); + return std::make_unique(std::move(Target)); +} + +// OUTPUT {, } +std::unique_ptr Parser::ParseOutputStmt() { + getNextToken(); + std::vector> Exprs; + while (true) { + auto Expr = ParseExpression(); + if (!Expr) return nullptr; + Exprs.push_back(std::move(Expr)); + if (CurTok != ',') break; + getNextToken(); + } + return std::make_unique(std::move(Exprs)); +} + // <- // Bare-name and single-index targets degrade to their legacy nodes so the // existing assignment code paths stay untouched. -- cgit v1.3.1-4-g156e