Skip to main content

luaur_ast/methods/
parser_check_binary_confusables.rs

1use crate::records::ast_expr_binary::AstExprBinaryOp;
2use crate::records::binary_op_priority::BinaryOpPriority;
3use crate::records::lexeme::Type;
4use crate::records::location::Location;
5use crate::records::parser::Parser;
6
7impl Parser {
8    pub(crate) fn check_binary_confusables(
9        &mut self,
10        binary_priority: &[BinaryOpPriority],
11        limit: u32,
12    ) -> Option<AstExprBinaryOp> {
13        let curr = *self.lexer.current();
14
15        // early-out: need to check if this is a possible confusable quickly
16        if curr.r#type != Type('&' as i32)
17            && curr.r#type != Type('|' as i32)
18            && curr.r#type != Type('!' as i32)
19        {
20            return None;
21        }
22
23        // slow path: possible confusable
24        let start = curr.location;
25        let next = self.lexer.lookahead();
26
27        if curr.r#type == Type('&' as i32)
28            && next.r#type == Type('&' as i32)
29            && curr.location.end == next.location.begin
30            && binary_priority[AstExprBinaryOp::And as usize].left as u32 > limit
31        {
32            self.next_lexeme();
33            self.report(
34                Location {
35                    begin: start.begin,
36                    end: next.location.end,
37                },
38                format_args!("Unexpected '&&'; did you mean 'and'?"),
39            );
40            return Some(AstExprBinaryOp::And);
41        } else if curr.r#type == Type('|' as i32)
42            && next.r#type == Type('|' as i32)
43            && curr.location.end == next.location.begin
44            && binary_priority[AstExprBinaryOp::Or as usize].left as u32 > limit
45        {
46            self.next_lexeme();
47            self.report(
48                Location {
49                    begin: start.begin,
50                    end: next.location.end,
51                },
52                format_args!("Unexpected '||'; did you mean 'or'?"),
53            );
54            return Some(AstExprBinaryOp::Or);
55        } else if curr.r#type == Type('!' as i32)
56            && next.r#type == Type('=' as i32)
57            && curr.location.end == next.location.begin
58            && binary_priority[AstExprBinaryOp::CompareNe as usize].left as u32 > limit
59        {
60            self.next_lexeme();
61            self.report(
62                Location {
63                    begin: start.begin,
64                    end: next.location.end,
65                },
66                format_args!("Unexpected '!='; did you mean '~='?"),
67            );
68            return Some(AstExprBinaryOp::CompareNe);
69        }
70
71        None
72    }
73}
74
75pub fn parser_check_binary_confusables(
76    this: &mut Parser,
77    binary_priority: &[BinaryOpPriority],
78    limit: u32,
79) -> Option<AstExprBinaryOp> {
80    this.check_binary_confusables(binary_priority, limit)
81}