i_slint_compiler/parser/
statements.rs1use crate::parser::r#type::parse_type;
5
6use super::element::parse_code_block;
7use super::expressions::parse_expression;
8use super::prelude::*;
9
10#[cfg_attr(test, parser_test)]
11pub fn parse_statement(p: &mut impl Parser) -> bool {
24 if p.nth(0).kind() == SyntaxKind::RBrace {
25 return false;
26 }
27 if p.test(SyntaxKind::Semicolon) {
28 return true;
29 }
30 let checkpoint = p.checkpoint();
31
32 if p.peek().as_str() == "if"
33 && !matches!(
34 p.nth(1).kind(),
35 SyntaxKind::Dot
36 | SyntaxKind::Comma
37 | SyntaxKind::Semicolon
38 | SyntaxKind::RBrace
39 | SyntaxKind::RBracket
40 | SyntaxKind::RParent
41 )
42 {
43 let mut p = p.start_node(SyntaxKind::Expression);
44 parse_if_statement(&mut *p);
45 return true;
46 }
47
48 if p.peek().as_str() == "return" {
49 let mut p = p.start_node_at(checkpoint, SyntaxKind::ReturnStatement);
50 p.expect(SyntaxKind::Identifier); if !p.test(SyntaxKind::Semicolon) {
52 parse_expression(&mut *p);
53 p.expect(SyntaxKind::Semicolon);
54 }
55 return true;
56 }
57
58 if p.peek().as_str() == "let" && p.nth(1).kind() == SyntaxKind::Identifier {
59 parse_let_statement(p);
60 return true;
61 }
62
63 if p.nth(0).kind() == SyntaxKind::Identifier && p.nth(1).kind() == SyntaxKind::ColonEqual {
64 let name = p.nth(0).as_str().to_string();
65 if p.nth(2).kind() == SyntaxKind::Identifier && p.nth(3).kind() == SyntaxKind::LBrace {
67 p.error("':=' is not valid in statements");
68 return false;
69 }
70 p.error(format!(
72 "':=' is not valid in statements. Use 'let {name} = <expression>;' to declare a local variable"
73 ));
74 let mut p = p.start_node_at(checkpoint, SyntaxKind::LetStatement);
75 {
76 let mut p = p.start_node(SyntaxKind::DeclaredIdentifier);
77 p.expect(SyntaxKind::Identifier);
78 }
79 p.expect(SyntaxKind::ColonEqual);
80 parse_expression(&mut *p);
81 p.test(SyntaxKind::Semicolon);
82 return true;
83 }
84
85 parse_expression(p);
86 if matches!(
87 p.nth(0).kind(),
88 SyntaxKind::MinusEqual
89 | SyntaxKind::PlusEqual
90 | SyntaxKind::StarEqual
91 | SyntaxKind::DivEqual
92 | SyntaxKind::Equal
93 ) {
94 let mut p = p.start_node_at(checkpoint.clone(), SyntaxKind::Expression);
95 let mut p = p.start_node_at(checkpoint, SyntaxKind::SelfAssignment);
96 p.consume();
97 parse_expression(&mut *p);
98 }
99 p.test(SyntaxKind::Semicolon)
100}
101
102#[cfg_attr(test, parser_test)]
103fn parse_let_statement(p: &mut impl Parser) {
109 let mut p = p.start_node(SyntaxKind::LetStatement);
110 debug_assert_eq!(p.peek().as_str(), "let");
111 p.expect(SyntaxKind::Identifier); {
113 let mut p = p.start_node(SyntaxKind::DeclaredIdentifier);
114 p.expect(SyntaxKind::Identifier);
115 }
116
117 if p.test(SyntaxKind::Colon) {
118 parse_type(&mut *p);
119 }
120
121 p.expect(SyntaxKind::Equal);
122 parse_expression(&mut *p);
123 p.expect(SyntaxKind::Semicolon);
124}
125
126#[cfg_attr(test, parser_test)]
127fn parse_if_statement(p: &mut impl Parser) {
134 let mut p = p.start_node(SyntaxKind::ConditionalExpression);
135 debug_assert_eq!(p.peek().as_str(), "if");
136 p.expect(SyntaxKind::Identifier);
137 parse_expression(&mut *p);
138 {
139 let mut p = p.start_node(SyntaxKind::Expression);
140 parse_code_block(&mut *p);
141 }
142 if p.peek().as_str() == "else" {
143 p.expect(SyntaxKind::Identifier);
144 let mut p = p.start_node(SyntaxKind::Expression);
145 if p.peek().as_str() == "if" {
146 parse_if_statement(&mut *p)
147 } else {
148 parse_code_block(&mut *p);
149 }
150 } else {
151 let mut p = p.start_node(SyntaxKind::Expression);
154 let _ = p.start_node(SyntaxKind::CodeBlock);
155 }
156}