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())