From f094fcb376afcfac3266d9bc348a522536f6f4f2 Mon Sep 17 00:00:00 2001 From: Abdelrahman Date: Sun, 29 Jun 2025 22:03:03 +0100 Subject: [PATCH] Add block statements --- cclox_src/parser/ast_interpreter.cc | 20 ++++++++++++++++++++ cclox_src/parser/ast_interpreter.hh | 1 + cclox_src/parser/environment.cc | 9 +++++++++ cclox_src/parser/parser.cc | 15 +++++++++++++++ cclox_src/parser/parser.hh | 1 + cclox_src/parser/stmt.hh | 12 +++++++++++- 6 files changed, 57 insertions(+), 1 deletion(-) diff --git a/cclox_src/parser/ast_interpreter.cc b/cclox_src/parser/ast_interpreter.cc index c866c21..b70cc3c 100644 --- a/cclox_src/parser/ast_interpreter.cc +++ b/cclox_src/parser/ast_interpreter.cc @@ -1,8 +1,10 @@ #include "ast_interpreter.hh" +#include "environment.hh" #include "expr.hh" #include "stmt.hh" #include "../error_handler.hh" #include "../tokenizer.hh" +#include #include #include #include @@ -26,6 +28,11 @@ void AstInterpreter::execute(const Stmt &stmt) { case StmtType::EXPRESSION: return execute_expression_statement(stmt); case StmtType::PRINT: return execute_print_statement(stmt); case StmtType::VAR: return execute_var_statement(stmt); + case StmtType::BLOCK: { + std::shared_ptr<_Block> ptr = std::get>(stmt.value); + assert(ptr != nullptr); + return execute_block_statement(ptr->statements, Environment{std::make_shared(environment)}); + } } } @@ -60,6 +67,19 @@ void AstInterpreter::execute_var_statement(const Stmt &stmt) { environment.define(ptr->name.lexeme, value); } +void AstInterpreter::execute_block_statement(const std::vector &statements, Environment environment) { + Environment previous = this->environment; + + try { + this->environment = environment; + for (const auto &stmt : statements) { + execute(stmt); + } + } catch (std::exception) {} + + this->environment = previous; +} + Object AstInterpreter::evaluate(const Expr &expr) { switch (expr.type) { case ExprType::BINARY: return evaluate_binary_expression(expr); diff --git a/cclox_src/parser/ast_interpreter.hh b/cclox_src/parser/ast_interpreter.hh index eb90514..4c4455e 100644 --- a/cclox_src/parser/ast_interpreter.hh +++ b/cclox_src/parser/ast_interpreter.hh @@ -15,6 +15,7 @@ private: void execute_expression_statement(const Stmt &stmt); void execute_print_statement(const Stmt &stmt); void execute_var_statement(const Stmt &stmt); + void execute_block_statement(const std::vector &statements, Environment environment); Object evaluate(const Expr &expr); Object evaluate_binary_expression(const Expr &expr); diff --git a/cclox_src/parser/environment.cc b/cclox_src/parser/environment.cc index ac19317..67c6b37 100644 --- a/cclox_src/parser/environment.cc +++ b/cclox_src/parser/environment.cc @@ -43,6 +43,11 @@ void Environment::assign(const Token &name, const Object &value) { return; } + if (enclosing != nullptr) { + enclosing->assign(name, value); + return; + } + throw RuntimeException(name, "Undefined variable '" + name.lexeme + "'."); } @@ -51,5 +56,9 @@ Object Environment::get(const Token &name) { return values.at(name.lexeme); } + if (enclosing != nullptr) { + return enclosing->get(name); + } + throw RuntimeException(name, "Undefined variable '" + name.lexeme + "'."); } diff --git a/cclox_src/parser/parser.cc b/cclox_src/parser/parser.cc index faad05c..87565bb 100644 --- a/cclox_src/parser/parser.cc +++ b/cclox_src/parser/parser.cc @@ -46,9 +46,24 @@ Stmt Parser::statement() { return print_statement(); } + if (match({TokenType::LEFT_BRACE})) { + return Block(block_statement()); + } + return expression_statement(); } +std::vector Parser::block_statement() { + std::vector statements{}; + + while (!check(TokenType::RIGHT_BRACE) && !is_at_end()) { + statements.push_back(declaration()); + } + + consume(TokenType::RIGHT_BRACE, "Expect '}' after block."); + return statements; +} + Stmt Parser::print_statement() { Expr value{expression()}; consume(TokenType::SEMICOLON, "Expect ';' after value."); diff --git a/cclox_src/parser/parser.hh b/cclox_src/parser/parser.hh index cac4cf0..2e3c745 100644 --- a/cclox_src/parser/parser.hh +++ b/cclox_src/parser/parser.hh @@ -25,6 +25,7 @@ struct Parser { Stmt declaration(); Stmt var_declaration(); Stmt statement(); + std::vector block_statement(); Stmt print_statement(); Stmt expression_statement(); Expr expression(); diff --git a/cclox_src/parser/stmt.hh b/cclox_src/parser/stmt.hh index b437292..b772380 100644 --- a/cclox_src/parser/stmt.hh +++ b/cclox_src/parser/stmt.hh @@ -4,27 +4,32 @@ #include "expr.hh" #include #include +#include struct Stmt; struct _Expression; struct _Print; struct _Var; +struct _Block; enum class StmtType { EXPRESSION, PRINT, VAR, + BLOCK, }; using StmtVariant = std::variant< std::shared_ptr<_Expression>, std::shared_ptr<_Print>, - std::shared_ptr<_Var> + std::shared_ptr<_Var>, + std::shared_ptr<_Block> >; #define Expression(EXPR) (Stmt{StmtType::EXPRESSION, std::make_shared<_Expression>(EXPR)}) #define Print(EXPR) (Stmt{StmtType::PRINT, std::make_shared<_Print>(EXPR)}) #define Var(NAME, EXPR) (Stmt{StmtType::VAR, std::make_shared<_Var>(NAME, EXPR)}) +#define Block(STATEMENTS) (Stmt{StmtType::BLOCK, std::make_shared<_Block>(STATEMENTS)}) struct Stmt { Stmt(StmtType type, StmtVariant value); @@ -63,4 +68,9 @@ struct _Var { Expr expr; }; +struct _Block { + _Block(const std::vector &statements) : statements{statements} {} + std::vector statements; +}; + #endif