chapter 9 in rust

This commit is contained in:
Sebastian Hugentobler 2025-02-12 13:10:07 +01:00
parent 1a485ebcb1
commit f82919414e
5 changed files with 271 additions and 35 deletions

View file

@ -5,7 +5,7 @@ use crate::{
expression::Expression,
statement::Statement,
token::{
self, Token,
self, Literal, Token,
TokenType::{self, *},
},
};
@ -32,6 +32,18 @@ pub enum ParserError {
InvalidAssignmentTarget(usize),
#[error("[line {0}] expected '}}' after block.")]
RightBraceAfterBlockExpected(usize),
#[error("[line {0}] expected '(' after if.")]
LeftParenAfterIfExpected(usize),
#[error("[line {0}] expected ')' after condition.")]
RightParenAfterConditionExpected(usize),
#[error("[line {0}] expected '(' after while.")]
LeftParenAfterWhileExpected(usize),
#[error("[line {0}] expected '(' after for.")]
LeftParenAfterForExpected(usize),
#[error("[line {0}] expected ';' after loop condition.")]
SemicolonAfterLoopConditionExpected(usize),
#[error("[line {0}] expected ')' after for clauses.")]
RightParenAfterForClausesExpected(usize),
}
/// Parse the Lox language.
@ -157,8 +169,14 @@ impl Parser {
}
fn statement(&mut self) -> Result<Statement, ParserError> {
if self.matches(&[Print]) {
if self.matches(&[For]) {
self.for_statement()
} else if self.matches(&[If]) {
self.if_statement()
} else if self.matches(&[Print]) {
self.print_statement()
} else if self.matches(&[While]) {
self.while_statement()
} else if self.matches(&[LeftBrace]) {
Ok(Statement::Block(self.block()?))
} else {
@ -166,6 +184,79 @@ impl Parser {
}
}
/// Build up a while statement from a for statement.
fn for_statement(&mut self) -> Result<Statement, ParserError> {
let line = self.current_token.line;
self.consume(&LeftParen)
.ok_or(ParserError::LeftParenAfterForExpected(line))?;
let initializer = if self.matches(&[Semicolon]) {
None
} else if self.matches(&[Var]) {
Some(self.var_declaration()?)
} else {
Some(self.expression_statement()?)
};
let condition = if !self.matches(&[Semicolon]) {
self.expression()?
} else {
Expression::Literal {
value: Literal::Boolean(true),
}
};
self.consume(&Semicolon)
.ok_or(ParserError::SemicolonAfterLoopConditionExpected(line))?;
let increment = if !self.check(&RightParen) {
Some(self.expression()?)
} else {
None
};
self.consume(&RightParen)
.ok_or(ParserError::RightParenAfterForClausesExpected(line))?;
let body = self.statement()?;
let body = match increment {
Some(inc) => Statement::Block(vec![body, Statement::Expression(inc)]),
None => body,
};
let body = Statement::While {
condition,
body: Box::new(body),
};
let body = match initializer {
Some(initializer) => Statement::Block(vec![initializer, body]),
None => body,
};
Ok(body)
}
fn if_statement(&mut self) -> Result<Statement, ParserError> {
let line = self.current_token.line;
self.consume(&LeftParen)
.ok_or(ParserError::LeftParenAfterIfExpected(line))?;
let condition = self.expression()?;
self.consume(&RightParen)
.ok_or(ParserError::RightParenAfterConditionExpected(line))?;
let then_branch = self.statement()?;
let else_branch = if self.matches(&[Else]) {
Some(Box::new(self.statement()?))
} else {
None
};
Ok(Statement::If {
condition,
then_branch: Box::new(then_branch),
else_branch,
})
}
fn print_statement(&mut self) -> Result<Statement, ParserError> {
let value = self.expression()?;
let line = self.current_token.line;
@ -197,6 +288,24 @@ impl Parser {
})
}
fn while_statement(&mut self) -> Result<Statement, ParserError> {
let line = self.current_token.line;
self.consume(&LeftParen)
.ok_or(ParserError::LeftParenAfterWhileExpected(line))?;
let condition = self.expression()?;
self.consume(&RightParen)
.ok_or(ParserError::RightParenAfterConditionExpected(line))?;
let body = self.statement()?;
Ok(Statement::While {
condition,
body: Box::new(body),
})
}
fn expression_statement(&mut self) -> Result<Statement, ParserError> {
let expr = self.expression()?;
let line = self.current_token.line;
@ -221,7 +330,7 @@ impl Parser {
}
fn assignment(&mut self) -> Result<Expression, ParserError> {
let expr = self.equality()?;
let expr = self.or()?;
if self.matches(&[Equal]) {
let equals = self.previous()?.clone();
@ -240,6 +349,38 @@ impl Parser {
}
}
fn logical_operator<F>(
&mut self,
operator: TokenType,
parse_fn: F,
) -> Result<Expression, ParserError>
where
F: Fn(&mut Self) -> Result<Expression, ParserError>,
{
let mut expr = parse_fn(self)?;
while self.matches(&[operator]) {
let operator = self.previous()?.clone();
let right = parse_fn(self)?;
expr = Expression::Logical {
left: Box::new(expr),
operator,
right: Box::new(right),
};
}
Ok(expr)
}
fn or(&mut self) -> Result<Expression, ParserError> {
self.logical_operator(Or, Self::and)
}
fn and(&mut self) -> Result<Expression, ParserError> {
self.logical_operator(And, Self::equality)
}
/// equality -> comparison ( ( "!=" | "==" ) comparison )* ;
fn equality(&mut self) -> Result<Expression, ParserError> {
self.binary_expr(Self::comparison, &[BangEqual, EqualEqual])