This commit is contained in:
2026-02-11 16:35:05 +01:00
parent ee279425f2
commit 4e2645e12d
13 changed files with 229 additions and 176 deletions
+51 -21
View File
@@ -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,
))