Initialize Rust implementation of Lox interpreter
This initial commit sets up the basic structure for a Rust implementation of the Lox interpreter, including: - Lexer for tokenizing source code - Parser for building AST - Basic interpreter functionality - Environment for variable storage The core components include source tracking, error handling, and basic expression evaluation.
This commit is contained in:
@@ -0,0 +1,437 @@
|
||||
use crate::{
|
||||
frontend::{
|
||||
ast::{AstNode, Expr, Stmt},
|
||||
tokens::{LiteralValue, Token, TokenType},
|
||||
},
|
||||
logging::display_ast::{pretty_print_with_config, PrettyConfig, PrettyPrint},
|
||||
result::{LoxError, LoxResult},
|
||||
};
|
||||
|
||||
pub struct Parser {
|
||||
tokens: Vec<Token>,
|
||||
current: usize,
|
||||
}
|
||||
|
||||
impl Parser {
|
||||
pub fn new(tokens: Vec<Token>) -> Self {
|
||||
Self { tokens, current: 0 }
|
||||
}
|
||||
|
||||
pub fn parse(&mut self) -> LoxResult<Vec<AstNode<Stmt>>> {
|
||||
let mut statements = Vec::new();
|
||||
let mut errors = Vec::new();
|
||||
println!("\n \n ++++++++++++++++++++++++++++++++++++\nStarting parsing");
|
||||
// Con configurazione personalizzata
|
||||
let config = PrettyConfig {
|
||||
indent: " ".to_string(),
|
||||
max_depth: None,
|
||||
show_positions: false,
|
||||
..Default::default()
|
||||
};
|
||||
while !self.is_at_end() {
|
||||
match self.statement() {
|
||||
Ok(stmt) => {
|
||||
println!(
|
||||
"Parsed Successfully: {}",
|
||||
pretty_print_with_config(&stmt.node, &config)
|
||||
);
|
||||
|
||||
statements.push(stmt.clone());
|
||||
}
|
||||
Err(err) => {
|
||||
println!("Error: {:?}", err);
|
||||
errors.push(err);
|
||||
let old_current = self.current;
|
||||
self.synchronize();
|
||||
println!("Synchronized from {} to {}", old_current, self.current);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !errors.is_empty() {
|
||||
return Err(errors.into_iter().next().unwrap());
|
||||
}
|
||||
|
||||
Ok(statements)
|
||||
}
|
||||
|
||||
fn statement(&mut self) -> LoxResult<AstNode<Stmt>> {
|
||||
match (&self.peek().token_type, &self.peek_next().token_type) {
|
||||
(TokenType::Var, _) => Ok(AstNode::new(
|
||||
self.var_statement()?,
|
||||
self.peek().source_slice.clone(),
|
||||
)),
|
||||
(TokenType::Print, _) => Ok(AstNode::new(
|
||||
self.print_statement()?,
|
||||
self.peek().source_slice.clone(),
|
||||
)),
|
||||
(TokenType::Return, _) => Ok(AstNode::new(
|
||||
self.return_statement()?,
|
||||
self.peek().source_slice.clone(),
|
||||
)),
|
||||
(TokenType::StartBlock, _) => Ok(AstNode::new(
|
||||
self.block_statement()?,
|
||||
self.peek().source_slice.clone(),
|
||||
)),
|
||||
(TokenType::Identifier, TokenType::Equal) => Ok(AstNode::new(
|
||||
self.assignment_statement()?,
|
||||
self.peek().source_slice.clone(),
|
||||
)),
|
||||
(TokenType::If, _) => Ok(AstNode::new(
|
||||
self.if_statement()?,
|
||||
self.peek().source_slice.clone(),
|
||||
)),
|
||||
_ => Ok(AstNode::new(
|
||||
self.expression_statement()?,
|
||||
self.peek().source_slice.clone(),
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
fn if_statement(&mut self) -> LoxResult<Stmt> {
|
||||
self.advance();
|
||||
let condition = self.expression()?;
|
||||
let then_branch = self.statement()?;
|
||||
let mut elif_branches = Vec::new();
|
||||
while self.peek().token_type == TokenType::Elif {
|
||||
self.advance();
|
||||
let condition = self.expression()?;
|
||||
let then_branch = self.statement()?;
|
||||
elif_branches.push((Box::new(condition), Box::new(then_branch.node)));
|
||||
}
|
||||
let else_branch = if self.peek().token_type == TokenType::Else {
|
||||
self.advance();
|
||||
Some(Box::new(self.statement()?.node))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
Ok(Stmt::If {
|
||||
condition: Box::new(condition),
|
||||
then_branch: Box::new(then_branch.node),
|
||||
elif_branch: elif_branches,
|
||||
else_branch: else_branch,
|
||||
})
|
||||
}
|
||||
|
||||
fn var_statement(&mut self) -> LoxResult<Stmt> {
|
||||
self.advance();
|
||||
let name = self.consume(TokenType::Identifier, "Expect variable name.")?;
|
||||
let name_lexeme = name.lexeme.clone();
|
||||
self.consume(TokenType::Equal, "Expect '=' after variable name.")?;
|
||||
let value = self.expression()?;
|
||||
self.consume(
|
||||
TokenType::Semicolon,
|
||||
"Expect ';' after variable declaration.",
|
||||
)?;
|
||||
Ok(Stmt::Var {
|
||||
name: name_lexeme,
|
||||
initializer: Some(Box::new(value)),
|
||||
})
|
||||
}
|
||||
|
||||
fn assignment_statement(&mut self) -> LoxResult<Stmt> {
|
||||
let name = self.consume(TokenType::Identifier, "Expect variable name.")?;
|
||||
let name_lexeme = name.lexeme.clone();
|
||||
self.consume(TokenType::Equal, "Expect '=' after variable name.")?;
|
||||
let value = self.expression()?;
|
||||
self.consume(
|
||||
TokenType::Semicolon,
|
||||
"Expect ';' after variable declaration.",
|
||||
)?;
|
||||
Ok(Stmt::Assign {
|
||||
name: name_lexeme,
|
||||
value: Box::new(value),
|
||||
})
|
||||
}
|
||||
|
||||
fn print_statement(&mut self) -> LoxResult<Stmt> {
|
||||
// consume the print keyword
|
||||
self.advance();
|
||||
let expr = self.expression()?;
|
||||
self.consume(TokenType::Semicolon, "Expect ';' after value.")?;
|
||||
Ok(Stmt::Print {
|
||||
expression: Box::new(expr),
|
||||
})
|
||||
}
|
||||
|
||||
fn block_statement(&mut self) -> LoxResult<Stmt> {
|
||||
self.advance();
|
||||
let mut statements = Vec::new();
|
||||
while self.peek().token_type != TokenType::EndBlock && !self.is_at_end() {
|
||||
let stmt = self.statement()?;
|
||||
statements.push(stmt.node.clone());
|
||||
if let Stmt::Expression { .. } = stmt.node {
|
||||
break;
|
||||
}
|
||||
}
|
||||
self.consume(TokenType::EndBlock, "Expect 'end' after block.")?;
|
||||
Ok(Stmt::Block {
|
||||
statements: Box::new(statements),
|
||||
})
|
||||
}
|
||||
|
||||
fn expression_statement(&mut self) -> LoxResult<Stmt> {
|
||||
let expr = self.expression()?;
|
||||
if self.peek().token_type == TokenType::Semicolon {
|
||||
self.advance();
|
||||
return Ok(Stmt::Stmt {
|
||||
expression: Box::new(expr),
|
||||
});
|
||||
}
|
||||
Ok(Stmt::Expression {
|
||||
expression: Box::new(expr),
|
||||
})
|
||||
}
|
||||
|
||||
fn return_statement(&mut self) -> LoxResult<Stmt> {
|
||||
self.advance();
|
||||
let expr = self.expression()?;
|
||||
self.consume(TokenType::Semicolon, "Expect ';' after return value.")?;
|
||||
Ok(Stmt::Return {
|
||||
expression: Box::new(expr),
|
||||
})
|
||||
}
|
||||
|
||||
fn expression(&mut self) -> LoxResult<Expr> {
|
||||
self.or_and()
|
||||
}
|
||||
|
||||
fn or_and(&mut self) -> LoxResult<Expr> {
|
||||
let mut expr = self.equality()?;
|
||||
|
||||
while [TokenType::Or, TokenType::And].contains(&self.peek().token_type) {
|
||||
let operator = self.peek().token_type.clone();
|
||||
self.advance();
|
||||
let right = self.equality()?;
|
||||
expr = Expr::Binary {
|
||||
left: Box::new(expr),
|
||||
operator,
|
||||
right: Box::new(right),
|
||||
};
|
||||
}
|
||||
|
||||
Ok(expr)
|
||||
}
|
||||
fn equality(&mut self) -> LoxResult<Expr> {
|
||||
let mut expr = self.comparison()?;
|
||||
|
||||
while [TokenType::BangEqual, TokenType::EqualEqual].contains(&self.peek().token_type) {
|
||||
let operator = self.peek().token_type.clone();
|
||||
self.advance();
|
||||
let right = self.comparison()?;
|
||||
expr = Expr::Binary {
|
||||
left: Box::new(expr),
|
||||
operator,
|
||||
right: Box::new(right),
|
||||
};
|
||||
}
|
||||
|
||||
Ok(expr)
|
||||
}
|
||||
|
||||
fn comparison(&mut self) -> LoxResult<Expr> {
|
||||
let mut expr = self.term()?;
|
||||
|
||||
while [
|
||||
TokenType::Greater,
|
||||
TokenType::GreaterEqual,
|
||||
TokenType::Less,
|
||||
TokenType::LessEqual,
|
||||
]
|
||||
.contains(&self.peek().token_type)
|
||||
{
|
||||
let operator = self.peek().token_type.clone();
|
||||
self.advance();
|
||||
let right = self.term()?;
|
||||
expr = Expr::Binary {
|
||||
left: Box::new(expr),
|
||||
operator,
|
||||
right: Box::new(right),
|
||||
};
|
||||
}
|
||||
|
||||
Ok(expr)
|
||||
}
|
||||
|
||||
fn term(&mut self) -> LoxResult<Expr> {
|
||||
let mut expr = self.factor()?;
|
||||
|
||||
while [TokenType::Plus, TokenType::Minus].contains(&self.peek().token_type) {
|
||||
let operator = self.peek().token_type.clone();
|
||||
self.advance();
|
||||
let right = self.factor()?;
|
||||
expr = Expr::Binary {
|
||||
left: Box::new(expr),
|
||||
operator,
|
||||
right: Box::new(right),
|
||||
};
|
||||
}
|
||||
|
||||
Ok(expr)
|
||||
}
|
||||
|
||||
fn factor(&mut self) -> LoxResult<Expr> {
|
||||
let mut expr = self.unary()?;
|
||||
|
||||
while [TokenType::Slash, TokenType::Star].contains(&self.peek().token_type) {
|
||||
let operator = self.peek().token_type.clone();
|
||||
self.advance();
|
||||
let right = self.unary()?;
|
||||
expr = Expr::Binary {
|
||||
left: Box::new(expr),
|
||||
operator,
|
||||
right: Box::new(right),
|
||||
};
|
||||
}
|
||||
|
||||
Ok(expr)
|
||||
}
|
||||
|
||||
fn unary(&mut self) -> LoxResult<Expr> {
|
||||
if [TokenType::Bang, TokenType::Minus].contains(&self.peek().token_type) {
|
||||
let operator = self.peek().token_type.clone();
|
||||
self.advance();
|
||||
let right = self.unary()?;
|
||||
return Ok(Expr::Unary {
|
||||
operator,
|
||||
operand: Box::new(right),
|
||||
});
|
||||
}
|
||||
|
||||
self.primary()
|
||||
}
|
||||
|
||||
fn primary(&mut self) -> LoxResult<Expr> {
|
||||
match self.peek().token_type {
|
||||
TokenType::False => {
|
||||
self.advance();
|
||||
Ok(Expr::Literal {
|
||||
value: LiteralValue::Boolean(false),
|
||||
})
|
||||
}
|
||||
TokenType::True => {
|
||||
self.advance();
|
||||
Ok(Expr::Literal {
|
||||
value: LiteralValue::Boolean(true),
|
||||
})
|
||||
}
|
||||
TokenType::Nil => {
|
||||
self.advance();
|
||||
Ok(Expr::Literal {
|
||||
value: LiteralValue::Nil,
|
||||
})
|
||||
}
|
||||
TokenType::Number => {
|
||||
self.advance();
|
||||
let token = self.previous();
|
||||
if let Some(literal) = &token.literal {
|
||||
Ok(Expr::Literal {
|
||||
value: literal.clone(),
|
||||
})
|
||||
} else {
|
||||
Err(self.error(token, "Expected number literal").into())
|
||||
}
|
||||
}
|
||||
TokenType::String => {
|
||||
self.advance();
|
||||
let token = self.previous();
|
||||
if let Some(literal) = &token.literal {
|
||||
Ok(Expr::Literal {
|
||||
value: literal.clone(),
|
||||
})
|
||||
} else {
|
||||
Err(self.error(token, "Expected string literal").into())
|
||||
}
|
||||
}
|
||||
TokenType::LeftParen => {
|
||||
self.advance();
|
||||
let expr = self.expression()?;
|
||||
self.consume(TokenType::RightParen, "Expect ')' after expression.")?;
|
||||
Ok(Expr::Grouping {
|
||||
expression: Box::new(expr),
|
||||
})
|
||||
}
|
||||
TokenType::Identifier => {
|
||||
let name = self.peek().lexeme.clone();
|
||||
self.advance();
|
||||
Ok(Expr::Variable { name: name })
|
||||
}
|
||||
_ => Err(self.error(self.peek(), "Expect expression.").into()),
|
||||
}
|
||||
}
|
||||
|
||||
fn is_at_end(&self) -> bool {
|
||||
if self.current >= self.tokens.len() {
|
||||
true
|
||||
} else {
|
||||
self.tokens[self.current].token_type == TokenType::Eof
|
||||
}
|
||||
}
|
||||
|
||||
fn advance(&mut self) -> &Token {
|
||||
if !self.is_at_end() {
|
||||
self.current += 1;
|
||||
}
|
||||
self.peek()
|
||||
}
|
||||
|
||||
fn peek(&self) -> &Token {
|
||||
if self.is_at_end() {
|
||||
&self.tokens.last().unwrap()
|
||||
} else {
|
||||
&self.tokens[self.current]
|
||||
}
|
||||
}
|
||||
|
||||
fn peek_next(&self) -> &Token {
|
||||
if self.is_at_end() {
|
||||
&self.peek()
|
||||
} else {
|
||||
&self.tokens[self.current + 1]
|
||||
}
|
||||
}
|
||||
|
||||
fn previous(&self) -> &Token {
|
||||
&self.tokens[self.current - 1]
|
||||
}
|
||||
|
||||
fn consume(&mut self, token_type: TokenType, message: &str) -> LoxResult<&Token> {
|
||||
if self.peek().token_type == token_type {
|
||||
self.advance();
|
||||
Ok(self.previous())
|
||||
} else {
|
||||
Err(self.error(self.peek(), message).into())
|
||||
}
|
||||
}
|
||||
|
||||
fn error(&self, token: &Token, message: &str) -> LoxError {
|
||||
LoxError::ParseError {
|
||||
source_slice: token.source_slice.clone(),
|
||||
message: message.to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
fn synchronize(&mut self) {
|
||||
self.advance();
|
||||
|
||||
while !self.is_at_end() {
|
||||
if self.previous().token_type == TokenType::Semicolon {
|
||||
return;
|
||||
}
|
||||
|
||||
match self.peek().token_type {
|
||||
TokenType::Class
|
||||
| TokenType::Fun
|
||||
| TokenType::Var
|
||||
| TokenType::For
|
||||
| TokenType::If
|
||||
| TokenType::While
|
||||
| TokenType::Print
|
||||
| TokenType::Return => return,
|
||||
_ => {}
|
||||
}
|
||||
|
||||
self.advance();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user