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