luaur_ast/methods/
parser_parse_if.rs1use crate::records::allocator::Allocator;
10use crate::records::ast_node::AstNode;
11use crate::records::ast_stat::AstStat;
12use crate::records::ast_stat_block::AstStatBlock;
13use crate::records::ast_stat_if::AstStatIf;
14use crate::records::lexeme::Type;
15use crate::records::location::Location;
16use crate::records::match_lexeme::MatchLexeme;
17use crate::records::parser::Parser;
18use crate::rtti::ast_node_as;
19
20impl Parser {
21 pub fn parse_if(&mut self) -> *mut AstStat {
22 let start = self.lexer.current().location;
23
24 self.next_lexeme(); let cond = self.parse_expr_i32(0);
27
28 let match_then = *self.lexer.current();
29 let mut then_location: Option<Location> = None;
30 if self.expect_and_consume_type(Type::ReservedThen, "if statement") {
31 then_location = Some(match_then.location);
32 }
33
34 let thenbody = self.parse_block();
35
36 let mut elsebody: *mut AstStat = core::ptr::null_mut();
37 let mut end = start;
38 let mut else_location: Option<Location> = None;
39
40 if self.lexer.current().r#type == Type::ReservedElseif {
41 unsafe {
42 (*thenbody).has_end = true;
43 }
44 let old_recursion_count = self.recursion_counter;
45 self.increment_recursion_counter("elseif");
46 else_location = Some(self.lexer.current().location);
47 elsebody = self.parse_if();
48 end = unsafe { (*elsebody).base.location };
49 self.recursion_counter = old_recursion_count;
50 } else {
51 let mut match_then_else = match_then;
52
53 if self.lexer.current().r#type == Type::ReservedElse {
54 unsafe {
55 (*thenbody).has_end = true;
56 }
57 else_location = Some(self.lexer.current().location);
58 match_then_else = *self.lexer.current();
59 self.next_lexeme();
60
61 let else_block = self.parse_block();
62 unsafe {
63 (*else_block).base.base.location.begin = match_then_else.location.end;
64 }
65 elsebody = else_block as *mut AstStat;
66 }
67
68 end = self.lexer.current().location;
69
70 let has_end = self.expect_match_end_and_consume(
71 Type::ReservedEnd,
72 &MatchLexeme::new(&match_then_else),
73 );
74
75 if !elsebody.is_null() {
76 let else_block = unsafe { ast_node_as::<AstStatBlock>(elsebody as *mut AstNode) };
77 if !else_block.is_null() {
78 unsafe {
79 (*else_block).has_end = has_end;
80 }
81 }
82 } else {
83 unsafe {
84 (*thenbody).has_end = has_end;
85 }
86 }
87 }
88
89 unsafe {
90 (*self.allocator).alloc(AstStatIf::new(
91 Location::new(start.begin, end.end),
92 cond,
93 thenbody,
94 elsebody,
95 then_location,
96 else_location,
97 )) as *mut AstStat
98 }
99 }
100}