feat: 添加break和continue语句的支持,更新解析器、解释器和词法分析器以处理相关语法
This commit is contained in:
@@ -44,4 +44,10 @@ pub enum Stmt {
|
||||
|
||||
/// return expr?;
|
||||
Return(Option<Expr>),
|
||||
|
||||
/// break
|
||||
Break,
|
||||
|
||||
/// continue
|
||||
Continue,
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use crate::ast::*;
|
||||
use crate::error::RuntimeError;
|
||||
use crate::interpreter::Signal;
|
||||
use super::{Value, Env, Function};
|
||||
use std::collections::HashMap;
|
||||
use std::rc::Rc;
|
||||
@@ -23,26 +24,30 @@ impl Interpreter {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn execute(&mut self, stmt: Stmt) -> Result<Option<Value>, RuntimeError> {
|
||||
fn execute(&mut self, stmt: Stmt) -> Result<Signal, RuntimeError> {
|
||||
match stmt {
|
||||
Stmt::Let { name, initializer } => {
|
||||
let val = self.evaluate(initializer)?;
|
||||
self.env.borrow_mut().define(name, val);
|
||||
Ok(None)
|
||||
Ok(Signal::None)
|
||||
}
|
||||
Stmt::ExprStmt(expr) => {
|
||||
Ok(Some(self.evaluate(expr)?))
|
||||
self.evaluate(expr)?;
|
||||
Ok(Signal::None)
|
||||
}
|
||||
Stmt::Block(stmts) => {
|
||||
let previous = Rc::clone(&self.env);
|
||||
self.env = Rc::new(RefCell::new(Env::new(Some(previous))));
|
||||
let mut result = None;
|
||||
let mut signal = Signal::None;
|
||||
for s in stmts {
|
||||
result = self.execute(s)?;
|
||||
signal = self.execute(s)?;
|
||||
if !matches!(signal, Signal::None) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
let parent = self.env.borrow().parent.as_ref().unwrap().clone();
|
||||
self.env = parent;
|
||||
Ok(result)
|
||||
Ok(signal)
|
||||
}
|
||||
Stmt::If { condition, then_branch, else_branch } => {
|
||||
let cond_val = self.evaluate(condition)?;
|
||||
@@ -51,7 +56,7 @@ impl Interpreter {
|
||||
} else if let Some(else_branch) = else_branch {
|
||||
self.execute(*else_branch)
|
||||
} else {
|
||||
Ok(None)
|
||||
Ok(Signal::None)
|
||||
}
|
||||
}
|
||||
Stmt::While { condition, body } => {
|
||||
@@ -60,25 +65,42 @@ impl Interpreter {
|
||||
if !self.is_truthy(&cond_val) {
|
||||
break;
|
||||
}
|
||||
self.execute(*body.clone())?;
|
||||
match self.execute(*body.clone())? {
|
||||
Signal::Break => break,
|
||||
Signal::Continue => continue,
|
||||
sig @ Signal::Return(_) => return Ok(sig),
|
||||
Signal::None => {}
|
||||
}
|
||||
}
|
||||
Ok(None)
|
||||
Ok(Signal::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;
|
||||
loop {
|
||||
if let Some(cond) = &condition {
|
||||
let cond_val = self.evaluate(cond.clone())?;
|
||||
if !self.is_truthy(&cond_val) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
match self.execute(*body.clone())? {
|
||||
Signal::Break => break,
|
||||
Signal::Continue => {
|
||||
if let Some(step) = &step {
|
||||
self.evaluate(step.clone())?;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
sig @ Signal::Return(_) => return Ok(sig),
|
||||
Signal::None => {}
|
||||
}
|
||||
self.execute(*body.clone())?;
|
||||
if let Some(step) = &step {
|
||||
self.evaluate(step.clone())?;
|
||||
}
|
||||
}
|
||||
Ok(None)
|
||||
Ok(Signal::None)
|
||||
}
|
||||
Stmt::Function { name, params, body } => {
|
||||
let func = Value::Function(Rc::new(Function {
|
||||
@@ -88,15 +110,17 @@ impl Interpreter {
|
||||
name: Some(name.clone()),
|
||||
}));
|
||||
self.env.borrow_mut().define(name, func);
|
||||
Ok(None)
|
||||
Ok(Signal::None)
|
||||
}
|
||||
Stmt::Return(expr_opt) => {
|
||||
if let Some(expr) = expr_opt {
|
||||
Ok(Some(self.evaluate(expr)?))
|
||||
Ok(Signal::Return(self.evaluate(expr)?))
|
||||
} else {
|
||||
Ok(Some(Value::Nil))
|
||||
Ok(Signal::Return(Value::Nil))
|
||||
}
|
||||
}
|
||||
Stmt::Break => Ok(Signal::Break),
|
||||
Stmt::Continue => Ok(Signal::Continue),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -327,9 +351,15 @@ impl Interpreter {
|
||||
self.env = env;
|
||||
let mut ret = Value::Nil;
|
||||
for stmt in &f.body {
|
||||
if let Some(val) = self.execute(stmt.clone())? {
|
||||
ret = val;
|
||||
break;
|
||||
match self.execute(stmt.clone())? {
|
||||
Signal::Return(val) => { ret = val; break; }
|
||||
Signal::None => {}
|
||||
Signal::Break | Signal::Continue => {
|
||||
return Err(RuntimeError::RuntimeError {
|
||||
message: "break/continue outside of loop".to_string(),
|
||||
token: None,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
self.env = previous;
|
||||
|
||||
@@ -24,6 +24,13 @@ pub enum Value {
|
||||
NativeFunction(NativeFn),
|
||||
}
|
||||
|
||||
pub enum Signal {
|
||||
None, // 正常执行
|
||||
Return(Value), // return 语句携带的返回值
|
||||
Break, // break 信号
|
||||
Continue, // continue 信号
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for Value {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
match self {
|
||||
|
||||
@@ -246,6 +246,8 @@ impl Lexer {
|
||||
"else" => TokenKind::Else,
|
||||
"while" => TokenKind::While,
|
||||
"for" => TokenKind::For,
|
||||
"break" => TokenKind::Break,
|
||||
"continue" => TokenKind::Continue,
|
||||
"return" => TokenKind::Return,
|
||||
"true" => TokenKind::True,
|
||||
"false" => TokenKind::False,
|
||||
|
||||
@@ -29,6 +29,8 @@ pub enum TokenKind {
|
||||
Else,
|
||||
While,
|
||||
For,
|
||||
Break,
|
||||
Continue,
|
||||
Return,
|
||||
True,
|
||||
False,
|
||||
|
||||
@@ -39,6 +39,10 @@ impl Parser {
|
||||
self.while_statement()
|
||||
} else if self.match_kind(&[TokenKind::For]) {
|
||||
self.for_statement()
|
||||
} else if self.match_kind(&[TokenKind::Break]) {
|
||||
self.break_statement()
|
||||
} else if self.match_kind(&[TokenKind::Continue]) {
|
||||
self.continue_statement()
|
||||
} else if self.match_kind(&[TokenKind::Return]) {
|
||||
self.return_statement()
|
||||
} else if self.match_kind(&[TokenKind::LeftBrace]) {
|
||||
@@ -153,6 +157,16 @@ impl Parser {
|
||||
}
|
||||
}
|
||||
|
||||
fn break_statement(&mut self) -> Stmt {
|
||||
self.match_kind(&[TokenKind::Semicolon]); // 分号可选
|
||||
Stmt::Break
|
||||
}
|
||||
|
||||
fn continue_statement(&mut self) -> Stmt {
|
||||
self.match_kind(&[TokenKind::Semicolon]); // 分号可选
|
||||
Stmt::Continue
|
||||
}
|
||||
|
||||
fn return_statement(&mut self) -> Stmt {
|
||||
let value = if !self.check(&TokenKind::Semicolon) && !self.check(&TokenKind::RightBrace) {
|
||||
Some(self.expression())
|
||||
|
||||
Reference in New Issue
Block a user