From 52e43ea1e2ab599dd94516eca26b545f3ff72a6f Mon Sep 17 00:00:00 2001 From: Sofia Date: Tue, 28 Apr 2026 01:34:52 +0300 Subject: [PATCH] Move ; parsing upper down the line --- src/ast.h | 9 +++---- src/codegen.cpp | 2 +- src/parsing.cpp | 66 ++++++++++++++++++++++++++++++++++++++++--------- src/tokens.cpp | 5 ++++ src/tokens.h | 1 + test.c | 4 --- 6 files changed, 65 insertions(+), 22 deletions(-) diff --git a/src/ast.h b/src/ast.h index 5639d1f..11db249 100644 --- a/src/ast.h +++ b/src/ast.h @@ -435,11 +435,10 @@ namespace AST { std::unique_ptr m_loop; public: ForStatement(token::Metadata meta, - std::unique_ptr init, - std::unique_ptr cond, - std::unique_ptr after, - std::unique_ptr loop, - std::optional> else_statement) + std::optional> init, + std::optional> cond, + std::optional> after, + std::unique_ptr loop) : Statement{ meta } , m_init{ std::move(init) } , m_cond{ std::move(cond) } diff --git a/src/codegen.cpp b/src/codegen.cpp index 1e7b560..10b348e 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -557,7 +557,7 @@ namespace AST { builder.builder->SetInsertPoint(after_block); } - void ForStatement::codegen(codegen::Builder& builder, codegen::Scope& scope, codegen::StackAllocator& allocator) { + void ForStatement::codegen(codegen::Builder& builder, codegen::Scope&, codegen::StackAllocator&) { if (!builder.block) return; diff --git a/src/parsing.cpp b/src/parsing.cpp index 8210bd1..3c20e3f 100644 --- a/src/parsing.cpp +++ b/src/parsing.cpp @@ -510,8 +510,6 @@ namespace parsing { expr = parse_expression(inner, scope).unwrap(); } - inner.expect(token::Type::Symbol, ";"); - stream.m_position = inner.m_position; auto init = new AST::InitializationStatement{ before_meta + inner.metadata(), std::move(ty), name.content, std::move(expr) }; return std::unique_ptr{ init }; @@ -521,19 +519,18 @@ namespace parsing { } } - Result, std::string> parse_statement(token::TokenStream& stream, Scope& scope) { + Result, bool>, std::string> parse_statement(token::TokenStream& stream, Scope& scope) { token::TokenStream inner{ stream }; auto before_meta = inner.metadata(); try { if (inner.peek().type == token::Type::ReturnKeyword) { inner.next(); auto expression = parse_expression(inner, scope).unwrap(); - inner.expect(token::Type::Symbol, ";"); stream.m_position = inner.m_position; auto ret = new AST::ReturnStatement{ before_meta + stream.metadata(),std::move(expression) }; - return std::unique_ptr{ ret }; + return std::pair{ std::unique_ptr{ ret }, true }; } else if (inner.peek().type == token::Type::IfKeyword) { inner.next(); @@ -541,11 +538,18 @@ namespace parsing { auto expression = parse_expression(inner, scope).unwrap(); inner.expect(token::Type::Symbol, ")"); - auto then_statement = parse_statement(inner, scope).unwrap(); + auto then_res = parse_statement(inner, scope).unwrap(); + if (then_res.second) + inner.expect(token::Type::Symbol, ";"); + auto then_statement = std::move(then_res.first); + std::optional> else_statement{}; if (inner.peek().type == token::Type::ElseKeyword) { inner.next(); - else_statement = parse_statement(inner, scope).unwrap(); + auto else_res = parse_statement(inner, scope).unwrap(); + if (else_res.second) + inner.expect(token::Type::Symbol, ";"); + else_statement = std::move(else_res.first); } stream.m_position = inner.m_position; @@ -556,17 +560,52 @@ namespace parsing { std::move(then_statement), std::move(else_statement) }; - return std::unique_ptr{ statement }; + return std::pair{ std::unique_ptr{ statement }, false }; + } + else if (inner.peek().type == token::Type::ForKeyword) { + inner.next(); + inner.expect(token::Type::Symbol, "("); + + std::optional> init; + std::optional> cond; + std::optional> after; + + if (inner.peek().content != ";") + init = parse_statement(inner, scope).unwrap().first; + inner.expect(token::Type::Symbol, ";"); + + if (inner.peek().content != ";") + cond = parse_expression(inner, scope).unwrap(); + inner.expect(token::Type::Symbol, ";"); + + if (inner.peek().content != ")") + after = parse_expression(inner, scope).unwrap(); + inner.expect(token::Type::Symbol, ")"); + + auto loop_res = parse_statement(inner, scope).unwrap(); + if (loop_res.second) + inner.expect(token::Type::Symbol, ";"); + auto loop = std::move(loop_res.first); + + stream.m_position = inner.m_position; + + auto statement = new AST::ForStatement{ + before_meta + stream.metadata(), + std::move(init), + std::move(cond), + std::move(after), + std::move(loop), + }; + return std::pair{ std::unique_ptr{ statement }, false }; } else if (auto init = parse_init_statement(inner, scope); init.ok()) { stream.m_position = inner.m_position; - return std::unique_ptr{ init.unwrap() }; + return std::pair{ std::unique_ptr{ init.unwrap() }, true }; } else if (auto expr = parse_expression(inner, scope); expr.ok()) { stream.m_position = inner.m_position; - stream.expect(token::Type::Symbol, ";"); auto expr_statement = new AST::ExpressionStatement{ before_meta + stream.metadata(), expr.unwrap() }; - return std::unique_ptr{ expr_statement }; + return std::pair{ std::unique_ptr{ expr_statement }, true }; } else { throw std::runtime_error("Expected return-keyword"); @@ -639,7 +678,10 @@ namespace parsing { auto statement = parse_statement(inner, inner_scope); while (statement.ok()) { - statement_list.push_back(statement.unwrap()); + auto statement_res = statement.unwrap(); + if (statement_res.second) + inner.expect(token::Type::Symbol, ";"); + statement_list.push_back(std::move(statement_res.first)); statement = parse_statement(inner, inner_scope); } diff --git a/src/tokens.cpp b/src/tokens.cpp index f655ab5..96395a1 100644 --- a/src/tokens.cpp +++ b/src/tokens.cpp @@ -59,6 +59,8 @@ namespace token { return "If"; case token::Type::ElseKeyword: return "Else"; + case token::Type::ForKeyword: + return "For"; case token::Type::Whitespace: return "Whitespace"; @@ -222,6 +224,9 @@ namespace token { else if (content == "else") { type = token::Type::ElseKeyword; } + else if (content == "for") { + type = token::Type::ForKeyword; + } tokens.push_back(token::Token{ type, content, meta + content.size() }); } else if (iswhitespace(c)) { diff --git a/src/tokens.h b/src/tokens.h index a52fd6d..619fa7b 100644 --- a/src/tokens.h +++ b/src/tokens.h @@ -16,6 +16,7 @@ namespace token { ReturnKeyword, IfKeyword, ElseKeyword, + ForKeyword, Whitespace, diff --git a/test.c b/test.c index 63b7d6b..439473d 100644 --- a/test.c +++ b/test.c @@ -51,9 +51,5 @@ int main() { twod_array[0][0] = 50; printf("2d array: %d!\n", twod_array[0][0]); - for (int counter = 0; counter < 10; counter++) { - printf("counter: %d\n", counter); - } - return 0; } \ No newline at end of file