Parseur d'expression et affichage du résultat avec l'ASTPrinter.

This commit is contained in:
2024-05-16 22:45:40 +02:00
parent 72ef4e3bbf
commit b4d2170eb4
4 changed files with 230 additions and 10 deletions

215
src/parser.rs Normal file
View File

@@ -0,0 +1,215 @@
use crate::expr::{Binary, Expr, Grouping, Unary};
use crate::expr::Literal::{LiteralBool, LiteralNumber, LiteralString};
use crate::token::Token;
use crate::token_type::TokenType;
pub struct Parser {
tokens: Vec<Token>,
current: usize
}
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<(), ParseError> {
if self.check(token_type) {
self.advance();
return Ok(());
}
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.equality()
}
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::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.")
})
}
}
pub fn parse(&mut self) -> Option<Expr> {
match self.expression() {
Ok(expr) => Some(expr),
Err(error) => {
println!("Error while parsing expression : {}",error.message);
None
}
}
}
}