1use super::{CompletedMarker, EXPR_RECOVERY, Parser, STMT_RECOVERY, TYPE_RECOVERY, expressions::ExprOpts};
29use crate::syntax_kind::{SyntaxKind, SyntaxKind::*};
30
31impl Parser<'_, '_> {
32 const PATTERN_RECOVERY: &'static [SyntaxKind] = &[COMMA, R_PAREN, COLON, EQ];
34
35 pub fn parse_stmt(&mut self) -> Option<CompletedMarker> {
37 self.skip_trivia();
38
39 match self.current() {
40 KW_LET => self.parse_let_stmt(),
41 KW_CONST => self.parse_const_stmt(),
42 KW_RETURN => self.parse_return_stmt(),
43 KW_IF => self.parse_if_stmt(),
44 KW_FOR => self.parse_for_stmt(),
45 KW_ASSERT => self.parse_assert_stmt(),
46 KW_ASSERT_EQ => self.parse_assert_eq_stmt(),
47 KW_ASSERT_NEQ => self.parse_assert_neq_stmt(),
48 L_BRACE => self.parse_block(),
49 _ => self.parse_expr_or_assign_stmt(),
50 }
51 }
52
53 fn parse_let_stmt(&mut self) -> Option<CompletedMarker> {
55 let m = self.start();
56 self.bump_any(); self.parse_pattern();
60
61 if self.eat(COLON) && self.parse_type().is_none() {
63 self.error_recover("expected type", TYPE_RECOVERY);
64 }
65
66 self.expect(EQ);
68 if self.parse_expr().is_none() {
69 self.error_recover("expected expression", EXPR_RECOVERY);
70 }
71
72 self.expect(SEMICOLON);
73 Some(m.complete(self, LET_STMT))
74 }
75
76 fn parse_const_stmt(&mut self) -> Option<CompletedMarker> {
78 let m = self.start();
79 self.bump_any(); self.skip_trivia();
83 if self.at(IDENT) {
84 self.bump_any();
85 } else {
86 self.error("expected identifier".to_string());
87 }
88
89 self.expect(COLON);
91 if self.parse_type().is_none() {
92 self.error_recover("expected type", TYPE_RECOVERY);
93 }
94
95 self.expect(EQ);
97 if self.parse_expr().is_none() {
98 self.error_recover("expected expression", EXPR_RECOVERY);
99 }
100
101 self.expect(SEMICOLON);
102 Some(m.complete(self, CONST_STMT))
103 }
104
105 fn parse_return_stmt(&mut self) -> Option<CompletedMarker> {
107 let m = self.start();
108 self.bump_any(); if !self.at(SEMICOLON) && !self.at_eof() && self.parse_expr().is_none() {
112 self.error_recover("expected expression or ';'", EXPR_RECOVERY);
114 }
115
116 self.expect(SEMICOLON);
117 Some(m.complete(self, RETURN_STMT))
118 }
119
120 fn parse_if_stmt(&mut self) -> Option<CompletedMarker> {
122 let m = self.start();
123 self.bump_any(); if self.parse_expr_with_opts(ExprOpts::no_struct()).is_none() {
127 self.error_recover("expected condition", EXPR_RECOVERY);
128 }
129
130 if self.parse_block().is_none() && !self.at_eof() {
132 self.error_recover("expected block", STMT_RECOVERY);
133 }
134
135 if self.eat(KW_ELSE) {
137 if self.at(KW_IF) {
138 self.parse_if_stmt();
140 } else {
141 if self.parse_block().is_none() && !self.at_eof() {
143 self.error_recover("expected block after 'else'", STMT_RECOVERY);
144 }
145 }
146 }
147
148 Some(m.complete(self, IF_STMT))
149 }
150
151 fn parse_for_stmt(&mut self) -> Option<CompletedMarker> {
153 let m = self.start();
154 self.bump_any(); self.skip_trivia();
158 if self.at(IDENT) {
159 self.bump_any();
160 } else {
161 self.error("expected loop variable".to_string());
162 }
163
164 if self.eat(COLON) && self.parse_type().is_none() {
166 self.error_recover("expected type", TYPE_RECOVERY);
167 }
168
169 self.expect(KW_IN);
171
172 if self.parse_expr_with_opts(ExprOpts::no_struct()).is_none() {
175 self.error_recover("expected range start", EXPR_RECOVERY);
176 }
177 if self.eat(DOT_DOT) && self.parse_expr_with_opts(ExprOpts::no_struct()).is_none() {
178 self.error_recover("expected range end", EXPR_RECOVERY);
179 }
180
181 if self.parse_block().is_none() && !self.at_eof() {
183 self.error_recover("expected block", STMT_RECOVERY);
184 }
185
186 Some(m.complete(self, FOR_STMT))
187 }
188
189 fn parse_assert_stmt(&mut self) -> Option<CompletedMarker> {
191 let m = self.start();
192 self.bump_any(); self.expect(L_PAREN);
195 if self.parse_expr().is_none() {
196 self.error_recover("expected expression", EXPR_RECOVERY);
197 }
198 self.expect(R_PAREN);
199
200 self.expect(SEMICOLON);
201 Some(m.complete(self, ASSERT_STMT))
202 }
203
204 fn parse_assert_eq_stmt(&mut self) -> Option<CompletedMarker> {
206 let m = self.start();
207 self.bump_any(); self.expect(L_PAREN);
210 if self.parse_expr().is_none() {
211 self.error_recover("expected first expression", EXPR_RECOVERY);
212 }
213 self.expect(COMMA);
214 if self.parse_expr().is_none() {
215 self.error_recover("expected second expression", EXPR_RECOVERY);
216 }
217 self.expect(R_PAREN);
218
219 self.expect(SEMICOLON);
220 Some(m.complete(self, ASSERT_EQ_STMT))
221 }
222
223 fn parse_assert_neq_stmt(&mut self) -> Option<CompletedMarker> {
225 let m = self.start();
226 self.bump_any(); self.expect(L_PAREN);
229 if self.parse_expr().is_none() {
230 self.error_recover("expected first expression", EXPR_RECOVERY);
231 }
232 self.expect(COMMA);
233 if self.parse_expr().is_none() {
234 self.error_recover("expected second expression", EXPR_RECOVERY);
235 }
236 self.expect(R_PAREN);
237
238 self.expect(SEMICOLON);
239 Some(m.complete(self, ASSERT_NEQ_STMT))
240 }
241
242 pub fn parse_block(&mut self) -> Option<CompletedMarker> {
244 let m = self.start();
245
246 if !self.eat(L_BRACE) {
247 self.error("expected {".to_string());
248 m.abandon(self);
249 return None;
250 }
251
252 while !self.at(R_BRACE) && !self.at_eof() {
254 if self.parse_stmt().is_none() {
255 self.error_recover("expected statement", STMT_RECOVERY);
257 }
258 }
259
260 self.expect(R_BRACE);
261 Some(m.complete(self, BLOCK))
262 }
263
264 fn parse_expr_or_assign_stmt(&mut self) -> Option<CompletedMarker> {
266 let m = self.start();
267
268 let expr = self.parse_expr();
269 if expr.is_none() {
270 m.abandon(self);
271 return None;
272 }
273
274 if let Some(assign_kind) = self.current_assign_op() {
276 self.bump_any(); if self.parse_expr().is_none() {
278 self.error_recover("expected expression after assignment operator", EXPR_RECOVERY);
279 }
280 self.expect(SEMICOLON);
281 return Some(m.complete(self, assign_kind));
282 }
283
284 self.expect(SEMICOLON);
286 Some(m.complete(self, EXPR_STMT))
287 }
288
289 fn current_assign_op(&self) -> Option<SyntaxKind> {
291 match self.current() {
292 EQ => Some(ASSIGN_STMT),
293 PLUS_EQ => Some(ASSIGN_STMT),
294 MINUS_EQ => Some(ASSIGN_STMT),
295 STAR_EQ => Some(ASSIGN_STMT),
296 SLASH_EQ => Some(ASSIGN_STMT),
297 PERCENT_EQ => Some(ASSIGN_STMT),
298 STAR2_EQ => Some(ASSIGN_STMT),
299 AMP_EQ => Some(ASSIGN_STMT),
300 PIPE_EQ => Some(ASSIGN_STMT),
301 CARET_EQ => Some(ASSIGN_STMT),
302 SHL_EQ => Some(ASSIGN_STMT),
303 SHR_EQ => Some(ASSIGN_STMT),
304 AMP2_EQ => Some(ASSIGN_STMT),
305 PIPE2_EQ => Some(ASSIGN_STMT),
306 _ => None,
307 }
308 }
309
310 fn parse_pattern(&mut self) {
312 self.skip_trivia();
313
314 match self.current() {
315 L_PAREN => {
317 let m = self.start();
318 self.bump_any(); if !self.at(R_PAREN) {
321 self.parse_pattern();
322 while self.eat(COMMA) {
323 if self.at(R_PAREN) {
324 break;
325 }
326 self.parse_pattern();
327 }
328 }
329
330 self.expect(R_PAREN);
331 m.complete(self, TUPLE_PATTERN);
332 }
333 IDENT => {
335 let m = self.start();
336 self.bump_any();
337 m.complete(self, IDENT_PATTERN);
338 }
339 UNDERSCORE => {
341 let m = self.start();
342 self.bump_any();
343 m.complete(self, WILDCARD_PATTERN);
344 }
345 _ => {
346 self.error_recover("expected pattern", Self::PATTERN_RECOVERY);
347 }
348 }
349 }
350}
351
352#[cfg(test)]
353mod tests {
354 use super::*;
355 use crate::{lexer::lex, parser::Parse};
356 use expect_test::{Expect, expect};
357
358 fn check_stmt(input: &str, expect: Expect) {
359 let (tokens, _) = lex(input);
360 let mut parser = Parser::new(input, &tokens);
361 let root = parser.start();
362 parser.parse_stmt();
363 parser.skip_trivia();
364 root.complete(&mut parser, ROOT);
365 let parse: Parse = parser.finish();
366 let output = format!("{:#?}", parse.syntax());
367 expect.assert_eq(&output);
368 }
369
370 #[test]
375 fn parse_stmt_let_simple() {
376 check_stmt("let x = 1;", expect![[r#"
377 ROOT@0..10
378 LET_STMT@0..10
379 KW_LET@0..3 "let"
380 WHITESPACE@3..4 " "
381 IDENT_PATTERN@4..5
382 IDENT@4..5 "x"
383 WHITESPACE@5..6 " "
384 EQ@6..7 "="
385 WHITESPACE@7..8 " "
386 LITERAL@8..9
387 INTEGER@8..9 "1"
388 SEMICOLON@9..10 ";"
389 "#]]);
390 }
391
392 #[test]
393 fn parse_stmt_let_typed() {
394 check_stmt("let x: u32 = 42;", expect![[r#"
395 ROOT@0..16
396 LET_STMT@0..16
397 KW_LET@0..3 "let"
398 WHITESPACE@3..4 " "
399 IDENT_PATTERN@4..5
400 IDENT@4..5 "x"
401 COLON@5..6 ":"
402 WHITESPACE@6..7 " "
403 TYPE_PATH@7..10
404 KW_U32@7..10 "u32"
405 WHITESPACE@10..11 " "
406 EQ@11..12 "="
407 WHITESPACE@12..13 " "
408 LITERAL@13..15
409 INTEGER@13..15 "42"
410 SEMICOLON@15..16 ";"
411 "#]]);
412 }
413
414 #[test]
415 fn parse_stmt_let_tuple_destructure() {
416 check_stmt("let (a, b) = tuple;", expect![[r#"
417 ROOT@0..19
418 LET_STMT@0..19
419 KW_LET@0..3 "let"
420 WHITESPACE@3..4 " "
421 TUPLE_PATTERN@4..10
422 L_PAREN@4..5 "("
423 IDENT_PATTERN@5..6
424 IDENT@5..6 "a"
425 COMMA@6..7 ","
426 WHITESPACE@7..8 " "
427 IDENT_PATTERN@8..9
428 IDENT@8..9 "b"
429 R_PAREN@9..10 ")"
430 WHITESPACE@10..11 " "
431 EQ@11..12 "="
432 WHITESPACE@12..13 " "
433 PATH_EXPR@13..18
434 IDENT@13..18 "tuple"
435 SEMICOLON@18..19 ";"
436 "#]]);
437 }
438
439 #[test]
444 fn parse_stmt_const() {
445 check_stmt("const MAX: u32 = 100;", expect![[r#"
446 ROOT@0..21
447 CONST_STMT@0..21
448 KW_CONST@0..5 "const"
449 WHITESPACE@5..6 " "
450 IDENT@6..9 "MAX"
451 COLON@9..10 ":"
452 WHITESPACE@10..11 " "
453 TYPE_PATH@11..14
454 KW_U32@11..14 "u32"
455 WHITESPACE@14..15 " "
456 EQ@15..16 "="
457 WHITESPACE@16..17 " "
458 LITERAL@17..20
459 INTEGER@17..20 "100"
460 SEMICOLON@20..21 ";"
461 "#]]);
462 }
463
464 #[test]
469 fn parse_stmt_return_value() {
470 check_stmt("return 42;", expect![[r#"
471 ROOT@0..10
472 RETURN_STMT@0..10
473 KW_RETURN@0..6 "return"
474 WHITESPACE@6..7 " "
475 LITERAL@7..9
476 INTEGER@7..9 "42"
477 SEMICOLON@9..10 ";"
478 "#]]);
479 }
480
481 #[test]
482 fn parse_stmt_return_empty() {
483 check_stmt("return;", expect![[r#"
484 ROOT@0..7
485 RETURN_STMT@0..7
486 KW_RETURN@0..6 "return"
487 SEMICOLON@6..7 ";"
488 "#]]);
489 }
490
491 #[test]
496 fn parse_stmt_assign() {
497 check_stmt("x = 1;", expect![[r#"
498 ROOT@0..6
499 ASSIGN_STMT@0..6
500 PATH_EXPR@0..2
501 IDENT@0..1 "x"
502 WHITESPACE@1..2 " "
503 EQ@2..3 "="
504 WHITESPACE@3..4 " "
505 LITERAL@4..5
506 INTEGER@4..5 "1"
507 SEMICOLON@5..6 ";"
508 "#]]);
509 }
510
511 #[test]
512 fn parse_stmt_assign_add() {
513 check_stmt("x += 1;", expect![[r#"
514 ROOT@0..7
515 ASSIGN_STMT@0..7
516 PATH_EXPR@0..2
517 IDENT@0..1 "x"
518 WHITESPACE@1..2 " "
519 PLUS_EQ@2..4 "+="
520 WHITESPACE@4..5 " "
521 LITERAL@5..6
522 INTEGER@5..6 "1"
523 SEMICOLON@6..7 ";"
524 "#]]);
525 }
526
527 #[test]
532 fn parse_stmt_if_simple() {
533 check_stmt("if cond { }", expect![[r#"
534 ROOT@0..11
535 IF_STMT@0..11
536 KW_IF@0..2 "if"
537 WHITESPACE@2..3 " "
538 PATH_EXPR@3..8
539 IDENT@3..7 "cond"
540 WHITESPACE@7..8 " "
541 BLOCK@8..11
542 L_BRACE@8..9 "{"
543 WHITESPACE@9..10 " "
544 R_BRACE@10..11 "}"
545 "#]]);
546 }
547
548 #[test]
549 fn parse_stmt_if_else() {
550 check_stmt("if a { } else { }", expect![[r#"
551 ROOT@0..17
552 IF_STMT@0..17
553 KW_IF@0..2 "if"
554 WHITESPACE@2..3 " "
555 PATH_EXPR@3..5
556 IDENT@3..4 "a"
557 WHITESPACE@4..5 " "
558 BLOCK@5..8
559 L_BRACE@5..6 "{"
560 WHITESPACE@6..7 " "
561 R_BRACE@7..8 "}"
562 WHITESPACE@8..9 " "
563 KW_ELSE@9..13 "else"
564 BLOCK@13..17
565 WHITESPACE@13..14 " "
566 L_BRACE@14..15 "{"
567 WHITESPACE@15..16 " "
568 R_BRACE@16..17 "}"
569 "#]]);
570 }
571
572 #[test]
577 fn parse_stmt_for() {
578 check_stmt("for i in 0..10 { }", expect![[r#"
579 ROOT@0..18
580 FOR_STMT@0..18
581 KW_FOR@0..3 "for"
582 WHITESPACE@3..4 " "
583 IDENT@4..5 "i"
584 WHITESPACE@5..6 " "
585 KW_IN@6..8 "in"
586 WHITESPACE@8..9 " "
587 LITERAL@9..10
588 INTEGER@9..10 "0"
589 DOT_DOT@10..12 ".."
590 LITERAL@12..14
591 INTEGER@12..14 "10"
592 BLOCK@14..18
593 WHITESPACE@14..15 " "
594 L_BRACE@15..16 "{"
595 WHITESPACE@16..17 " "
596 R_BRACE@17..18 "}"
597 "#]]);
598 }
599
600 #[test]
605 fn parse_stmt_assert() {
606 check_stmt("assert(x);", expect![[r#"
607 ROOT@0..10
608 ASSERT_STMT@0..10
609 KW_ASSERT@0..6 "assert"
610 L_PAREN@6..7 "("
611 PATH_EXPR@7..8
612 IDENT@7..8 "x"
613 R_PAREN@8..9 ")"
614 SEMICOLON@9..10 ";"
615 "#]]);
616 }
617
618 #[test]
619 fn parse_stmt_assert_eq() {
620 check_stmt("assert_eq(a, b);", expect![[r#"
621 ROOT@0..16
622 ASSERT_EQ_STMT@0..16
623 KW_ASSERT_EQ@0..9 "assert_eq"
624 L_PAREN@9..10 "("
625 PATH_EXPR@10..11
626 IDENT@10..11 "a"
627 COMMA@11..12 ","
628 WHITESPACE@12..13 " "
629 PATH_EXPR@13..14
630 IDENT@13..14 "b"
631 R_PAREN@14..15 ")"
632 SEMICOLON@15..16 ";"
633 "#]]);
634 }
635
636 #[test]
641 fn parse_stmt_block() {
642 check_stmt("{ let x = 1; }", expect![[r#"
643 ROOT@0..14
644 BLOCK@0..14
645 L_BRACE@0..1 "{"
646 WHITESPACE@1..2 " "
647 LET_STMT@2..12
648 KW_LET@2..5 "let"
649 WHITESPACE@5..6 " "
650 IDENT_PATTERN@6..7
651 IDENT@6..7 "x"
652 WHITESPACE@7..8 " "
653 EQ@8..9 "="
654 WHITESPACE@9..10 " "
655 LITERAL@10..11
656 INTEGER@10..11 "1"
657 SEMICOLON@11..12 ";"
658 WHITESPACE@12..13 " "
659 R_BRACE@13..14 "}"
660 "#]]);
661 }
662
663 #[test]
664 fn parse_stmt_expr() {
665 check_stmt("foo();", expect![[r#"
666 ROOT@0..6
667 EXPR_STMT@0..6
668 CALL_EXPR@0..5
669 PATH_EXPR@0..3
670 IDENT@0..3 "foo"
671 L_PAREN@3..4 "("
672 R_PAREN@4..5 ")"
673 SEMICOLON@5..6 ";"
674 "#]]);
675 }
676}