closure
This commit is contained in:
+51
-21
@@ -2,7 +2,7 @@ use crate::{
|
||||
common::{
|
||||
ast::{AstNode, Expr, Stmt},
|
||||
base_value::{BaseValue, LoxFunction},
|
||||
lox_result::{parse_error, runtime_error, LoxResult},
|
||||
lox_result::{parse_error, runtime_error, LoxError, LoxResult},
|
||||
},
|
||||
frontend::{
|
||||
source_registry::SourceSlice,
|
||||
@@ -24,7 +24,7 @@ impl Parser {
|
||||
let mut statements = Vec::new();
|
||||
let mut errors = Vec::new();
|
||||
while !self.is_at_end() {
|
||||
match self.statement() {
|
||||
match self.statement(None) {
|
||||
Ok(stmt) => {
|
||||
statements.push(stmt.clone());
|
||||
}
|
||||
@@ -42,11 +42,12 @@ impl Parser {
|
||||
Ok(statements)
|
||||
}
|
||||
|
||||
fn statement(&mut self) -> LoxResult<AstNode<Stmt>> {
|
||||
fn statement(&mut self, label: Option<String>) -> LoxResult<AstNode<Stmt>> {
|
||||
match (&self.peek().token_type, &self.peek_next().token_type) {
|
||||
(TokenType::Print, _) => self.print_statement(),
|
||||
(TokenType::Return, _) => self.return_statement(),
|
||||
(TokenType::StartBlock, _) => self.block_statement(),
|
||||
(TokenType::Return, _) => self.return_statement(label),
|
||||
(TokenType::Break, _) => self.return_statement(Some("loop".to_string())),
|
||||
(TokenType::StartBlock, _) => self.block_statement(label),
|
||||
(TokenType::Var, TokenType::Identifier) => {
|
||||
self.advance();
|
||||
self.var_statement()
|
||||
@@ -68,11 +69,7 @@ impl Parser {
|
||||
let condition = self.expression()?;
|
||||
self.consume(TokenType::Semicolon, "Expected ';' after for condition")?;
|
||||
let increment = self.assignment_statement()?;
|
||||
|
||||
self.consume(TokenType::StartBlock, "Expected 'do' after for range")?;
|
||||
|
||||
let body = self.statement()?;
|
||||
self.consume(TokenType::EndBlock, "Expected 'end' after for body")?;
|
||||
let body = self.statement(Some("loop".to_string()))?;
|
||||
|
||||
let end_slice = self.previous().source_slice.clone();
|
||||
let combined_slice = SourceSlice::from_positions(
|
||||
@@ -118,7 +115,7 @@ impl Parser {
|
||||
// self.advance();
|
||||
// self.consume(TokenType::In, "Expect 'in' after for variable.")?;
|
||||
// let iterable = self.expression()?;
|
||||
// let body = self.statement()?;
|
||||
// let body = self.statement(None)?;
|
||||
// let end_slice = body.source_slice.clone();
|
||||
// let combined_slice = SourceSlice::from_positions(
|
||||
// start_slice.source_id,
|
||||
@@ -139,7 +136,7 @@ impl Parser {
|
||||
let start_slice = self.peek().source_slice.clone();
|
||||
self.advance();
|
||||
let condition = self.expression()?;
|
||||
let body = self.statement()?;
|
||||
let body = self.statement(Some("loop".to_string()))?;
|
||||
let end_slice = body.source_slice.clone();
|
||||
let combined_slice = SourceSlice::from_positions(
|
||||
start_slice.source_id,
|
||||
@@ -161,7 +158,7 @@ impl Parser {
|
||||
self.advance(); // consume 'if'
|
||||
let condition = self.expression()?;
|
||||
self.consume(TokenType::Then, "Expect 'then' after if condition.")?;
|
||||
let then_branch = self.statement()?;
|
||||
let then_branch = self.statement(None)?;
|
||||
let mut elif_branches = Vec::new();
|
||||
let mut last_slice = then_branch.source_slice.clone();
|
||||
|
||||
@@ -169,14 +166,14 @@ impl Parser {
|
||||
self.advance(); // consume 'elif'
|
||||
let elif_condition = self.expression()?;
|
||||
self.consume(TokenType::Then, "Expect 'then' after elif condition.")?;
|
||||
let elif_branch = self.statement()?;
|
||||
let elif_branch = self.statement(None)?;
|
||||
last_slice = elif_branch.source_slice.clone();
|
||||
elif_branches.push((Box::new(elif_condition), Box::new(elif_branch)));
|
||||
}
|
||||
|
||||
let else_branch = if self.peek().token_type == TokenType::Else {
|
||||
self.advance(); // consume 'else'
|
||||
let else_stmt = self.statement()?;
|
||||
let else_stmt = self.statement(None)?;
|
||||
last_slice = else_stmt.source_slice.clone();
|
||||
Some(Box::new(else_stmt))
|
||||
} else {
|
||||
@@ -259,7 +256,7 @@ impl Parser {
|
||||
self.consume(TokenType::RightBrace, "Expected '}' after guard expression")?;
|
||||
}
|
||||
|
||||
let body = self.statement()?;
|
||||
let body = self.statement(None)?;
|
||||
let node = AstNode {
|
||||
node: Expr::Literal {
|
||||
value: BaseValue::Function(LoxFunction {
|
||||
@@ -370,12 +367,13 @@ impl Parser {
|
||||
))
|
||||
}
|
||||
|
||||
fn block_statement(&mut self) -> LoxResult<AstNode<Stmt>> {
|
||||
fn block_statement(&mut self, label: Option<String>) -> LoxResult<AstNode<Stmt>> {
|
||||
let start_slice = self.peek().source_slice.clone();
|
||||
self.advance();
|
||||
let mut statements = Vec::new();
|
||||
|
||||
while self.peek().token_type != TokenType::EndBlock && !self.is_at_end() {
|
||||
let stmt = self.statement()?;
|
||||
let stmt = self.statement(label.clone())?;
|
||||
let should_break = matches!(stmt.node, Stmt::Expression { .. });
|
||||
statements.push(stmt);
|
||||
if should_break {
|
||||
@@ -389,10 +387,15 @@ impl Parser {
|
||||
start_slice.start_position,
|
||||
end_slice.end_position,
|
||||
);
|
||||
let label_str = if let Some(label) = label {
|
||||
label
|
||||
} else {
|
||||
String::default()
|
||||
};
|
||||
Ok(AstNode::new(
|
||||
Stmt::Block {
|
||||
statements: Box::new(statements),
|
||||
label: String::default(),
|
||||
label: label_str,
|
||||
return_value: Box::new(BaseValue::Nil),
|
||||
},
|
||||
combined_slice,
|
||||
@@ -429,10 +432,31 @@ impl Parser {
|
||||
))
|
||||
}
|
||||
|
||||
fn return_statement(&mut self) -> LoxResult<AstNode<Stmt>> {
|
||||
fn return_statement(&mut self, label: Option<String>) -> LoxResult<AstNode<Stmt>> {
|
||||
let start_slice = self.peek().source_slice.clone();
|
||||
self.advance();
|
||||
let expr = self.expression()?;
|
||||
let expr = match self.expression() {
|
||||
Ok(expr) => expr,
|
||||
Err(LoxError::ParseError {
|
||||
message,
|
||||
source_slice,
|
||||
}) => {
|
||||
if message == "Expect expression." {
|
||||
AstNode {
|
||||
node: Expr::Literal {
|
||||
value: BaseValue::Nil,
|
||||
},
|
||||
source_slice: start_slice.clone(),
|
||||
}
|
||||
} else {
|
||||
return Err(LoxError::ParseError {
|
||||
message,
|
||||
source_slice,
|
||||
});
|
||||
}
|
||||
}
|
||||
Err(err) => return Err(err),
|
||||
};
|
||||
let semicolon = self.consume(TokenType::Semicolon, "Expect ';' after return value.")?;
|
||||
let end_slice = semicolon.source_slice.clone();
|
||||
let combined_slice = SourceSlice::from_positions(
|
||||
@@ -440,10 +464,16 @@ impl Parser {
|
||||
start_slice.start_position,
|
||||
end_slice.end_position,
|
||||
);
|
||||
let label_str = if let Some(label) = label {
|
||||
label
|
||||
} else {
|
||||
String::default()
|
||||
};
|
||||
Ok(AstNode::new(
|
||||
Stmt::Return {
|
||||
expression: Box::new(expr),
|
||||
return_value: Box::new(BaseValue::Nil),
|
||||
label: label_str,
|
||||
},
|
||||
combined_slice,
|
||||
))
|
||||
|
||||
Reference in New Issue
Block a user