implement chapter 12 in rust

This commit is contained in:
Sebastian Hugentobler 2025-05-25 16:04:00 +02:00
parent 283155c38b
commit 621c97102a
Signed by: shu
SSH key fingerprint: SHA256:ppcx6MlixdNZd5EUM1nkHOKoyQYoJwzuQKXM6J/t66M
10 changed files with 366 additions and 17 deletions

View file

@ -25,6 +25,8 @@ pub enum ParserError {
SemicolonAfterValueExpected(usize),
#[error("line {0}: expected ';' after expression.")]
SemicolonAfterExpressionExpected(usize),
#[error("line {0}: expected class name.")]
ClassNameExpected(usize),
#[error("line {0}: expected variable name.")]
VariableNameExpected(usize),
#[error("line {0}: invalid assignment target.")]
@ -57,6 +59,12 @@ pub enum ParserError {
LeftBraceBeforeFunctionBodyExpected(usize),
#[error("line {0}: expected ';' after return value.")]
SemicolonAfterReturnExpected(usize),
#[error("line {0}: expected '{{' before class body.")]
LeftBraceBeforeClassExpected(usize),
#[error("line {0}: expected '}}' after class body.")]
RightBraceAfterClassExpected(usize),
#[error("line {0}: expected property name after '.'.")]
PropertyNameAfterDotExpected(usize),
}
/// Parse the Lox language.
@ -174,7 +182,9 @@ impl Parser {
}
fn declaration(&mut self) -> Result<Statement, ParserError> {
if self.matches(&[Fun]) {
if self.matches(&[Class]) {
self.class_declaration()
} else if self.matches(&[Fun]) {
self.function()
} else if self.matches(&[Var]) {
self.var_declaration()
@ -297,6 +307,28 @@ impl Parser {
Ok(Statement::Return { keyword, value })
}
fn class_declaration(&mut self) -> Result<Statement, ParserError> {
let line = self.current_token.line;
let name = self
.consume(&Identifier)
.ok_or(ParserError::ClassNameExpected(line))?
.clone();
self.consume(&LeftBrace)
.ok_or(ParserError::LeftBraceBeforeClassExpected(line))?;
let mut methods = Vec::new();
while !self.check(&RightBrace) && !self.is_at_end() {
let method = self.function()?;
methods.push(method);
}
self.consume(&RightBrace)
.ok_or(ParserError::RightBraceAfterClassExpected(line))?;
Ok(Statement::Class { name, methods })
}
fn var_declaration(&mut self) -> Result<Statement, ParserError> {
let line = self.current_token.line;
let name = self
@ -409,6 +441,12 @@ impl Parser {
name,
value: Box::new(value),
})
} else if let Expression::Get { object, name } = expr {
Ok(Expression::Set {
object,
name,
value: Box::new(value),
})
} else {
Err(ParserError::InvalidAssignmentTarget(equals.line))
}
@ -490,6 +528,17 @@ impl Parser {
loop {
if self.matches(&[LeftParen]) {
expr = self.finish_call(expr)?;
} else if self.matches(&[Dot]) {
let line = self.current_token.line;
let name = self
.consume(&Identifier)
.ok_or(ParserError::PropertyNameAfterDotExpected(line))?
.clone();
expr = Expression::Get {
object: Box::new(expr),
name,
}
} else {
break;
}
@ -536,6 +585,10 @@ impl Parser {
Ok(Expression::Literal {
value: token::Literal::Nil,
})
} else if self.matches(&[This]) {
Ok(Expression::This {
keyword: self.previous()?.clone(),
})
} else if self.matches(&[Identifier]) {
let prev = self.previous()?.clone();
Ok(Expression::Variable { name: prev })