301 lines
8.9 KiB
Rust
301 lines
8.9 KiB
Rust
use crate::expr::{Assign, Binary, Expr, Grouping, Unary, Variable};
|
|
use crate::expr::Literal::{LiteralBool, LiteralNumber, LiteralString};
|
|
use crate::token::Token;
|
|
use crate::token_type::TokenType;
|
|
use crate::stmt::{BlockStatement, ExpressionStatement, PrintStatement, Statement, VarStatement};
|
|
|
|
pub struct Parser {
|
|
tokens: Vec<Token>,
|
|
current: usize
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub struct ParseError {
|
|
message: String
|
|
}
|
|
|
|
impl Parser {
|
|
pub fn new( t_init: Vec<Token >) -> Self {
|
|
Parser {
|
|
tokens: t_init,
|
|
current: 0
|
|
}
|
|
}
|
|
|
|
fn match_token( &mut self, token_type_list: &[TokenType] ) -> bool {
|
|
for token_type in token_type_list {
|
|
if self.check(token_type) {
|
|
self.advance();
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
fn check(&self, token_type: &TokenType) -> bool {
|
|
if self.is_at_end() {
|
|
return false;
|
|
}
|
|
|
|
return self.peek().token_type==*token_type;
|
|
}
|
|
|
|
fn advance(&mut self) -> Token {
|
|
if !self.is_at_end() {
|
|
self.current += 1;
|
|
}
|
|
return self.previous();
|
|
}
|
|
|
|
fn is_at_end(&self) -> bool {
|
|
return self.peek().token_type==TokenType::Eof;
|
|
}
|
|
|
|
fn peek(&self) -> Token {
|
|
return self.tokens[self.current].clone();
|
|
}
|
|
|
|
fn previous(&self) -> Token {
|
|
return self.tokens[self.current - 1].clone();
|
|
}
|
|
|
|
fn consume(&mut self, token_type: &TokenType, message: String) -> Result<Token, ParseError> {
|
|
if self.check(token_type) {
|
|
Ok(self.advance())
|
|
} else {
|
|
Err(ParseError { message })
|
|
}
|
|
}
|
|
|
|
fn synchronise(&mut self) {
|
|
self.advance();
|
|
|
|
while !self.is_at_end() {
|
|
if self.previous().token_type == TokenType::Semicolon {
|
|
return;
|
|
}
|
|
|
|
match self.peek().token_type {
|
|
TokenType::Class => return,
|
|
TokenType::Fun => return,
|
|
TokenType::Var => return,
|
|
TokenType::For => return,
|
|
TokenType::If => return,
|
|
TokenType::While => return,
|
|
TokenType::Print => return,
|
|
TokenType::Return => return,
|
|
_ => (),
|
|
}
|
|
|
|
self.advance();
|
|
}
|
|
}
|
|
|
|
fn expression(&mut self) -> Result<Expr, ParseError> {
|
|
self.assignment()
|
|
}
|
|
|
|
fn assignment(&mut self) -> Result<Expr, ParseError> {
|
|
let expr = self.equality()?;
|
|
|
|
if self.match_token(&[TokenType::Equal]) {
|
|
let value = Box::new(self.assignment()?); // l'assignation a une associativité par la droite
|
|
|
|
match expr {
|
|
Expr::VariableExpr(v) => {
|
|
Ok( Expr::AssignExpr(Assign { name: v.name, value }))
|
|
}
|
|
_ => Err(ParseError { message: String::from("Invalid assignment target") })
|
|
}
|
|
} else {
|
|
Ok(expr)
|
|
}
|
|
}
|
|
|
|
fn equality(&mut self) -> Result<Expr, ParseError> {
|
|
let mut expr: Expr = self.comparison()?;
|
|
|
|
while self.match_token( &[TokenType::BangEqual, TokenType::EqualEqual]) {
|
|
let operator: Token = self.previous();
|
|
let right: Expr = self.comparison()?;
|
|
expr = Expr::BinaryExpr(Binary{
|
|
left: Box::new(expr),
|
|
operator,
|
|
right: Box::new(right)
|
|
});
|
|
}
|
|
|
|
return Ok(expr);
|
|
}
|
|
|
|
fn comparison(&mut self) -> Result<Expr, ParseError> {
|
|
let mut expr = self.term()?;
|
|
|
|
while self.match_token(&[TokenType::Greater, TokenType::GreaterEqual, TokenType::Less, TokenType::LessEqual]) {
|
|
let operator = self.previous();
|
|
let right = self.term()?;
|
|
expr = Expr::BinaryExpr(Binary{
|
|
left: Box::new(expr),
|
|
operator,
|
|
right: Box::new(right)
|
|
});
|
|
}
|
|
|
|
return Ok(expr);
|
|
}
|
|
|
|
fn term(&mut self) -> Result<Expr,ParseError> {
|
|
let mut expr = self.factor()?;
|
|
|
|
while self.match_token(&[TokenType::Minus, TokenType::Plus]) {
|
|
let operator = self.previous();
|
|
let right = self.factor()?;
|
|
expr = Expr::BinaryExpr(Binary{
|
|
left: Box::new(expr),
|
|
operator,
|
|
right: Box::new(right)
|
|
});
|
|
}
|
|
|
|
return Ok(expr);
|
|
}
|
|
|
|
fn factor(&mut self) -> Result<Expr,ParseError> {
|
|
let mut expr = self.unary()?;
|
|
|
|
while self.match_token(&[TokenType::Star, TokenType::Slash]) {
|
|
let operator = self.previous();
|
|
let right = self.unary()?;
|
|
expr = Expr::BinaryExpr(Binary{
|
|
left: Box::new(expr),
|
|
operator,
|
|
right: Box::new(right)
|
|
});
|
|
}
|
|
|
|
return Ok(expr);
|
|
}
|
|
|
|
fn unary(&mut self) -> Result<Expr,ParseError> {
|
|
if self.match_token(&[TokenType::Bang, TokenType::Minus]) {
|
|
let operator = self.previous();
|
|
let right = self.unary()?;
|
|
return Ok(Expr::UnaryExpr(Unary {
|
|
operator,
|
|
right: Box::new(right)
|
|
}));
|
|
}
|
|
|
|
self.primary()
|
|
}
|
|
|
|
fn primary(&mut self) -> Result<Expr,ParseError> {
|
|
if self.match_token(&[TokenType::False]) {
|
|
return Ok(Expr::LiteralExpr(LiteralBool(false)));
|
|
}
|
|
if self.match_token(&[TokenType::True]) {
|
|
return Ok(Expr::LiteralExpr(LiteralBool(true)));
|
|
}
|
|
if self.match_token(&[TokenType::Nil]) {
|
|
return Ok(Expr::LiteralExpr(LiteralBool(false)));
|
|
}
|
|
if self.match_token(&[TokenType::Number]) {
|
|
return Ok(Expr::LiteralExpr(LiteralNumber(self.previous().literal.parse::<f64>().unwrap())));
|
|
}
|
|
if self.match_token(&[TokenType::String]) {
|
|
return Ok(Expr::LiteralExpr(LiteralString(self.previous().literal)));
|
|
}
|
|
if self.match_token(&[TokenType::Identifier]) {
|
|
return Ok(Expr::VariableExpr(Variable { name: self.previous() } ));
|
|
}
|
|
|
|
if self.match_token(&[TokenType::LeftParen]) {
|
|
let expr = self.expression()?;
|
|
self.consume(&TokenType::RightParen, String::from("Expect ')' after expression."))?;
|
|
return Ok(Expr::GroupingExpr(Grouping {
|
|
expression: Box::new(expr)
|
|
}));
|
|
} else {
|
|
Err(ParseError {
|
|
message: String::from("Unexpected token : expression expected.")
|
|
})
|
|
}
|
|
}
|
|
|
|
fn statement(&mut self) -> Result<Statement, ParseError> {
|
|
if self.match_token(&[TokenType::Print]) {
|
|
return self.print_statement();
|
|
}
|
|
|
|
if self.match_token(&[TokenType::LeftBrace]) {
|
|
return self.block_statement();
|
|
}
|
|
|
|
self.expr_statement()
|
|
}
|
|
|
|
fn block_statement(&mut self) -> Result<Statement, ParseError> {
|
|
let mut statements: Vec<Statement> = Vec::new();
|
|
|
|
while !self.check(&TokenType::RightBrace) && !self.is_at_end() {
|
|
statements.push(self.declaration()?);
|
|
}
|
|
|
|
self.consume(&TokenType::RightBrace, String::from("Expect '}' after block"))?;
|
|
|
|
Ok(Statement::Block(BlockStatement::new(statements)))
|
|
}
|
|
|
|
fn print_statement(&mut self) -> Result<Statement, ParseError> {
|
|
match self.expression() {
|
|
Ok(e) => {
|
|
self.consume(&TokenType::Semicolon, String::from("; attendu"))?;
|
|
Ok(Statement::Print(PrintStatement{ expr: e }))
|
|
}
|
|
Err(e ) => { Err(e) }
|
|
}
|
|
}
|
|
|
|
fn expr_statement(&mut self) -> Result<Statement, ParseError> {
|
|
match self.expression() {
|
|
Ok(e) => {
|
|
self.consume(&TokenType::Semicolon, String::from("; attendu"))?;
|
|
Ok(Statement::Expression(ExpressionStatement{ expr: e }))
|
|
}
|
|
Err(e ) => { Err(e) }
|
|
}
|
|
}
|
|
|
|
fn declaration(&mut self) -> Result<Statement, ParseError> {
|
|
if self.match_token(&[TokenType::Var]) {
|
|
self.var_declaration()
|
|
} else {
|
|
self.statement()
|
|
}
|
|
}
|
|
|
|
fn var_declaration(&mut self) -> Result<Statement, ParseError> {
|
|
let name = self.consume(&TokenType::Identifier, String::from("nom de variable attendu"))?;
|
|
|
|
let mut initializer: Option<Expr> = None;
|
|
if self.match_token(&[TokenType::Equal]) {
|
|
initializer = Some(self.expression()?);
|
|
}
|
|
|
|
self.consume(&TokenType::Semicolon, String::from("; attendu"))?;
|
|
Ok(Statement::Var(VarStatement{ token: name, initializer }))
|
|
}
|
|
|
|
pub fn parse(&mut self) -> Vec<Statement> {
|
|
let mut statements= Vec::new();
|
|
while !self.is_at_end() {
|
|
match self.declaration() {
|
|
Ok(stmt) => statements.push(stmt),
|
|
Err(_e) => self.synchronise(),
|
|
}
|
|
}
|
|
|
|
statements
|
|
}
|
|
} |