From fc345f2ffbab0de7c222289ade37c90422a80443 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emmanuel=20Beno=C3=AEt?= Date: Sat, 31 Dec 2022 00:50:31 +0100 Subject: [PATCH] Parser - Parse expressions --- src/main.rs | 9 ++- src/parser.rs | 156 +++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 162 insertions(+), 3 deletions(-) diff --git a/src/main.rs b/src/main.rs index 8cc4cc1..ecd5cd6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -10,6 +10,7 @@ use std::{ process::ExitCode, }; +use ast::AstDumper; use errors::ErrorHandler; use parser::Parser; use scanner::Scanner; @@ -25,7 +26,13 @@ fn run(source: String) -> ErrorHandler { println!("{:#?}", token); } - let _parser = Parser::new(tokens); + let parser = Parser::new(tokens); + match parser.parse(&mut error_handler) { + None => (), + Some(ast) => { + println!("AST generated ! {}", ast.dump()) + } + } error_handler } diff --git a/src/parser.rs b/src/parser.rs index aa28eef..f6970de 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -1,12 +1,164 @@ -use crate::tokens::Token; +use crate::{ + ast, + errors::{ErrorHandler, ParserError}, + tokens::{Token, TokenType}, +}; #[derive(Debug)] pub struct Parser { tokens: Vec, + current: usize, } impl Parser { pub fn new(tokens: Vec) -> Self { - Self { tokens } + Self { tokens, current: 0 } + } + + pub fn parse(mut self, err_hdl: &mut ErrorHandler) -> Option { + match self.parse_expression() { + Ok(expr) => Some(expr), + Err(e) => { + e.report(err_hdl); + None + } + } + } + + fn parse_expression(&mut self) -> Result { + self.parse_equality() + } + + fn parse_equality(&mut self) -> Result { + let mut expr = self.parse_comparison()?; + while let Some(operator) = self.expect(&[TokenType::BangEqual, TokenType::EqualEqual]) { + let right = self.parse_comparison()?; + expr = ast::ExprNode::Binary { + left: Box::new(expr), + operator: operator.clone(), + right: Box::new(right), + }; + } + Ok(expr) + } + + fn parse_comparison(&mut self) -> Result { + let mut expr = self.parse_term()?; + while let Some(operator) = self.expect(&[ + TokenType::Greater, + TokenType::GreaterEqual, + TokenType::Less, + TokenType::LessEqual, + ]) { + let right = self.parse_term()?; + expr = ast::ExprNode::Binary { + left: Box::new(expr), + operator: operator.clone(), + right: Box::new(right), + }; + } + Ok(expr) + } + + fn parse_term(&mut self) -> Result { + let mut expr = self.parse_factor()?; + while let Some(operator) = self.expect(&[TokenType::Minus, TokenType::Plus]) { + let right = self.parse_factor()?; + expr = ast::ExprNode::Binary { + left: Box::new(expr), + operator: operator.clone(), + right: Box::new(right), + }; + } + Ok(expr) + } + + fn parse_factor(&mut self) -> Result { + let mut expr = self.parse_unary()?; + while let Some(operator) = self.expect(&[TokenType::Slash, TokenType::Star]) { + let right = self.parse_unary()?; + expr = ast::ExprNode::Binary { + left: Box::new(expr), + operator: operator.clone(), + right: Box::new(right), + }; + } + Ok(expr) + } + + fn parse_unary(&mut self) -> Result { + if let Some(operator) = self.expect(&[TokenType::Bang, TokenType::Minus]) { + Ok(ast::ExprNode::Unary { + operator: operator.clone(), + right: Box::new(self.parse_unary()?), + }) + } else { + self.parse_primary() + } + } + + fn parse_primary(&mut self) -> Result { + if self.expect(&[TokenType::LeftParen]).is_some() { + let expr = self.parse_expression()?; + self.consume(&TokenType::RightParen, "expected ')' after expression")?; + Ok(ast::ExprNode::Grouping { + expression: Box::new(expr), + }) + } else if let Some(token) = + self.expect(&[TokenType::False, TokenType::True, TokenType::Nil]) + { + Ok(ast::ExprNode::Litteral { value: token }) + } else { + match &self.peek().token_type { + TokenType::Number(_) | &TokenType::String(_) => Ok(ast::ExprNode::Litteral { + value: self.advance().clone(), + }), + _ => Err(ParserError::new(self.peek(), "expected expression")), + } + } + } + + fn expect(&mut self, accepts: &[TokenType]) -> Option { + for tt in accepts { + if self.check(tt) { + return Some(self.advance().clone()); + } + } + None + } + + fn consume(&mut self, token_type: &TokenType, error: &str) -> Result<&Token, ParserError> { + if self.check(token_type) { + Ok(self.advance()) + } else { + Err(ParserError::new(self.peek(), error)) + } + } + + fn check(&self, token_type: &TokenType) -> bool { + if self.is_at_end() { + false + } else { + &self.peek().token_type == token_type + } + } + + fn advance(&mut self) -> &Token { + if !self.is_at_end() { + self.current += 1 + } + self.previous() + } + + fn is_at_end(&self) -> bool { + self.peek().token_type == TokenType::EOF + } + + fn peek(&self) -> &Token { + &self.tokens[self.current] + } + + fn previous(&self) -> &Token { + &self.tokens[self.current - 1] } }