Skip to main content

rl_lang/parser/expressions/
comparsion.rs

1use crate::{
2    ast::{ExprId, nodes::ExpressionKind},
3    lexer::tokentypes::TokenType,
4    parser::parser_logic::Parser,
5    utils::errors::Error,
6};
7
8impl Parser {
9    /// Parses comparison and compound-assignment operators:
10    /// `<`, `<=`, `>`, `>=`, `+=`, `-=`, `*=`, `/=`.
11    ///
12    /// Compound-assignment operators (`+=` etc.) are desugared in-place: when
13    /// the left-hand side is a plain [`ExpressionKind::Identifier`], they expand
14    /// to an [`ExpressionKind::Assign`] whose value is the corresponding
15    /// [`ExpressionKind::Binary`]. If the LHS is not a simple identifier the
16    /// operator is treated as a plain binary expression (the checker will reject
17    /// it later if needed).
18    pub fn parse_comparsion(&mut self) -> Result<ExprId, Error> {
19        let mut left = self.parse_term()?;
20        while self.match_type(&[
21            TokenType::Less,
22            TokenType::LessEqual,
23            TokenType::Greater,
24            TokenType::GreaterEqual,
25            TokenType::PlusEqual,
26            TokenType::MinusEqual,
27            TokenType::StarEqual,
28            TokenType::SlashEqual,
29        ]) {
30            while self.match_type(&[TokenType::Newline]) {}
31            let operator = self.previous();
32            while self.match_type(&[TokenType::Newline]) {}
33            let right = self.parse_term()?;
34            let left_id = self.ast_arena.exprs.get(left);
35            let right_id = self.ast_arena.exprs.get(right);
36
37            let span = left_id.span.join(right_id.span);
38
39            match operator {
40                TokenType::PlusEqual
41                | TokenType::MinusEqual
42                | TokenType::StarEqual
43                | TokenType::SlashEqual => {
44                    if let ExpressionKind::Identifier(name) = &left_id.kind {
45                        let name = name.clone();
46                        let lhs_span = left_id.span;
47                        let operator = match operator {
48                            TokenType::PlusEqual => TokenType::Plus,
49                            TokenType::MinusEqual => TokenType::Minus,
50                            TokenType::StarEqual => TokenType::Star,
51                            TokenType::SlashEqual => TokenType::Slash,
52                            _ => unreachable!(),
53                        };
54                        let left_expr = self
55                            .ast_arena
56                            .alloc_expr(ExpressionKind::Identifier(name.clone()), lhs_span);
57
58                        let binary = self.ast_arena.alloc_expr(
59                            ExpressionKind::Binary {
60                                left: left_expr,
61                                operator,
62                                right,
63                            },
64                            span,
65                        );
66
67                        left = self.ast_arena.alloc_expr(
68                            ExpressionKind::Assign {
69                                name,
70                                value: binary,
71                            },
72                            span,
73                        );
74                    } else {
75                        left = self.ast_arena.alloc_expr(
76                            ExpressionKind::Binary {
77                                left,
78                                operator,
79                                right,
80                            },
81                            span,
82                        );
83                    }
84                }
85                _ => {
86                    left = self.ast_arena.alloc_expr(
87                        ExpressionKind::Binary {
88                            left,
89                            operator,
90                            right,
91                        },
92                        span,
93                    );
94                }
95            }
96        }
97        Ok(left)
98    }
99}