aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author_ov4 <ov4@ov4.org>2026-10-17 09:09:54 +0000
committer_ov4 <ov4@ov4.org>2026-10-17 09:09:54 +0000
commit59a2bb6acb975d820ab29be63a6f909d6e6ef40f (patch)
treeac87916075e9e5a9f166b14fea0b39864d801166
parentdc645a36aaade7087ade574cefe69ce7bb29753e (diff)
feat(parser): parse INCLUDE and GLOBAL blocks
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
-rw-r--r--include/cps/AST.h15
-rw-r--r--include/cps/Lexer.h2
-rw-r--r--lib/CodeGen/StatementGen.cc5
-rw-r--r--lib/Lexer/Lexer.cc3
-rw-r--r--lib/Parser/Parser.cc32
5 files changed, 57 insertions, 0 deletions
diff --git a/include/cps/AST.h b/include/cps/AST.h
index f20b106..8c8c3be 100644
--- a/include/cps/AST.h
+++ b/include/cps/AST.h
@@ -100,6 +100,21 @@ public:
virtual ~StmtAST() = default;
};
+class IncludeStmtAST : public StmtAST {
+ std::string Path;
+public:
+ explicit IncludeStmtAST(std::string Path) : Path(std::move(Path)) {}
+ const std::string &getPath() const { return Path; }
+};
+
+class GlobalBlockAST : public StmtAST {
+ std::vector<std::unique_ptr<StmtAST>> Body;
+public:
+ explicit GlobalBlockAST(std::vector<std::unique_ptr<StmtAST>> Body)
+ : Body(std::move(Body)) {}
+ const auto &getBody() const { return Body; }
+};
+
class TryStmtAST : public StmtAST {
std::vector<std::unique_ptr<StmtAST>> Body, CatchBody;
public:
diff --git a/include/cps/Lexer.h b/include/cps/Lexer.h
index b465591..957ca48 100644
--- a/include/cps/Lexer.h
+++ b/include/cps/Lexer.h
@@ -101,6 +101,8 @@ enum Token {
tok_c_double = -612,
tok_new = -613, tok_delete = -614,
+ tok_include = -650, tok_global = -651, tok_endglobal = -652,
+
tok_try = -700,
tok_catch = -701,
tok_endtry = -702,
diff --git a/lib/CodeGen/StatementGen.cc b/lib/CodeGen/StatementGen.cc
index df8c396..529f7f0 100644
--- a/lib/CodeGen/StatementGen.cc
+++ b/lib/CodeGen/StatementGen.cc
@@ -13,6 +13,11 @@ void CodeGen::emitStmt(StmtAST *Stmt) {
SaveAndRestore<int> Location(DiagnosticLine, Stmt && Stmt->getLine() ? Stmt->getLine() : DiagnosticLine);
if (!Stmt) return;
+ if (dynamic_cast<IncludeStmtAST*>(Stmt) || dynamic_cast<GlobalBlockAST*>(Stmt)) {
+ reportError("INCLUDE and GLOBAL are not supported yet");
+ return;
+ }
+
if (auto *Class = dynamic_cast<ClassTypeDeclAST*>(Stmt)) {
for (const auto &Method : Class->getMethods()) {
// Invalid or duplicate members have already been diagnosed.
diff --git a/lib/Lexer/Lexer.cc b/lib/Lexer/Lexer.cc
index acdedd0..44d40e5 100644
--- a/lib/Lexer/Lexer.cc
+++ b/lib/Lexer/Lexer.cc
@@ -74,6 +74,9 @@ int Lexer::readToken() {
IdentifierStr += static_cast<char>(LastChar);
if (IdentifierStr == "CONSTANT") return tok_constant;
+ if (IdentifierStr == "INCLUDE") return tok_include;
+ if (IdentifierStr == "GLOBAL") return tok_global;
+ if (IdentifierStr == "ENDGLOBAL") return tok_endglobal;
if (IdentifierStr == "DECLARE") return tok_declare;
if (IdentifierStr == "INTEGER") return tok_integer_kw;
if (IdentifierStr == "BOOLEAN") return tok_boolean_kw;
diff --git a/lib/Parser/Parser.cc b/lib/Parser/Parser.cc
index 826bc89..d4dd18e 100644
--- a/lib/Parser/Parser.cc
+++ b/lib/Parser/Parser.cc
@@ -46,6 +46,7 @@ std::vector<std::unique_ptr<StmtAST>> Parser::Parse() {
void Parser::syncToStatementStart() {
while (CurTok != tok_eof) {
switch (CurTok) {
+ case tok_include: case tok_global: case tok_endglobal:
case tok_delete: case tok_constant: case tok_declare: case tok_identifier: case tok_input: case tok_output:
case tok_case: case tok_endcase: case tok_otherwise:
case tok_if: case tok_while: case tok_repeat: case tok_for:
@@ -95,6 +96,37 @@ std::unique_ptr<StmtAST> Parser::ParseStatement() {
}
std::unique_ptr<StmtAST> Parser::ParseStatementImpl() {
+ if (CurTok == tok_include || CurTok == tok_global) {
+ bool Include = CurTok == tok_include;
+ int Line = Lex.getLine();
+ getNextToken();
+ if (BlockDepth != 1) {
+ sourceDiagnostic(Line, "error: %s is only allowed at top level at line %d\n",
+ Include ? "INCLUDE" : "GLOBAL", Line);
+ return nullptr;
+ }
+ if (Include) {
+ if (CurTok != tok_string_literal) {
+ sourceDiagnostic(Line, "error: INCLUDE requires a string literal at line %d\n", Line);
+ return nullptr;
+ }
+ auto Stmt = std::make_unique<IncludeStmtAST>(Lex.StringVal);
+ getNextToken();
+ return Stmt;
+ }
+ auto Body = ParseBlock({tok_endglobal});
+ if (CurTok != tok_endglobal) {
+ sourceDiagnostic(Line, "error: Expected ENDGLOBAL at line %d\n", Lex.getLine());
+ return nullptr;
+ }
+ getNextToken();
+ return std::make_unique<GlobalBlockAST>(std::move(Body));
+ }
+ if (CurTok == tok_endglobal) {
+ sourceDiagnostic(Lex.getLine(), "error: ENDGLOBAL without matching GLOBAL at line %d\n", Lex.getLine());
+ getNextToken();
+ return nullptr;
+ }
if (CurTok == tok_delete) {
int Line = Lex.getLine();
getNextToken();