chapter 10 in rust

This commit is contained in:
Sebastian Hugentobler 2025-02-13 12:29:31 +01:00
parent a13db8e29c
commit a98d249399
9 changed files with 401 additions and 35 deletions

View file

@ -1,6 +1,3 @@
use thiserror::Error;
use tracing::error;
use crate::{
expression::Expression,
statement::Statement,
@ -9,6 +6,8 @@ use crate::{
TokenType::{self, *},
},
};
use thiserror::Error;
use tracing::error;
#[derive(Error, Debug)]
pub enum ParserError {
@ -44,6 +43,20 @@ pub enum ParserError {
SemicolonAfterLoopConditionExpected(usize),
#[error("[line {0}] expected ')' after for clauses.")]
RightParenAfterForClausesExpected(usize),
#[error("[line {0}] expected ')' after arguments.")]
RightParenAfterArgumentsExpected(usize),
#[error("[line {0}] expected function name.")]
FunctionNameExpected(usize),
#[error("[line {0}] expected '(' after function name.")]
LeftParenAfterFunctionNameExpected(usize),
#[error("[line {0}] expected ')' after parameters.")]
RightParenAfterParamsExpected(usize),
#[error("[line {0}] expected parameter name.")]
ParamNameExpected(usize),
#[error("[line {0}] expected '{{' before function body.")]
LeftBraceBeforeFunctionBodyExpected(usize),
#[error("[line {0}] expected ';' after return value.")]
SemicolonAfterReturnExpected(usize),
}
/// Parse the Lox language.
@ -161,7 +174,9 @@ impl Parser {
}
fn declaration(&mut self) -> Result<Statement, ParserError> {
if self.matches(&[Var]) {
if self.matches(&[Fun]) {
self.function()
} else if self.matches(&[Var]) {
self.var_declaration()
} else {
self.statement()
@ -175,6 +190,8 @@ impl Parser {
self.if_statement()
} else if self.matches(&[Print]) {
self.print_statement()
} else if self.matches(&[Return]) {
self.return_statement()
} else if self.matches(&[While]) {
self.while_statement()
} else if self.matches(&[LeftBrace]) {
@ -266,6 +283,20 @@ impl Parser {
Ok(Statement::Print(value))
}
fn return_statement(&mut self) -> Result<Statement, ParserError> {
let keyword = self.previous()?.clone();
let value = if self.check(&Semicolon) {
None
} else {
Some(self.expression()?)
};
self.consume(&Semicolon)
.ok_or(ParserError::SemicolonAfterReturnExpected(keyword.line))?;
Ok(Statement::Return { keyword, value })
}
fn var_declaration(&mut self) -> Result<Statement, ParserError> {
let line = self.current_token.line;
let name = self
@ -315,6 +346,43 @@ impl Parser {
Ok(Statement::Expression(expr))
}
fn function(&mut self) -> Result<Statement, ParserError> {
let line = self.current_token.line;
let name = self
.consume(&Identifier)
.ok_or(ParserError::FunctionNameExpected(line))?
.clone();
self.consume(&LeftParen)
.ok_or(ParserError::LeftParenAfterFunctionNameExpected(line))?;
let mut params = Vec::new();
if !self.check(&RightParen) {
let param = self
.consume(&Identifier)
.ok_or(ParserError::ParamNameExpected(line))?
.clone();
params.push(param);
while self.matches(&[Comma]) {
let param = self
.consume(&Identifier)
.ok_or(ParserError::ParamNameExpected(line))?
.clone();
params.push(param);
}
}
self.consume(&RightParen)
.ok_or(ParserError::RightParenAfterParamsExpected(line))?;
self.consume(&LeftBrace)
.ok_or(ParserError::LeftBraceBeforeFunctionBodyExpected(line))?;
let body = self.block()?;
Ok(Statement::Function { name, params, body })
}
fn block(&mut self) -> Result<Vec<Statement>, ParserError> {
let mut statements = Vec::new();
@ -412,10 +480,48 @@ impl Parser {
right: Box::new(right),
})
} else {
self.primary()
self.call()
}
}
fn call(&mut self) -> Result<Expression, ParserError> {
let mut expr = self.primary()?;
loop {
if self.matches(&[LeftParen]) {
expr = self.finish_call(expr)?;
} else {
break;
}
}
Ok(expr)
}
fn finish_call(&mut self, callee: Expression) -> Result<Expression, ParserError> {
let mut args = Vec::new();
if !self.check(&RightParen) {
args.push(self.expression()?);
while self.matches(&[Comma]) {
args.push(self.expression()?);
}
}
let line = self.current_token.line;
let paren = self
.consume(&RightParen)
.ok_or(ParserError::RightParenAfterArgumentsExpected(line))?
.clone();
Ok(Expression::Call {
callee: Box::new(callee),
paren,
args,
})
}
/// primary -> NUMBER | STRING | "true" | "false" | "nil" | "(" expression ")" ;
fn primary(&mut self) -> Result<Expression, ParserError> {
if self.matches(&[False]) {