2025-02-10 14:36:55 +01:00
|
|
|
use thiserror::Error;
|
|
|
|
use tracing::error;
|
|
|
|
|
|
|
|
use crate::{
|
|
|
|
expression::Expression,
|
2025-02-12 10:30:51 +01:00
|
|
|
statement::Statement,
|
2025-02-10 14:36:55 +01:00
|
|
|
token::{
|
|
|
|
self, Token,
|
|
|
|
TokenType::{self, *},
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
#[derive(Error, Debug)]
|
|
|
|
pub enum ParserError {
|
|
|
|
#[error("empty token stream")]
|
|
|
|
NoTokens,
|
2025-02-12 10:30:51 +01:00
|
|
|
#[error("[line {0}] expected expression")]
|
2025-02-10 14:36:55 +01:00
|
|
|
ExpressionExpected(usize),
|
2025-02-12 10:30:51 +01:00
|
|
|
#[error("[line {0}] expected ')' after expression.")]
|
2025-02-10 14:36:55 +01:00
|
|
|
ParenAfterExpression(usize),
|
2025-02-12 10:30:51 +01:00
|
|
|
#[error("[Out of bounds access at index {0}.")]
|
2025-02-10 14:36:55 +01:00
|
|
|
OutOfBoundsAccess(usize),
|
2025-02-12 10:30:51 +01:00
|
|
|
#[error("[line {0}] literal expected.")]
|
2025-02-10 14:36:55 +01:00
|
|
|
LiteralExpected(usize),
|
2025-02-12 10:30:51 +01:00
|
|
|
#[error("[line {0}] expected ';' after value.")]
|
|
|
|
SemicolonAfterValueExpected(usize),
|
|
|
|
#[error("[line {0}] expected ';' after expression.")]
|
|
|
|
SemicolonAfterExpressionExpected(usize),
|
|
|
|
#[error("[line {0}] expected variable name.")]
|
|
|
|
VariableNameExpected(usize),
|
|
|
|
#[error("[line {0}] invalid assignment target.")]
|
|
|
|
InvalidAssignmentTarget(usize),
|
|
|
|
#[error("[line {0}] expected '}}' after block.")]
|
|
|
|
RightBraceAfterBlockExpected(usize),
|
2025-02-10 14:36:55 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Parse the Lox language.
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
struct Parser {
|
|
|
|
current: usize,
|
|
|
|
current_token: Token,
|
|
|
|
tokens: Vec<Token>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Parser {
|
|
|
|
/// Create a new parser instance, fail if the tokens vector is empty.
|
|
|
|
fn new(tokens: Vec<Token>) -> Result<Self, ParserError> {
|
|
|
|
let current_token = tokens.first().ok_or(ParserError::NoTokens)?.clone();
|
|
|
|
|
|
|
|
Ok(Self {
|
|
|
|
current: 0,
|
|
|
|
current_token,
|
|
|
|
tokens,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2025-02-12 10:30:51 +01:00
|
|
|
/// Parse all tokens to a list of statements for execution.
|
|
|
|
fn run(&mut self) -> Result<Vec<Statement>, ParserError> {
|
|
|
|
let mut statements = Vec::new();
|
|
|
|
|
|
|
|
while !self.is_at_end() {
|
|
|
|
match self.declaration() {
|
|
|
|
Ok(x) => statements.push(x),
|
|
|
|
Err(e) => {
|
|
|
|
error!("{e}");
|
|
|
|
self.synchronize();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(statements)
|
|
|
|
}
|
|
|
|
|
2025-02-10 14:36:55 +01:00
|
|
|
/// Check if any of the provided types match the type of the current token.
|
|
|
|
///
|
|
|
|
/// If so, advance the current token.
|
|
|
|
fn matches(&mut self, types: &[TokenType]) -> bool {
|
|
|
|
let matches = types.iter().any(|x| self.check(x));
|
|
|
|
matches.then(|| self.advance());
|
|
|
|
matches
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Return true if the current token type matches the match_type, false otherwise.
|
|
|
|
fn check(&self, match_type: &TokenType) -> bool {
|
|
|
|
self.current_token.token_type == *match_type
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Advance the current token if we have not hit Eof yet.
|
|
|
|
///
|
|
|
|
/// Return the token before the advancement.
|
|
|
|
fn advance(&mut self) -> Result<&Token, ParserError> {
|
|
|
|
if !self.is_at_end() {
|
|
|
|
self.current += 1;
|
|
|
|
self.current_token = self
|
|
|
|
.tokens
|
|
|
|
.get(self.current)
|
|
|
|
.ok_or(ParserError::OutOfBoundsAccess(self.current))?
|
|
|
|
.clone();
|
|
|
|
}
|
|
|
|
|
|
|
|
self.previous()
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Return true if the current token is Eof, false otherwise.
|
|
|
|
fn is_at_end(&self) -> bool {
|
|
|
|
self.current_token.token_type == Eof
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Return the token before the current one or an error if there is none.
|
|
|
|
fn previous(&self) -> Result<&Token, ParserError> {
|
|
|
|
self.tokens
|
|
|
|
.get(self.current - 1)
|
|
|
|
.ok_or_else(|| ParserError::OutOfBoundsAccess(self.current - 1))
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Consume the current token if its token type matches the provided token_type and advance the
|
|
|
|
/// current token. Otherwise return None..
|
|
|
|
fn consume(&mut self, token_type: &TokenType) -> Option<&Token> {
|
|
|
|
if self.check(token_type) {
|
|
|
|
self.advance().ok()
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Parse a binary expression using the next_precedence function and operators to match.
|
|
|
|
fn binary_expr(
|
|
|
|
&mut self,
|
|
|
|
next_precedence: impl Fn(&mut Self) -> Result<Expression, ParserError>,
|
|
|
|
operators: &[TokenType],
|
|
|
|
) -> Result<Expression, ParserError> {
|
|
|
|
let mut expr = next_precedence(self)?;
|
|
|
|
|
|
|
|
while self.matches(operators) {
|
|
|
|
let operator = self.previous()?.clone();
|
|
|
|
let right = next_precedence(self)?;
|
|
|
|
expr = Expression::Binary {
|
|
|
|
left: Box::new(expr.clone()),
|
|
|
|
operator,
|
|
|
|
right: Box::new(right),
|
|
|
|
};
|
|
|
|
}
|
|
|
|
Ok(expr)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// expression -> equality ;
|
|
|
|
fn expression(&mut self) -> Result<Expression, ParserError> {
|
2025-02-12 10:30:51 +01:00
|
|
|
self.assignment()
|
|
|
|
}
|
|
|
|
|
|
|
|
fn declaration(&mut self) -> Result<Statement, ParserError> {
|
|
|
|
if self.matches(&[Var]) {
|
|
|
|
self.var_declaration()
|
|
|
|
} else {
|
|
|
|
self.statement()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn statement(&mut self) -> Result<Statement, ParserError> {
|
|
|
|
if self.matches(&[Print]) {
|
|
|
|
self.print_statement()
|
|
|
|
} else if self.matches(&[LeftBrace]) {
|
|
|
|
Ok(Statement::Block(self.block()?))
|
|
|
|
} else {
|
|
|
|
self.expression_statement()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn print_statement(&mut self) -> Result<Statement, ParserError> {
|
|
|
|
let value = self.expression()?;
|
|
|
|
let line = self.current_token.line;
|
|
|
|
self.consume(&Semicolon)
|
|
|
|
.ok_or(ParserError::SemicolonAfterValueExpected(line))?;
|
|
|
|
|
|
|
|
Ok(Statement::Print(value))
|
|
|
|
}
|
|
|
|
|
|
|
|
fn var_declaration(&mut self) -> Result<Statement, ParserError> {
|
|
|
|
let line = self.current_token.line;
|
|
|
|
let name = self
|
|
|
|
.consume(&Identifier)
|
|
|
|
.ok_or(ParserError::VariableNameExpected(line))?
|
|
|
|
.clone();
|
|
|
|
|
|
|
|
let initializer = if self.matches(&[Equal]) {
|
|
|
|
Some(self.expression()?)
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
};
|
|
|
|
|
|
|
|
self.consume(&Semicolon)
|
|
|
|
.ok_or(ParserError::SemicolonAfterExpressionExpected(line))?;
|
|
|
|
|
|
|
|
Ok(Statement::Var {
|
|
|
|
name,
|
|
|
|
initializer: Box::new(initializer),
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
fn expression_statement(&mut self) -> Result<Statement, ParserError> {
|
|
|
|
let expr = self.expression()?;
|
|
|
|
let line = self.current_token.line;
|
|
|
|
self.consume(&Semicolon)
|
|
|
|
.ok_or(ParserError::SemicolonAfterExpressionExpected(line))?;
|
|
|
|
|
|
|
|
Ok(Statement::Expression(expr))
|
|
|
|
}
|
|
|
|
|
|
|
|
fn block(&mut self) -> Result<Vec<Statement>, ParserError> {
|
|
|
|
let mut statements = Vec::new();
|
|
|
|
|
|
|
|
while !self.check(&RightBrace) && !self.is_at_end() {
|
|
|
|
statements.push(self.declaration()?);
|
|
|
|
}
|
|
|
|
|
|
|
|
let line = self.previous()?.line;
|
|
|
|
self.consume(&RightBrace)
|
|
|
|
.ok_or(ParserError::RightBraceAfterBlockExpected(line))?;
|
|
|
|
|
|
|
|
Ok(statements)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn assignment(&mut self) -> Result<Expression, ParserError> {
|
|
|
|
let expr = self.equality()?;
|
|
|
|
|
|
|
|
if self.matches(&[Equal]) {
|
|
|
|
let equals = self.previous()?.clone();
|
|
|
|
let value = self.assignment()?;
|
|
|
|
|
|
|
|
if let Expression::Variable { name } = expr {
|
|
|
|
Ok(Expression::Assign {
|
|
|
|
name,
|
|
|
|
value: Box::new(value),
|
|
|
|
})
|
|
|
|
} else {
|
|
|
|
Err(ParserError::InvalidAssignmentTarget(equals.line))
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
Ok(expr)
|
|
|
|
}
|
2025-02-10 14:36:55 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/// equality -> comparison ( ( "!=" | "==" ) comparison )* ;
|
|
|
|
fn equality(&mut self) -> Result<Expression, ParserError> {
|
|
|
|
self.binary_expr(Self::comparison, &[BangEqual, EqualEqual])
|
|
|
|
}
|
|
|
|
|
|
|
|
/// comparison -> term ( ( ">" | ">=" | "<" | "<=" ) term )* ;
|
|
|
|
fn comparison(&mut self) -> Result<Expression, ParserError> {
|
|
|
|
self.binary_expr(Self::term, &[Greater, GreaterEqual, Less, LessEqual])
|
|
|
|
}
|
|
|
|
|
|
|
|
/// term -> factor ( ( "-" | "+" ) factor )* ;
|
|
|
|
fn term(&mut self) -> Result<Expression, ParserError> {
|
|
|
|
self.binary_expr(Self::factor, &[Minus, Plus])
|
|
|
|
}
|
|
|
|
|
|
|
|
/// factor -> unary ( ( "/" | "*" ) unary )* ;
|
|
|
|
fn factor(&mut self) -> Result<Expression, ParserError> {
|
|
|
|
self.binary_expr(Self::unary, &[Slash, Star])
|
|
|
|
}
|
|
|
|
|
|
|
|
/// unary -> ( "!" | "-" ) unary | primary ;
|
|
|
|
fn unary(&mut self) -> Result<Expression, ParserError> {
|
|
|
|
if self.matches(&[Bang, Minus]) {
|
|
|
|
let operator = self.previous()?.clone();
|
|
|
|
let right = self.unary()?;
|
|
|
|
|
|
|
|
Ok(Expression::Unary {
|
|
|
|
operator,
|
|
|
|
right: Box::new(right),
|
|
|
|
})
|
|
|
|
} else {
|
|
|
|
self.primary()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// primary -> NUMBER | STRING | "true" | "false" | "nil" | "(" expression ")" ;
|
|
|
|
fn primary(&mut self) -> Result<Expression, ParserError> {
|
|
|
|
if self.matches(&[False]) {
|
|
|
|
Ok(Expression::Literal {
|
|
|
|
value: token::Literal::Boolean(false),
|
|
|
|
})
|
|
|
|
} else if self.matches(&[True]) {
|
|
|
|
Ok(Expression::Literal {
|
|
|
|
value: token::Literal::Boolean(true),
|
|
|
|
})
|
|
|
|
} else if self.matches(&[Nil]) {
|
|
|
|
Ok(Expression::Literal {
|
|
|
|
value: token::Literal::Nil,
|
|
|
|
})
|
2025-02-12 10:30:51 +01:00
|
|
|
} else if self.matches(&[Identifier]) {
|
|
|
|
let prev = self.previous()?.clone();
|
|
|
|
Ok(Expression::Variable { name: prev })
|
2025-02-10 14:36:55 +01:00
|
|
|
} else if self.matches(&[Number, String]) {
|
|
|
|
let prev = self.previous()?;
|
|
|
|
let value = prev
|
|
|
|
.literal
|
|
|
|
.clone()
|
|
|
|
.ok_or(ParserError::LiteralExpected(prev.line))?;
|
|
|
|
|
|
|
|
Ok(Expression::Literal { value })
|
|
|
|
} else if self.matches(&[LeftParen]) {
|
|
|
|
let expr = self.expression()?;
|
|
|
|
let line = self.current_token.line;
|
|
|
|
self.consume(&RightParen)
|
|
|
|
.ok_or(ParserError::ParenAfterExpression(line))?;
|
|
|
|
|
|
|
|
Ok(Expression::Grouping {
|
|
|
|
expression: Box::new(expr),
|
|
|
|
})
|
|
|
|
} else {
|
|
|
|
let prev = self.previous()?;
|
|
|
|
Err(ParserError::ExpressionExpected(prev.line))
|
|
|
|
}
|
|
|
|
}
|
2025-02-10 14:45:11 +01:00
|
|
|
|
|
|
|
fn synchronize(&mut self) {
|
|
|
|
let _ = self.advance();
|
|
|
|
while !self.is_at_end()
|
|
|
|
&& self.previous().unwrap().token_type != Semicolon
|
|
|
|
&& !&[Class, Fun, Var, For, If, While, Print, Return]
|
|
|
|
.contains(&self.current_token.token_type)
|
|
|
|
{
|
|
|
|
let _ = self.advance();
|
|
|
|
}
|
|
|
|
}
|
2025-02-10 14:36:55 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Try to parse the provided tokens into an AST.
|
2025-02-12 10:30:51 +01:00
|
|
|
pub fn ast(tokens: Vec<Token>) -> Result<Vec<Statement>, ParserError> {
|
2025-02-10 14:36:55 +01:00
|
|
|
let mut parser = Parser::new(tokens)?;
|
2025-02-12 10:30:51 +01:00
|
|
|
parser.run()
|
2025-02-10 14:36:55 +01:00
|
|
|
}
|