From fc345f2ffbab0de7c222289ade37c90422a80443 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Emmanuel=20Beno=C3=AEt?= <tseeker@nocternity.net>
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<Token>,
+    current: usize,
 }
 
 impl Parser {
     pub fn new(tokens: Vec<Token>) -> Self {
-        Self { tokens }
+        Self { tokens, current: 0 }
+    }
+
+    pub fn parse(mut self, err_hdl: &mut ErrorHandler) -> Option<ast::ExprNode> {
+        match self.parse_expression() {
+            Ok(expr) => Some(expr),
+            Err(e) => {
+                e.report(err_hdl);
+                None
+            }
+        }
+    }
+
+    fn parse_expression(&mut self) -> Result<ast::ExprNode, ParserError> {
+        self.parse_equality()
+    }
+
+    fn parse_equality(&mut self) -> Result<ast::ExprNode, ParserError> {
+        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<ast::ExprNode, ParserError> {
+        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<ast::ExprNode, ParserError> {
+        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<ast::ExprNode, ParserError> {
+        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<ast::ExprNode, ParserError> {
+        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<ast::ExprNode, ParserError> {
+        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<Token> {
+        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]
     }
 }