From 5dc55c3476ddc560168512085d66bd34a528dc8a Mon Sep 17 00:00:00 2001 From: 0264408 Date: Wed, 11 Feb 2026 09:39:06 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=AE=9E=E7=8E=B0for=E5=BE=AA=E7=8E=AF?= =?UTF-8?q?=E8=AF=AD=E5=8F=A5=E7=9A=84=E8=A7=A3=E6=9E=90=E5=92=8C=E6=89=A7?= =?UTF-8?q?=E8=A1=8C=E9=80=BB=E8=BE=91=EF=BC=8C=E6=9B=B4=E6=96=B0=E8=AF=8D?= =?UTF-8?q?=E6=B3=95=E5=88=86=E6=9E=90=E5=99=A8=E4=BB=A5=E6=94=AF=E6=8C=81?= =?UTF-8?q?for=E5=85=B3=E9=94=AE=E5=AD=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/loop.ast | 9 +++++++++ src/ast/stmt.rs | 8 ++++++++ src/interpreter/interpreter.rs | 16 +++++++++++++++ src/lexer/lexer.rs | 1 + src/lexer/token.rs | 1 + src/parser/parser.rs | 36 ++++++++++++++++++++++++++++++++++ 6 files changed, 71 insertions(+) create mode 100644 examples/loop.ast diff --git a/examples/loop.ast b/examples/loop.ast new file mode 100644 index 0000000..7914c2d --- /dev/null +++ b/examples/loop.ast @@ -0,0 +1,9 @@ +let i = 0; +while(i < 10) { + print(i); + i = i + 1; +} + +for (let i = 0; i < 10; i = i + 1) { + print(i) +} diff --git a/src/ast/stmt.rs b/src/ast/stmt.rs index 46bd417..9693cd1 100644 --- a/src/ast/stmt.rs +++ b/src/ast/stmt.rs @@ -27,6 +27,14 @@ pub enum Stmt { body: Box, }, + /// for 循环 + For { + initializer: Option>, + condition: Option, + step: Option, + body: Box, + }, + /// 函数声明 Function { name: String, diff --git a/src/interpreter/interpreter.rs b/src/interpreter/interpreter.rs index 2e44408..ff31921 100644 --- a/src/interpreter/interpreter.rs +++ b/src/interpreter/interpreter.rs @@ -64,6 +64,22 @@ impl Interpreter { } Ok(None) } + Stmt::For { initializer, condition, step, body } => { + if let Some(init) = initializer { + self.execute(*init)?; + } + while let Some(cond) = &condition { + let cond_val = self.evaluate(cond.clone())?; + if !self.is_truthy(&cond_val) { + break; + } + self.execute(*body.clone())?; + if let Some(step) = &step { + self.evaluate(step.clone())?; + } + } + Ok(None) + } Stmt::Function { name, params, body } => { let func = Value::Function(Rc::new(Function { params, diff --git a/src/lexer/lexer.rs b/src/lexer/lexer.rs index 21eef96..4509919 100644 --- a/src/lexer/lexer.rs +++ b/src/lexer/lexer.rs @@ -243,6 +243,7 @@ impl Lexer { "if" => TokenKind::If, "else" => TokenKind::Else, "while" => TokenKind::While, + "for" => TokenKind::For, "return" => TokenKind::Return, "true" => TokenKind::True, "false" => TokenKind::False, diff --git a/src/lexer/token.rs b/src/lexer/token.rs index 18b087c..57a05f7 100644 --- a/src/lexer/token.rs +++ b/src/lexer/token.rs @@ -27,6 +27,7 @@ pub enum TokenKind { If, Else, While, + For, Return, True, False, diff --git a/src/parser/parser.rs b/src/parser/parser.rs index b7f3f31..9a8543e 100644 --- a/src/parser/parser.rs +++ b/src/parser/parser.rs @@ -37,6 +37,8 @@ impl Parser { self.if_statement() } else if self.match_kind(&[TokenKind::While]) { self.while_statement() + } else if self.match_kind(&[TokenKind::For]) { + self.for_statement() } else if self.match_kind(&[TokenKind::Return]) { self.return_statement() } else if self.match_kind(&[TokenKind::LeftBrace]) { @@ -117,6 +119,40 @@ impl Parser { Stmt::While { condition, body } } + fn for_statement(&mut self) -> Stmt { + self.consume(TokenKind::LeftParen, "Expected '(' after 'for'.").unwrap(); + let initializer = if self.match_kind(&[TokenKind::Semicolon]) { + None + } else if self.match_kind(&[TokenKind::Let]) { + Some(self.let_declaration()) + } else { + Some(self.expression_statement()) + }; + + let condition = if !self.check(&TokenKind::Semicolon) { + Some(self.expression()) + } else { + None + }; + + self.consume(TokenKind::Semicolon, "Expected ';' after loop condition.").unwrap(); + let step = if !self.check(&TokenKind::RightParen) { + Some(self.expression()) + } else { + None + }; + + self.consume(TokenKind::RightParen, "Expected ')' after for clauses.").unwrap(); + let body = Box::new(self.statement()); + + Stmt::For { + initializer: initializer.map(Box::new), + condition, + step, + body + } + } + fn return_statement(&mut self) -> Stmt { let value = if !self.check(&TokenKind::Semicolon) && !self.check(&TokenKind::RightBrace) { Some(self.expression())