Skip to main content

luaur_ast/methods/
parser_parse_if_else_expr.rs

1use crate::records::allocator::Allocator;
2use crate::records::ast_expr::AstExpr;
3use crate::records::ast_expr_if_else::AstExprIfElse;
4use crate::records::cst_expr_if_else::CstExprIfElse;
5use crate::records::lexeme::Type;
6use crate::records::location::Location;
7use crate::records::parser::Parser;
8use crate::records::position::Position;
9
10impl Parser {
11    pub(crate) fn parse_if_else_expr(&mut self) -> *mut AstExpr {
12        let mut has_else = false;
13        let start = self.lexer.current().location;
14
15        self.next_lexeme();
16
17        let condition = self.parse_expr_i32(0);
18
19        let has_then = self.expect_and_consume_type(Type::ReservedThen, "if then else expression");
20        let then_position = if has_then {
21            self.lexer.previous_location().begin
22        } else {
23            Position::missing()
24        };
25
26        let true_expr = self.parse_expr_i32(0);
27        let mut false_expr: *mut AstExpr = core::ptr::null_mut();
28
29        let else_position = self.lexer.current().location.begin;
30        let mut is_else_if = false;
31
32        if self.lexer.current().r#type == Type::ReservedElseif {
33            let old_recursion_count = self.recursion_counter;
34            self.increment_recursion_counter("expression");
35            has_else = true;
36            false_expr = self.parse_if_else_expr();
37            self.recursion_counter = old_recursion_count;
38            is_else_if = true;
39        } else {
40            has_else = self.expect_and_consume_type(Type::ReservedElse, "if then else expression");
41            false_expr = self.parse_expr_i32(0);
42        }
43
44        let end = unsafe { (*false_expr).base.location };
45
46        let node = unsafe {
47            (*self.allocator).alloc(AstExprIfElse::new(
48                Location::new(start.begin, end.end),
49                condition,
50                has_then,
51                true_expr,
52                has_else,
53                false_expr,
54            ))
55        };
56
57        if self.options.store_cst_data {
58            let cst_node = unsafe {
59                (*self.allocator).alloc(CstExprIfElse::new(
60                    then_position,
61                    else_position,
62                    is_else_if,
63                ))
64            };
65            self.cst_node_map.try_insert(
66                node as *mut crate::records::ast_node::AstNode,
67                cst_node as *mut crate::records::cst_node::CstNode,
68            );
69        }
70
71        node as *mut AstExpr
72    }
73}