expr_solver/
parser.rs

1use std::vec;
2
3use crate::ast::AST;
4use crate::lexer::Lexer;
5use crate::token::Token;
6
7// Top level parser.
8// parses linear array of tokens into AST.
9pub struct Parser<'a> {
10    lexer: &'a mut Lexer,
11}
12
13impl<'a> Parser<'a> {
14    // constructor for parser.
15    pub fn new(lexer: &'a mut Lexer) -> Self {
16        log::debug!("[expr-solver] Creating new parser instance.");
17        Self { lexer }
18    }
19
20    // public parse method.
21    pub fn parse(&mut self) -> Result<AST, String> {
22        log::debug!("[expr-solver] starting parsing.");
23        // we start with binding power of 0.
24        match self.expr(0) {
25            Ok(ast) => {
26                log::debug!("Parsed to ast:\n{}", ast);
27                Ok(ast)
28            }
29            Err(e) => {
30                log::debug!("Failed to parse AST.");
31                Err(e)
32            }
33        }
34    }
35
36    /// Parses an expression using Operator-Precedence parse (Pratt Parsing)
37    /// ref : https://en.wikipedia.org/wiki/Operator-precedence_parser
38    /// # Arguments
39    /// * min_binding_power - minimum binding power till recursivel parse the expression.
40    /// # Returns
41    /// * AST - ast of the expression.
42    fn expr(&mut self, min_binding_power: u8) -> Result<AST, String> {
43        // Parsing left hand side of the expression.
44        let mut left_hand_side = match self.lexer.next_token() {
45            // if the token is a number we simply create a node out of it.
46            Token::Number(f) => AST::Node(Token::Number(f)),
47
48            // if we reached the end we panic.
49            Token::Eof => return Err("Unexpected token : EOF".to_string()),
50
51            // if grouping, the AST can be treated as primary expression.
52            Token::LeftParen => {
53                let lhs = match self.expr(0) {
54                    Ok(lhs) => lhs,
55                    Err(e) => return Err(e),
56                };
57
58                if !matches!(self.lexer.next_token(), Token::RightParen) {
59                    return Err("Expected ')' after expression.".to_string());
60                }
61
62                lhs
63            }
64
65            // if its a operator, then it means the operator is a unary.
66            operator => {
67                // we get the right binding power of the unary operator.
68                let ((), right_binding_power) = Parser::prefix_binding_power(operator);
69
70                // then recursively parse it.
71                match self.expr(right_binding_power) {
72                    // save if its safe.
73                    Ok(right_hand_side) => AST::Con(operator, vec![right_hand_side]),
74                    // return if err.
75                    Err(err) => return Err(err),
76                }
77            }
78        };
79
80        loop {
81            // Operator: Infix operator.
82            let operator = match self.lexer.peek() {
83                // shouldn't be a number, obviously.
84                Token::Number(n) => return Err(format!("Expected operator recieved number : {n}")),
85
86                // also shouldn't end.
87                Token::Eof => break,
88
89                // take the operator.
90                op => op,
91            };
92
93            // get the left binding power of the postfix operator.
94            if let Some((left_bp, ())) = Parser::postfix_binding_power(operator) {
95                // we break the loop when precendence of the current left binding
96                // power of the postfix operator is less than minimum binding power.
97                if left_bp < min_binding_power {
98                    break;
99                }
100                self.lexer.next_token();
101
102                left_hand_side = AST::Con(operator, vec![left_hand_side]);
103
104                // we need to skip the current iteration.
105                continue;
106            }
107
108            // get the left binding power and right binding power of this infix operator.
109            if let Some((left_bp, right_bp)) = Parser::infix_binding_power(operator) {
110                // ends recursion when the minimum binding power for this
111                // expr function call is less then left binding power of the current operator.
112                if left_bp < min_binding_power {
113                    break;
114                }
115
116                // consume operator token.
117                self.lexer.next_token();
118
119                // recurisvely call expr to parse right hand side of the expression.
120                match self.expr(right_bp) {
121                    Ok(right_hand_side) => {
122                        // create ast.
123                        left_hand_side = AST::Con(operator, vec![left_hand_side, right_hand_side]);
124                    }
125                    Err(err) => return Err(err),
126                }
127
128                continue;
129            }
130
131            // break the loop if none of the above cases are met.
132            break;
133        }
134
135        // return the created AST.
136        Ok(left_hand_side)
137    }
138
139    /// Gets the infix binding power of a operator.
140    /// # Arguments
141    /// * token - the operator token.
142    /// # Returns
143    /// * (left, right) - left and right infix binding power of the operator.
144    fn infix_binding_power(token: Token) -> Option<(u8, u8)> {
145        let power = match token {
146            Token::Plus => (1, 2),
147            Token::Minus => (1, 2),
148            Token::Star => (3, 4),
149            Token::Slash => (3, 4),
150
151            // basically unreachable.
152            _ => return None,
153        };
154
155        Some(power)
156    }
157
158    /// Gets the postfix binding power of a operator.
159    /// # Arguments
160    /// * token - the operator token.
161    /// # Returns
162    /// * (left, ())) - left postfix binding power of the operator.
163    fn postfix_binding_power(token: Token) -> Option<(u8, ())> {
164        let power = match token {
165            Token::Bang => (6, ()),
166
167            // basically unreachable.
168            _ => return None,
169        };
170
171        Some(power)
172    }
173
174    /// Gets the prefix binding power of a unary operators.
175    /// # Arguments
176    /// * token - the operator token.
177    /// # Returns
178    /// * ((), right) - right prefix binding power of the operator.
179    fn prefix_binding_power(token: Token) -> ((), u8) {
180        match token {
181            Token::Minus | Token::Plus => ((), 5),
182
183            // basically unreachable.
184            t => panic!("Cannot get infix binding power of {t}"),
185        }
186    }
187}