Add break continue

This commit is contained in:
2026-01-16 00:01:23 +08:00
parent df84159ed8
commit 9c5a3397d9
9 changed files with 137 additions and 4 deletions

View File

@@ -183,6 +183,14 @@ struct ReturnStmt : public Stmt {
explicit ReturnStmt(ExprPtr value = nullptr) : value(std::move(value)) {}
};
struct BreakStmt : public Stmt {
BreakStmt() = default;
};
struct ContinueStmt : public Stmt {
ContinueStmt() = default;
};
struct FunctionDecl : public Stmt {
std::string name;
std::vector<std::pair<std::string, std::string>> parameters; // (type, name)

View File

@@ -106,6 +106,10 @@ void Interpreter::execute_statement(const Stmt& stmt) {
exec_for(*for_stmt);
} else if (auto* return_stmt = dynamic_cast<const ReturnStmt*>(&stmt)) {
exec_return(*return_stmt);
} else if (auto* break_stmt = dynamic_cast<const BreakStmt*>(&stmt)) {
exec_break(*break_stmt);
} else if (auto* continue_stmt = dynamic_cast<const ContinueStmt*>(&stmt)) {
exec_continue(*continue_stmt);
} else if (auto* func_decl = dynamic_cast<const FunctionDecl*>(&stmt)) {
exec_function_decl(*func_decl);
} else if (auto* class_decl = dynamic_cast<const ClassDecl*>(&stmt)) {
@@ -397,8 +401,17 @@ void Interpreter::exec_if(const IfStmt& stmt) {
}
void Interpreter::exec_while(const WhileStmt& stmt) {
while (is_truthy(evaluate(*stmt.condition))) {
execute_statement(*stmt.body);
try {
while (is_truthy(evaluate(*stmt.condition))) {
try {
execute_statement(*stmt.body);
} catch (const ContinueException&) {
// Continue: just proceed to the next iteration (check condition again)
continue;
}
}
} catch (const BreakException&) {
// Break: exit the loop
}
}
@@ -412,12 +425,18 @@ void Interpreter::exec_for(const ForStmt& stmt) {
}
while (!stmt.condition || is_truthy(evaluate(*stmt.condition))) {
execute_statement(*stmt.body);
try {
execute_statement(*stmt.body);
} catch (const ContinueException&) {
// Continue: proceed to increment
}
if (stmt.increment) {
evaluate(*stmt.increment);
}
}
} catch (const BreakException&) {
// Break: exit the loop
} catch (...) {
environment = previous;
throw;
@@ -431,6 +450,14 @@ void Interpreter::exec_return(const ReturnStmt& stmt) {
throw ReturnException(value);
}
void Interpreter::exec_break(const BreakStmt& stmt) {
throw BreakException();
}
void Interpreter::exec_continue(const ContinueStmt& stmt) {
throw ContinueException();
}
void Interpreter::exec_function_decl(const FunctionDecl& stmt) {
auto func_decl = std::make_shared<FunctionDecl>(stmt);
auto func = std::make_shared<FunctionValue>(stmt.name, func_decl);

View File

@@ -20,6 +20,9 @@ public:
explicit ReturnException(ValuePtr value) : value(std::move(value)) {}
};
class BreakException : public std::exception {};
class ContinueException : public std::exception {};
class Environment {
public:
std::shared_ptr<Environment> parent;
@@ -138,6 +141,8 @@ private:
void exec_while(const WhileStmt& stmt);
void exec_for(const ForStmt& stmt);
void exec_return(const ReturnStmt& stmt);
void exec_break(const BreakStmt& stmt);
void exec_continue(const ContinueStmt& stmt);
void exec_function_decl(const FunctionDecl& stmt);
void exec_class_decl(const ClassDecl& stmt);

View File

@@ -224,6 +224,8 @@ TokenType Lexer::get_keyword_type(const std::string& text) const {
{"and", TokenType::AND},
{"or", TokenType::OR},
{"this", TokenType::THIS},
{"continue", TokenType::CONTINUE},
{"break", TokenType::BREAK},
};
auto it = keywords.find(text);

View File

@@ -12,7 +12,7 @@ enum class TokenType {
// Keywords
CLASS, FUNC, NUMBER, STRING, BOOL, LIST, MAP,
IF, ELSE, WHILE, FOR, RETURN, VAR,
TRUE, FALSE, NIL, THIS,
TRUE, FALSE, NIL, THIS, CONTINUE, BREAK,
// Operators
PLUS, MINUS, STAR, SLASH, PERCENT,

View File

@@ -179,6 +179,8 @@ StmtPtr Parser::statement() {
if (match({TokenType::WHILE})) return while_statement();
if (match({TokenType::FOR})) return for_statement();
if (match({TokenType::RETURN})) return return_statement();
if (match({TokenType::BREAK})) return break_statement();
if (match({TokenType::CONTINUE})) return continue_statement();
if (match({TokenType::LEFT_BRACE})) return block_statement();
return expression_statement();
@@ -247,6 +249,16 @@ StmtPtr Parser::return_statement() {
return std::make_unique<ReturnStmt>(std::move(value));
}
StmtPtr Parser::break_statement() {
consume(TokenType::SEMICOLON, "Expected ';' after 'break'.");
return std::make_unique<BreakStmt>();
}
StmtPtr Parser::continue_statement() {
consume(TokenType::SEMICOLON, "Expected ';' after 'continue'.");
return std::make_unique<ContinueStmt>();
}
StmtPtr Parser::block_statement() {
std::vector<StmtPtr> statements;

View File

@@ -44,6 +44,8 @@ private:
StmtPtr while_statement();
StmtPtr for_statement();
StmtPtr return_statement();
StmtPtr break_statement();
StmtPtr continue_statement();
StmtPtr block_statement();
StmtPtr expression_statement();