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}