roan_ast/parser/
expressions.rs

1use crate::{
2    AssignOperator, BinOpAssociativity, BinOpKind, BinOperator, Expr, ParseContext, Parser, Stmt,
3    Token, TokenKind, TypeAnnotation, UnOpKind, UnOperator,
4};
5use indexmap::IndexMap;
6use roan_error::error::RoanError::{ExpectedToken, UnexpectedToken};
7use tracing::debug;
8
9impl Parser {
10    /// Parses any expression, starting with an assignment.
11    ///
12    /// This method serves as the entry point for expression parsing.
13    ///
14    /// # Returns
15    /// - `Ok(Expr)`: The parsed expression if successful.
16    /// - `Err(anyhow::Error)`: An error if parsing fails.
17    pub fn parse_expr(&mut self) -> anyhow::Result<Expr> {
18        self.parse_assignment()
19    }
20
21    /// Parses an expression statement.
22    ///
23    /// This method parses an expression and checks for a semicolon to terminate the statement.
24    ///
25    /// # Returns
26    /// - `Ok(Stmt)`: The expression statement if successful.
27    /// - `Err(anyhow::Error)`: An error if parsing fails.
28    pub fn expression_stmt(&mut self) -> anyhow::Result<Stmt> {
29        let expr = self.parse_expr()?;
30
31        self.possible_check(TokenKind::Semicolon);
32
33        Ok(expr.into())
34    }
35
36    /// Parses a binary expression.
37    ///
38    /// This method first parses a unary expression and then handles the binary operators in the expression.
39    ///
40    /// # Returns
41    /// - `Ok(Expr)`: The parsed binary expression if successful.
42    /// - `Err(anyhow::Error)`: An error if parsing fails.
43    pub fn parse_binary_expression(&mut self) -> anyhow::Result<Expr> {
44        let left = self.parse_unary_expression()?;
45        self.parse_binary_expression_recurse(left, 0)
46    }
47
48    /// Attempts to parse a binary operator.
49    ///
50    /// This method checks the next token to see if it's a binary operator and returns it if found.
51    ///
52    /// # Returns
53    /// - `Some(BinOperator)`: The parsed binary operator if found.
54    /// - `None`: If no binary operator is found.
55    fn parse_binary_operator(&mut self) -> Option<BinOperator> {
56        let token = self.peek();
57        let kind = match token.kind {
58            TokenKind::Plus => Some(BinOpKind::Plus),
59            TokenKind::Minus => Some(BinOpKind::Minus),
60            TokenKind::Asterisk => Some(BinOpKind::Multiply),
61            TokenKind::Slash => Some(BinOpKind::Divide),
62            TokenKind::Ampersand => Some(BinOpKind::BitwiseAnd),
63            TokenKind::Pipe => Some(BinOpKind::BitwiseOr),
64            TokenKind::Caret => Some(BinOpKind::BitwiseXor),
65            TokenKind::DoubleAsterisk => Some(BinOpKind::Power),
66            TokenKind::EqualsEquals => Some(BinOpKind::Equals),
67            TokenKind::BangEquals => Some(BinOpKind::BangEquals),
68            TokenKind::LessThan => Some(BinOpKind::LessThan),
69            TokenKind::LessThanEquals => Some(BinOpKind::LessThanOrEqual),
70            TokenKind::GreaterThan => Some(BinOpKind::GreaterThan),
71            TokenKind::GreaterThanEquals => Some(BinOpKind::GreaterThanOrEqual),
72            TokenKind::Percent => Some(BinOpKind::Modulo),
73            TokenKind::And => Some(BinOpKind::And),
74            TokenKind::Or => Some(BinOpKind::Or),
75            TokenKind::Increment => Some(BinOpKind::Increment),
76            TokenKind::Decrement => Some(BinOpKind::Decrement),
77            TokenKind::DoubleGreaterThan => Some(BinOpKind::ShiftRight),
78            TokenKind::DoubleLessThan => Some(BinOpKind::ShiftLeft),
79            _ => None,
80        };
81        kind.map(|kind| BinOperator::new(kind, token.clone()))
82    }
83
84    /// Parses binary expressions recursively, handling operator precedence and associativity.
85    ///
86    /// This method continues to parse binary expressions until no further valid operators are found.
87    ///
88    /// # Parameters
89    /// - `left`: The left-hand side expression.
90    /// - `precedence`: The precedence of the operator being processed.
91    ///
92    /// # Returns
93    /// - `Ok(Expr)`: The final parsed expression if successful.
94    /// - `Err(anyhow::Error)`: An error if parsing fails.
95    pub fn parse_binary_expression_recurse(
96        &mut self,
97        mut left: Expr,
98        precedence: u8,
99    ) -> anyhow::Result<Expr> {
100        while let Some(operator) = self.parse_binary_operator() {
101            let operator_precedence = operator.precedence();
102            if operator_precedence < precedence {
103                break;
104            }
105
106            self.consume();
107
108            let mut right = self.parse_unary_expression()?;
109
110            while let Some(next_operator) = self.parse_binary_operator() {
111                let next_precedence = next_operator.precedence();
112
113                if next_precedence > operator_precedence
114                    || (next_precedence == operator_precedence
115                        && next_operator.associativity() == BinOpAssociativity::Right)
116                {
117                    right = self.parse_binary_expression_recurse(right, next_precedence)?;
118                } else {
119                    break;
120                }
121            }
122
123            left = Expr::new_binary(left, operator, right);
124        }
125
126        Ok(left)
127    }
128
129    /// Attempts to parse a unary operator.
130    ///
131    /// This method checks the next token to see if it's a unary operator and returns it if found.
132    ///
133    /// # Returns
134    /// - `Some(UnOperator)`: The parsed unary operator if found.
135    /// - `None`: If no unary operator is found.
136    pub fn parse_unary_operator(&mut self) -> Option<UnOperator> {
137        let token = self.peek();
138        let kind = match token.kind {
139            TokenKind::Minus => Some(UnOpKind::Minus),
140            TokenKind::Tilde => Some(UnOpKind::BitwiseNot),
141            TokenKind::Bang => Some(UnOpKind::LogicalNot),
142            _ => None,
143        };
144        kind.map(|kind| UnOperator::new(kind, token.clone()))
145    }
146
147    /// Parses a unary expression, handling unary operators.
148    ///
149    /// This method checks for a unary operator and processes the operand accordingly.
150    ///
151    /// # Returns
152    /// - `Ok(Expr)`: The parsed unary expression if successful.
153    /// - `Err(anyhow::Error)`: An error if parsing fails.
154    pub fn parse_unary_expression(&mut self) -> anyhow::Result<Expr> {
155        if let Some(operator) = self.parse_unary_operator() {
156            let token = self.consume();
157            let operand = self.parse_unary_expression()?;
158            return Ok(Expr::new_unary(operator, operand, token));
159        }
160        self.parse_access_expression()
161    }
162
163    /// Parses an access expression.
164    pub fn parse_access_expression(&mut self) -> anyhow::Result<Expr> {
165        debug!("Parsing access expression");
166        let mut expr = self.parse_primary_expression()?;
167        let mut token = self.peek();
168
169        loop {
170            if token.kind == TokenKind::Dot {
171                self.consume();
172
173                let field_token = self.consume();
174                let mut field_expr = Expr::new_variable(field_token.clone(), field_token.literal());
175
176                if self.peek().kind == TokenKind::LeftParen {
177                    field_expr = self.parse_call_expr(field_token)?;
178                }
179
180                expr = Expr::new_field_access(expr, field_expr, token);
181            } else if token.kind == TokenKind::LeftBracket {
182                self.consume();
183                let index = self.parse_expr()?;
184                self.expect(TokenKind::RightBracket)?;
185                expr = Expr::new_index_access(expr, index, token);
186            } else if token.kind == TokenKind::DoubleColon {
187                let colons = self.consume();
188                let field = self.parse_expr()?;
189
190                expr = Expr::new_static_method_access(expr, field, colons);
191            } else {
192                break;
193            }
194            token = self.peek();
195        }
196
197        Ok(expr)
198    }
199
200    /// Parses a struct constructor expression.
201    ///
202    /// This method expects an identifier followed by a left brace and a list of field assignments.
203    ///
204    /// # Parameters
205    /// - `identifier`: The token representing the struct name.
206    ///
207    /// # Returns
208    /// - `Ok(Expr)`: The parsed struct constructor expression if successful.
209    /// - `Err(anyhow::Error)`: An error if parsing fails.
210    pub fn parse_struct_constructor(&mut self, identifier: Token) -> anyhow::Result<Expr> {
211        self.expect(TokenKind::LeftBrace)?;
212
213        let mut fields = vec![];
214
215        while self.peek().kind != TokenKind::RightBrace && !self.is_eof() {
216            let field_name = self.consume();
217            self.expect(TokenKind::Colon)?;
218            let field_value = self.parse_expr()?;
219
220            fields.push((field_name.literal(), field_value));
221
222            if self.peek().kind != TokenKind::RightBrace {
223                self.expect(TokenKind::Comma)?;
224            }
225        }
226
227        self.expect(TokenKind::RightBrace)?;
228
229        Ok(Expr::new_struct_constructor(
230            identifier.literal(),
231            fields,
232            identifier,
233        ))
234    }
235
236    /// Parses a primary expression, such as literals, identifiers, or parenthesized expressions.
237    ///
238    /// # Returns
239    /// - `Ok(Expr)`: The parsed primary expression if successful.
240    /// - `Err(anyhow::Error)`: An error if parsing fails.
241    pub fn parse_primary_expression(&mut self) -> anyhow::Result<Expr> {
242        let token = self.consume();
243
244        match &token.kind {
245            TokenKind::Integer(int) => Ok(Expr::new_integer(token.clone(), *int)),
246            TokenKind::Float(float) => Ok(Expr::new_float(token.clone(), *float)),
247            TokenKind::Null => Ok(Expr::new_null(token)),
248            TokenKind::True | TokenKind::False => {
249                Ok(Expr::new_bool(token.clone(), token.as_bool().unwrap()))
250            }
251            TokenKind::TripleDot => Ok(Expr::new_spread(token.clone(), self.parse_expr()?)),
252            TokenKind::LeftBracket => self.parse_vector(),
253            TokenKind::LeftBrace => {
254                let mut fields: IndexMap<String, Expr> = IndexMap::new();
255
256                while self.peek().kind != TokenKind::RightBrace && !self.is_eof() {
257                    let field_name = {
258                        if matches!(self.peek().kind, TokenKind::String(_)) {
259                            self.consume()
260                        } else {
261                            return Err(ExpectedToken(
262                                "string literal".to_string(),
263                                "Field names in objects must be string literals.".to_string(),
264                                self.peek().span.clone(),
265                            )
266                            .into());
267                        }
268                    };
269
270                    self.expect(TokenKind::Colon)?;
271                    let field_value = self.parse_expr()?;
272
273                    fields.insert(
274                        field_name
275                            .literal()
276                            .strip_prefix("\"")
277                            .unwrap()
278                            .strip_suffix("\"")
279                            .unwrap()
280                            .to_string(),
281                        field_value,
282                    );
283
284                    if self.peek().kind != TokenKind::RightBrace {
285                        self.expect(TokenKind::Comma)?;
286                    }
287                }
288
289                let closing_brace = self.expect(TokenKind::RightBrace)?;
290
291                Ok(Expr::new_object(fields, (token, closing_brace)))
292            }
293            TokenKind::Identifier => {
294                debug!("Parsing identifier: {}", token.literal());
295
296                if self.peek().kind == TokenKind::LeftParen {
297                    self.parse_call_expr(token)
298                } else if self.peek().kind == TokenKind::LeftBrace {
299                    if self.is_context(&ParseContext::Normal) {
300                        self.parse_struct_constructor(token)
301                    } else {
302                        Ok(Expr::new_variable(token.clone(), token.literal()))
303                    }
304                } else {
305                    Ok(Expr::new_variable(token.clone(), token.literal()))
306                }
307            }
308            TokenKind::LeftParen => {
309                let expr = self.parse_expr()?;
310
311                self.expect(TokenKind::RightParen)?;
312
313                Ok(Expr::new_parenthesized(expr))
314            }
315            TokenKind::String(s) => Ok(Expr::new_string(token.clone(), s.clone())),
316            TokenKind::Char(c) => Ok(Expr::new_char(token.clone(), *c)),
317            _ => {
318                debug!("Unexpected token: {:?}", token);
319                Err(UnexpectedToken(token.kind.to_string(), token.span.clone()).into())
320            }
321        }
322    }
323
324    /// Parses a then-else expression.
325    ///
326    /// This method expects an identifier followed by a then keyword and two expressions.
327    ///
328    /// # Parameters
329    /// - `identifier`: The token representing the identifier.
330    ///
331    /// # Returns
332    /// - `Ok(Expr)`: The parsed then-else expression if successful.
333    /// - `Err(anyhow::Error)`: An error if parsing fails.
334    pub fn parse_then_else_expr(&mut self, condition: Expr) -> anyhow::Result<Expr> {
335        debug!("Parsing then-else expression");
336        let then_token = self.expect(TokenKind::Then)?;
337
338        let then_expr = self.parse_expr()?;
339        let else_token = self.expect(TokenKind::Else)?;
340
341        let else_expr = self.parse_expr()?;
342
343        Ok(Expr::new_then_else(
344            condition, then_expr, else_expr, then_token, else_token,
345        ))
346    }
347
348    /// Parses a function call expression.
349    ///
350    /// This method expects an identifier followed by parentheses containing arguments.
351    ///
352    /// # Parameters
353    /// - `callee`: The token representing the function name.
354    ///
355    /// # Returns
356    /// - `Ok(Expr)`: The parsed call expression if successful.
357    /// - `Err(anyhow::Error)`: An error if parsing fails.
358    pub fn parse_call_expr(&mut self, callee: Token) -> anyhow::Result<Expr> {
359        self.expect(TokenKind::LeftParen)?;
360
361        let mut args = vec![];
362
363        if self.peek().kind != TokenKind::RightParen {
364            while self.peek().kind != TokenKind::RightParen && !self.is_eof() {
365                let arg = self.parse_expr()?;
366
367                args.push(arg);
368
369                if self.peek().kind != TokenKind::RightParen {
370                    self.expect(TokenKind::Comma)?;
371                }
372            }
373        }
374
375        self.expect(TokenKind::RightParen)?;
376
377        Ok(Expr::new_call(callee.literal(), args, callee))
378    }
379
380    /// Parses an optional type annotation.
381    ///
382    /// This method checks for a colon followed by a type annotation and parses it if present.
383    ///
384    /// # Returns
385    /// - `Ok(Some(TypeAnnotation))`: The parsed type annotation if present.
386    /// - `Ok(None)`: If no type annotation is present.
387    pub fn parse_optional_type_annotation(&mut self) -> anyhow::Result<Option<TypeAnnotation>> {
388        if self.peek().kind == TokenKind::Colon {
389            Ok(Some(self.parse_type_annotation()?))
390        } else {
391            Ok(None)
392        }
393    }
394
395    /// Parses a vector expression.
396    ///
397    /// This method expects a left bracket followed by a list of expressions and a closing right bracket.
398    ///
399    /// # Returns
400    /// - `Ok(Expr)`: The parsed vector expression if successful.
401    /// - `Err(anyhow::Error)`: An error if parsing fails.
402    pub fn parse_vector(&mut self) -> anyhow::Result<Expr> {
403        debug!("Parsing vector");
404
405        let mut elements = vec![];
406        if self.peek().kind != TokenKind::RightBracket {
407            while self.peek().kind != TokenKind::RightBracket && !self.is_eof() {
408                let arg = self.parse_expr()?;
409
410                elements.push(arg);
411
412                if self.peek().kind != TokenKind::RightBracket {
413                    self.expect(TokenKind::Comma)?;
414                }
415            }
416        }
417
418        self.expect(TokenKind::RightBracket)?;
419
420        Ok(Expr::new_vec(elements))
421    }
422
423    /// Parses an assignment expression.
424    ///
425    /// This method checks for an identifier followed by an equals sign and an expression.
426    ///
427    /// # Returns
428    /// - `Ok(Expr)`: The parsed assignment expression if successful.
429    /// - `Err(anyhow::Error)`: An error if parsing fails.
430    pub fn parse_assignment(&mut self) -> anyhow::Result<Expr> {
431        tracing::debug!("Parsing assignment");
432
433        let expr = self.parse_binary_expression()?;
434        if let Some(assign_op) = self.parse_assignment_operator() {
435            self.consume();
436            let right = self.parse_expr()?;
437
438            let operator = AssignOperator::from_token_kind(assign_op);
439            return Ok(Expr::new_assign(expr, operator, right));
440        } else if self.peek().kind == TokenKind::Then {
441            return self.parse_then_else_expr(expr);
442        }
443
444        Ok(expr)
445    }
446
447    /// Attempts to parse an assignment operator.
448    ///
449    /// This method checks the next token to see if it's an assignment operator and returns it if found.
450    ///
451    /// # Returns
452    /// - `Some(TokenKind)`: The parsed assignment operator if found.
453    /// - `None`: If no assignment operator is found.
454    fn parse_assignment_operator(&mut self) -> Option<TokenKind> {
455        match self.peek().kind {
456            TokenKind::Equals
457            | TokenKind::PlusEquals
458            | TokenKind::MinusEquals
459            | TokenKind::MultiplyEquals
460            | TokenKind::DivideEquals => Some(self.peek().kind.clone()),
461            _ => None,
462        }
463    }
464}