1use crate::hir::{BinaryOp, OpKind, PostfixOp, UnaryOp};
2use crate::parser::{CompletedMarker, Parser};
3use crate::syntax_kind::SyntaxKind;
4use crate::token_set::TokenSet;
5
6const RECOVERY_SET: TokenSet = TokenSet::new(&[SyntaxKind::Semicolon]);
7const BOOL_SET: TokenSet = TokenSet::new(&[SyntaxKind::TrueKw, SyntaxKind::FalseKw]);
8
9pub fn root(p: &mut Parser<'_>) {
10 let m = p.start();
11 p.eat_trivia();
12 while !p.at(SyntaxKind::Eof) {
13 let (_, semicolon) = stmt(p);
14 if semicolon {
15 p.expect(SyntaxKind::Semicolon);
16 }
17 }
18 m.complete(p, SyntaxKind::Root);
19}
20
21pub fn stmt(p: &mut Parser<'_>) -> (CompletedMarker, bool) {
22 match p.current() {
23 SyntaxKind::Semicolon => (empty_stmt(p), true),
24 SyntaxKind::LetKw => (let_stmt(p), true),
25 SyntaxKind::WhileKw => (while_stmt(p), false),
26 SyntaxKind::BreakKw => (break_stmt(p), true),
27 SyntaxKind::ContinueKw => (continue_stmt(p), true),
28 SyntaxKind::FunKw => (func_stmt(p), false),
29 _ => expr_stmt(p),
30 }
31}
32
33pub fn empty_stmt(p: &mut Parser<'_>) -> CompletedMarker {
34 let m = p.start();
35 m.complete(p, SyntaxKind::EmptyStmt)
36}
37
38pub fn func_stmt(p: &mut Parser<'_>) -> CompletedMarker {
39 assert!(p.at(SyntaxKind::FunKw));
40 let m = p.start();
41 p.bump();
42 p.expect(SyntaxKind::Ident);
43 param_list(p);
44 p.expect(SyntaxKind::Colon);
45 type_spec(p);
46 block_expr(p);
47 m.complete(p, SyntaxKind::FuncDef)
48}
49
50pub fn while_stmt(p: &mut Parser<'_>) -> CompletedMarker {
51 assert!(p.at(SyntaxKind::WhileKw));
52 let m = p.start();
53 p.bump();
54 p.expect(SyntaxKind::OpenParen);
55 expr(p, 0);
56 p.expect(SyntaxKind::CloseParen);
57 expr(p, 0);
58 m.complete(p, SyntaxKind::WhileStmt)
59}
60
61pub fn break_stmt(p: &mut Parser<'_>) -> CompletedMarker {
62 assert!(p.at(SyntaxKind::BreakKw));
63 let m = p.start();
64 p.bump();
65 m.complete(p, SyntaxKind::BreakStmt)
66}
67
68pub fn continue_stmt(p: &mut Parser<'_>) -> CompletedMarker {
69 assert!(p.at(SyntaxKind::ContinueKw));
70 let m = p.start();
71 p.bump();
72 m.complete(p, SyntaxKind::ContinueStmt)
73}
74
75pub fn expr_stmt(p: &mut Parser<'_>) -> (CompletedMarker, bool) {
76 let m = p.start();
77 let res = expr(p, 0);
78 let ends_with_block = res.is_some_and(|r| r.1);
79 (m.complete(p, SyntaxKind::ExprStmt), !ends_with_block)
80}
81
82pub fn typed_ident(p: &mut Parser<'_>, optional: bool) -> CompletedMarker {
83 let m = p.start();
84 p.expect(SyntaxKind::Ident);
85 if optional {
86 if p.eat(SyntaxKind::Colon) {
87 type_spec(p);
88 }
89 } else {
90 p.expect(SyntaxKind::Colon);
91 type_spec(p);
92 }
93 m.complete(p, SyntaxKind::TypedIdent)
94}
95
96pub fn type_spec(p: &mut Parser<'_>) -> Option<CompletedMarker> {
97 match p.current() {
98 SyntaxKind::OpenParen => {
99 let m = p.start();
100 p.bump();
101 type_spec(p);
102 p.expect(SyntaxKind::Comma);
103 type_spec(p);
104 while p.eat(SyntaxKind::Comma) {
105 type_spec(p);
106 }
107 p.expect(SyntaxKind::CloseParen);
108 Some(m.complete(p, SyntaxKind::TupleTypeSpec))
109 },
110 SyntaxKind::Ident => {
111 let m = p.start();
112 p.expect(SyntaxKind::Ident);
113 let mut c = m.complete(p, SyntaxKind::IdentTypeSpec);
114 loop {
115 match p.current() {
116 SyntaxKind::OpenBracket => {
117 let m = c.precede(p);
118 p.bump();
119 p.expect(SyntaxKind::CloseBracket);
120 c = m.complete(p, SyntaxKind::ArrayTypeSpec);
121 },
122 SyntaxKind::Question => {
123 let m = c.precede(p);
124 p.bump();
125 c = m.complete(p, SyntaxKind::OptionTypeSpec);
126 },
127 _ => break
128 }
129 }
130 Some(c)
131 },
132 _ => {
133 p.error_and_recover(&[SyntaxKind::OpenParen, SyntaxKind::Ident], &RECOVERY_SET);
134 None
135 }
136 }
137}
138
139pub fn param_list(p: &mut Parser<'_>) -> CompletedMarker {
140 let m = p.start();
141 p.expect(SyntaxKind::OpenParen);
142 if !p.at(SyntaxKind::CloseParen) {
143 typed_ident(p, false);
144 while p.eat(SyntaxKind::Comma) {
145 typed_ident(p, false);
146 }
147 }
148 p.expect(SyntaxKind::CloseParen);
149 m.complete(p, SyntaxKind::ParamList)
150}
151
152pub fn let_stmt(p: &mut Parser<'_>) -> CompletedMarker {
153 assert!(p.at(SyntaxKind::LetKw));
154 let m = p.start();
155 p.bump();
156 typed_ident(p, true);
157 p.expect(SyntaxKind::Equals);
158 expr(p, 0);
159 m.complete(p, SyntaxKind::LetStmt)
160}
161
162pub fn expr(p: &mut Parser<'_>, min_binding_power: i8) -> Option<(CompletedMarker, bool)> {
163 let (mut lhs, mut ends_with_block) = lhs(p)?;
164 loop {
165 let op: OpKind = match p.current() {
166 SyntaxKind::Plus => OpKind::BinaryOp(BinaryOp::Add),
167 SyntaxKind::Minus => OpKind::BinaryOp(BinaryOp::Sub),
168 SyntaxKind::Star => OpKind::BinaryOp(BinaryOp::Mul),
169 SyntaxKind::Slash => OpKind::BinaryOp(BinaryOp::Div),
170 SyntaxKind::Percent => OpKind::BinaryOp(BinaryOp::Rem),
171 SyntaxKind::Equals => OpKind::BinaryOp(BinaryOp::Assign),
172 SyntaxKind::EqEq => OpKind::BinaryOp(BinaryOp::EqEq),
173 SyntaxKind::Neq => OpKind::BinaryOp(BinaryOp::Neq),
174 SyntaxKind::Ge => OpKind::BinaryOp(BinaryOp::Ge),
175 SyntaxKind::Le => OpKind::BinaryOp(BinaryOp::Le),
176 SyntaxKind::Gt => OpKind::BinaryOp(BinaryOp::Gt),
177 SyntaxKind::Lt => OpKind::BinaryOp(BinaryOp::Lt),
178 SyntaxKind::And => OpKind::BinaryOp(BinaryOp::And),
179 SyntaxKind::Or => OpKind::BinaryOp(BinaryOp::Or),
180 SyntaxKind::OpenBracket => OpKind::PostfixOp(PostfixOp::Index),
181 _ => break,
182 };
183 let (left_binding_power, right_binding_power) = op.binding_power();
184 if left_binding_power < min_binding_power {
185 break;
186 }
187 p.bump();
188 ends_with_block = false;
189 let m = lhs.precede(p);
190 if matches!(op, OpKind::PostfixOp(PostfixOp::Index)) {
191 expr(p, 0);
192 p.expect(SyntaxKind::CloseBracket);
193 lhs = m.complete(p, SyntaxKind::IndexExpr);
194 } else {
195 let rhs = expr(p, right_binding_power);
196 lhs = m.complete(p, SyntaxKind::BinaryExpr);
197 if rhs.is_none() {
198 break;
199 }
200 }
201 }
202 Some((lhs, ends_with_block))
203}
204
205pub fn lhs(p: &mut Parser<'_>) -> Option<(CompletedMarker, bool)> {
206 match p.current() {
207 SyntaxKind::NoneKw => Some((none_literal(p), false)),
208 SyntaxKind::Integer => Some((integer_literal(p), false)),
209 SyntaxKind::Float => Some((float_literal(p), false)),
210 SyntaxKind::TrueKw | SyntaxKind::FalseKw => Some((bool_literal(p), false)),
211 SyntaxKind::String => Some((string_literal(p), false)),
212 SyntaxKind::Char => Some((char_literal(p), false)),
213 SyntaxKind::OpenBracket => Some((array_literal(p), false)),
214 SyntaxKind::Minus => Some((prefix_expr(p), false)),
215 SyntaxKind::OpenParen => Some((paren_expr(p), false)),
216 SyntaxKind::OpenBrace => Some((block_expr(p), true)),
217 SyntaxKind::Ident if p.nth_at(1, SyntaxKind::OpenParen) => Some((fn_call_expr(p), false)),
218 SyntaxKind::Ident => Some((ref_expr(p), false)),
219 SyntaxKind::IfKw => Some(if_expr(p)),
220 _ => {
221 p.error_and_recover(&[SyntaxKind::Integer, SyntaxKind::Float, SyntaxKind::String, SyntaxKind::Char, SyntaxKind::TrueKw, SyntaxKind::FalseKw, SyntaxKind::OpenBracket, SyntaxKind::Minus, SyntaxKind::OpenParen, SyntaxKind::OpenBrace, SyntaxKind::Ident, SyntaxKind::IfKw], &RECOVERY_SET);
222 None
223 }
224 }
225}
226
227pub fn prefix_expr(p: &mut Parser<'_>) -> CompletedMarker {
228 assert!(p.at(SyntaxKind::Minus));
229 let m = p.start();
230 p.bump();
231 let op = OpKind::UnaryOp(UnaryOp::Neg);
232 let (_, right_binding_power) = op.binding_power();
233 expr(p, right_binding_power);
234 m.complete(p, SyntaxKind::PrefixExpr)
235}
236
237pub fn paren_expr(p: &mut Parser<'_>) -> CompletedMarker {
238 assert!(p.at(SyntaxKind::OpenParen));
239 let m = p.start();
240 p.bump();
241 expr(p, 0);
242 let mut comma = false;
243 while p.eat(SyntaxKind::Comma) {
244 expr(p, 0);
245 comma = true;
246 }
247 p.expect(SyntaxKind::CloseParen);
248 if comma {
249 m.complete(p, SyntaxKind::TupleExpr)
250 } else {
251 m.complete(p, SyntaxKind::ParenExpr)
252 }
253}
254
255pub fn ref_expr(p: &mut Parser<'_>) -> CompletedMarker {
256 assert!(p.at(SyntaxKind::Ident));
257 let m = p.start();
258 p.bump();
259 m.complete(p, SyntaxKind::RefExpr)
260}
261
262pub fn if_expr(p: &mut Parser<'_>) -> (CompletedMarker, bool) {
263 assert!(p.at(SyntaxKind::IfKw));
264 let m = p.start();
265 p.bump();
266 p.expect(SyntaxKind::OpenParen);
267 expr(p, 0);
268 p.expect(SyntaxKind::CloseParen);
269 let res = expr(p, 0);
270 let mut ends_with_block = res.is_some_and(|r| r.1);
271 if p.eat(SyntaxKind::ElseKw) {
272 let res = expr(p, 0);
273 ends_with_block = res.is_some_and(|r| r.1);
274 }
275 (m.complete(p, SyntaxKind::IfExpr), ends_with_block)
276}
277
278pub fn fn_call_expr(p: &mut Parser<'_>) -> CompletedMarker {
279 assert!(p.at(SyntaxKind::Ident));
280 let m = p.start();
281 p.bump();
282 p.expect(SyntaxKind::OpenParen);
283 if !p.at(SyntaxKind::CloseParen) {
284 expr(p, 0);
285 while p.eat(SyntaxKind::Comma) {
286 expr(p, 0);
287 }
288 }
289 p.expect(SyntaxKind::CloseParen);
290 m.complete(p, SyntaxKind::FnCallExpr)
291}
292
293pub fn block_expr(p: &mut Parser<'_>) -> CompletedMarker {
294 let m = p.start();
295 p.expect(SyntaxKind::OpenBrace);
296 while !p.at(SyntaxKind::Eof) {
297 if p.at(SyntaxKind::CloseBrace) {
298 empty_stmt(p);
299 break;
300 }
301 let (_, semicolon) = stmt(p);
302 if p.at(SyntaxKind::CloseBrace) {
303 break;
304 }
305 if semicolon {
306 p.expect(SyntaxKind::Semicolon);
307 }
308 }
309 p.expect(SyntaxKind::CloseBrace);
310 m.complete(p, SyntaxKind::BlockExpr)
311}
312
313pub fn none_literal(p: &mut Parser<'_>) -> CompletedMarker {
314 assert!(p.at(SyntaxKind::NoneKw));
315 let m = p.start();
316 p.bump();
317 m.complete(p, SyntaxKind::NoneLiteral)
318}
319
320pub fn integer_literal(p: &mut Parser<'_>) -> CompletedMarker {
321 assert!(p.at(SyntaxKind::Integer));
322 let m = p.start();
323 p.bump();
324 m.complete(p, SyntaxKind::IntLiteral)
325}
326
327pub fn float_literal(p: &mut Parser<'_>) -> CompletedMarker {
328 assert!(p.at(SyntaxKind::Float));
329 let m = p.start();
330 p.bump();
331 m.complete(p, SyntaxKind::FloatLiteral)
332}
333
334pub fn string_literal(p: &mut Parser<'_>) -> CompletedMarker {
335 assert!(p.at(SyntaxKind::String));
336 let m = p.start();
337 p.bump();
338 m.complete(p, SyntaxKind::StringLiteral)
339}
340
341pub fn char_literal(p: &mut Parser<'_>) -> CompletedMarker {
342 assert!(p.at(SyntaxKind::Char));
343 let m = p.start();
344 p.bump();
345 m.complete(p, SyntaxKind::CharLiteral)
346}
347
348pub fn bool_literal(p: &mut Parser<'_>) -> CompletedMarker {
349 assert!(p.at_set(&BOOL_SET));
350 let m = p.start();
351 p.bump();
352 m.complete(p, SyntaxKind::BoolLiteral)
353}
354
355pub fn array_literal(p: &mut Parser<'_>) -> CompletedMarker {
356 assert!(p.at(SyntaxKind::OpenBracket));
357 let m = p.start();
358 p.bump();
359 expr(p, 0);
360 p.expect(SyntaxKind::Semicolon);
361 expr(p, 0);
362 while p.eat(SyntaxKind::Comma) {
363 expr(p, 0);
364 }
365 p.expect(SyntaxKind::CloseBracket);
366 m.complete(p, SyntaxKind::ArrayLiteral)
367}
368
369#[cfg(test)]
370mod tests {
371 use crate::diagnostic::Diagnostic;
372 use crate::language::SyntaxNode;
373 use crate::lexer::Lexer;
374 use crate::parser::Parser;
375
376 fn parse(text: &str) -> (SyntaxNode, Vec<Diagnostic>) {
377 let lexer = Lexer::new(text);
378 let (tokens, _) = lexer.tokenize();
379 let parser = Parser::new(tokens);
380 parser.parse()
381 }
382
383 #[test]
384 fn multi_stmt() {
385 insta::assert_debug_snapshot!(parse("1; 2; 3;"));
386 }
387
388 #[test]
389 fn func_def() {
390 insta::assert_debug_snapshot!(parse("fun f(n: int): int { 1 }"));
391 }
392
393 #[test]
394 fn let_stmt() {
395 insta::assert_debug_snapshot!(parse("let a: int = 1;"));
396 }
397
398 #[test]
399 fn expr_stmt() {
400 insta::assert_debug_snapshot!(parse("1 + 2 * 3;"));
401 }
402
403 #[test]
404 fn unary() {
405 insta::assert_debug_snapshot!(parse("-1 * -2;"));
406 }
407
408 #[test]
409 fn paren() {
410 insta::assert_debug_snapshot!(parse("(1 + 2) * 3;"));
411 }
412
413 #[test]
414 fn let_array() {
415 insta::assert_debug_snapshot!(parse("let a: int[][] = [[1; 2]; 3];"));
416 }
417
418 #[test]
419 fn ref_expr() {
420 insta::assert_debug_snapshot!(parse("a + bc;"));
421 }
422
423 #[test]
424 fn fn_call_expr() {
425 insta::assert_debug_snapshot!(parse("f(a, 1);"));
426 }
427
428 #[test]
429 fn assign_expr() {
430 insta::assert_debug_snapshot!(parse("a = b[0] = 1;"));
431 }
432
433 #[test]
434 fn block_expr() {
435 insta::assert_debug_snapshot!(parse("{1} + {2};"));
436 }
437
438 #[test]
439 fn type_spec() {
440 insta::assert_debug_snapshot!(parse("let a: (int[]?, str, (char?, unit)) = 0;"));
441 }
442}