1use super::{CompletedMarker, EXPR_RECOVERY, Parser, STMT_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 fn recover_statement_terminator(&mut self) {
37 if self.eat(SEMICOLON) {
38 return;
39 }
40
41 self.expect(SEMICOLON);
44
45 if self.at(R_BRACE) || self.at_eof() {
46 return;
47 }
48
49 self.recover(&[SEMICOLON, R_BRACE]);
50 self.eat(SEMICOLON);
51 }
52
53 pub fn parse_stmt(&mut self) -> Option<CompletedMarker> {
55 self.skip_trivia();
56
57 match self.current() {
58 KW_LET => self.parse_let_stmt(),
59 KW_CONST => self.parse_const_stmt(),
60 KW_RETURN => self.parse_return_stmt(),
61 KW_IF => self.parse_if_stmt(),
62 KW_FOR => self.parse_for_stmt(),
63 KW_ASSERT => self.parse_assert_stmt(),
64 KW_ASSERT_EQ => self.parse_assert_eq_stmt(),
65 KW_ASSERT_NEQ => self.parse_assert_neq_stmt(),
66 L_BRACE => self.parse_block(),
67 _ => self.parse_expr_or_assign_stmt(),
68 }
69 }
70
71 fn parse_let_stmt(&mut self) -> Option<CompletedMarker> {
73 let m = self.start();
74 self.bump_any(); self.parse_pattern();
78
79 if self.eat(COLON) && self.parse_type().is_none() {
81 self.error("expected type");
82 }
83
84 self.expect(EQ);
86 if self.parse_expr().is_none() {
87 self.error_recover("expected expression", EXPR_RECOVERY);
88 }
89
90 self.recover_statement_terminator();
91 Some(m.complete(self, LET_STMT))
92 }
93
94 fn parse_const_stmt(&mut self) -> Option<CompletedMarker> {
96 let m = self.start();
97 self.bump_any(); self.skip_trivia();
101 if self.at(IDENT) {
102 self.bump_any();
103 } else {
104 self.error("expected identifier");
105 }
106
107 if self.expect(COLON) {
110 if self.parse_type().is_none() {
111 self.error("expected type");
112 }
113 } else if !self.at(EQ) && self.parse_type().is_none() {
114 self.error("expected type");
115 }
116
117 self.expect(EQ);
119 if self.parse_expr().is_none() {
120 self.error_recover("expected expression", EXPR_RECOVERY);
121 }
122
123 self.recover_statement_terminator();
124 Some(m.complete(self, CONST_STMT))
125 }
126
127 fn parse_return_stmt(&mut self) -> Option<CompletedMarker> {
129 let m = self.start();
130 self.bump_any(); if !self.at(SEMICOLON) && !self.at_eof() && self.parse_expr().is_none() {
134 self.error_recover("expected expression or ';'", EXPR_RECOVERY);
136 }
137
138 self.recover_statement_terminator();
139 Some(m.complete(self, RETURN_STMT))
140 }
141
142 fn parse_if_stmt(&mut self) -> Option<CompletedMarker> {
144 let m = self.start();
145 self.bump_any(); if self.parse_expr_with_opts(ExprOpts::no_struct()).is_none() {
149 self.error_recover("expected condition", EXPR_RECOVERY);
150 }
151
152 if self.parse_block().is_none() && !self.at_eof() {
154 self.error_recover("expected block", STMT_RECOVERY);
155 }
156
157 if self.eat(KW_ELSE) {
159 if self.at(KW_IF) {
160 self.parse_if_stmt();
162 } else {
163 if self.parse_block().is_none() && !self.at_eof() {
165 self.error_recover("expected block after 'else'", STMT_RECOVERY);
166 }
167 }
168 }
169
170 Some(m.complete(self, IF_STMT))
171 }
172
173 fn parse_for_stmt(&mut self) -> Option<CompletedMarker> {
175 let m = self.start();
176 self.bump_any(); self.skip_trivia();
180 if self.at(IDENT) {
181 self.bump_any();
182 } else {
183 self.error("expected loop variable");
184 }
185
186 if self.eat(COLON) && self.parse_type().is_none() {
188 self.error("expected type");
189 }
190
191 self.expect(KW_IN);
193
194 if self.parse_expr_with_opts(ExprOpts::no_struct()).is_none() {
197 self.error_recover("expected range start", EXPR_RECOVERY);
198 }
199 let inclusive = if self.eat(DOT_DOT) {
200 false
201 } else if self.eat(DOT_DOT_EQ) {
202 true
203 } else {
204 self.error("expected '..' or '..='");
205 false
206 };
207 if self.parse_expr_with_opts(ExprOpts::no_struct()).is_none() {
208 self.error_recover("expected range end", EXPR_RECOVERY);
209 }
210
211 if self.parse_block().is_none() && !self.at_eof() {
213 self.error_recover("expected block", STMT_RECOVERY);
214 }
215
216 let kind = if inclusive { FOR_INCLUSIVE_STMT } else { FOR_STMT };
217 Some(m.complete(self, kind))
218 }
219
220 fn parse_assert_stmt(&mut self) -> Option<CompletedMarker> {
222 let m = self.start();
223 self.bump_any(); self.expect(L_PAREN);
226 if self.parse_expr().is_none() {
227 self.error("expected expression");
228 }
229 self.expect(R_PAREN);
230
231 self.recover_statement_terminator();
232 Some(m.complete(self, ASSERT_STMT))
233 }
234
235 fn parse_assert_eq_stmt(&mut self) -> Option<CompletedMarker> {
237 let m = self.start();
238 self.bump_any(); self.expect(L_PAREN);
241 if self.parse_expr().is_none() {
242 self.error("expected first expression");
243 }
244 self.expect(COMMA);
245 if self.parse_expr().is_none() {
246 self.error("expected second expression");
247 }
248 self.expect(R_PAREN);
249
250 self.recover_statement_terminator();
251 Some(m.complete(self, ASSERT_EQ_STMT))
252 }
253
254 fn parse_assert_neq_stmt(&mut self) -> Option<CompletedMarker> {
256 let m = self.start();
257 self.bump_any(); self.expect(L_PAREN);
260 if self.parse_expr().is_none() {
261 self.error("expected first expression");
262 }
263 self.expect(COMMA);
264 if self.parse_expr().is_none() {
265 self.error("expected second expression");
266 }
267 self.expect(R_PAREN);
268
269 self.recover_statement_terminator();
270 Some(m.complete(self, ASSERT_NEQ_STMT))
271 }
272
273 pub fn parse_block(&mut self) -> Option<CompletedMarker> {
275 let m = self.start();
276
277 if !self.eat(L_BRACE) {
278 self.error("expected {");
279 m.abandon(self);
280 return None;
281 }
282
283 while !self.at(R_BRACE) && !self.at_eof() {
285 let had_error = self.erroring;
286 self.erroring = false;
289 if self.parse_stmt().is_none() {
290 self.error_recover("expected statement", STMT_RECOVERY);
292 } else if self.erroring && !had_error {
293 if self.at(R_BRACE) || !self.at_any(STMT_RECOVERY) {
298 self.recover(STMT_RECOVERY);
299 self.eat(SEMICOLON);
300 }
301 }
302 }
303
304 self.expect(R_BRACE);
305 Some(m.complete(self, BLOCK))
306 }
307
308 fn parse_expr_or_assign_stmt(&mut self) -> Option<CompletedMarker> {
310 let m = self.start();
311
312 let expr = self.parse_expr();
313 if expr.is_none() {
314 m.abandon(self);
315 return None;
316 }
317
318 if let Some(assign_kind) = self.current_assign_op() {
320 self.bump_any(); if self.parse_expr().is_none() {
322 self.error_recover("expected expression after assignment operator", EXPR_RECOVERY);
323 }
324 self.recover_statement_terminator();
325 return Some(m.complete(self, assign_kind));
326 }
327
328 self.recover_statement_terminator();
330 Some(m.complete(self, EXPR_STMT))
331 }
332
333 fn current_assign_op(&self) -> Option<SyntaxKind> {
335 match self.current() {
336 EQ => Some(ASSIGN_STMT),
337 PLUS_EQ | MINUS_EQ | STAR_EQ | SLASH_EQ | PERCENT_EQ | STAR2_EQ | AMP_EQ | PIPE_EQ | CARET_EQ | SHL_EQ
338 | SHR_EQ | AMP2_EQ | PIPE2_EQ => Some(COMPOUND_ASSIGN_STMT),
339 _ => None,
340 }
341 }
342
343 fn parse_pattern(&mut self) {
345 self.skip_trivia();
346
347 match self.current() {
348 L_PAREN => {
350 let m = self.start();
351 self.bump_any(); if !self.at(R_PAREN) {
354 self.parse_pattern();
355 while self.eat(COMMA) {
356 if self.at(R_PAREN) {
357 break;
358 }
359 self.parse_pattern();
360 }
361 }
362
363 self.expect(R_PAREN);
364 m.complete(self, TUPLE_PATTERN);
365 }
366 IDENT => {
368 let m = self.start();
369 self.bump_any();
370 m.complete(self, IDENT_PATTERN);
371 }
372 UNDERSCORE => {
374 let m = self.start();
375 self.bump_any();
376 m.complete(self, WILDCARD_PATTERN);
377 }
378 _ => {
379 self.error_recover("expected pattern", Self::PATTERN_RECOVERY);
380 }
381 }
382 }
383}
384
385#[cfg(test)]
386mod tests {
387 use super::*;
388 use crate::{lexer::lex, parser::Parse};
389 use expect_test::{Expect, expect};
390
391 fn check_stmt(input: &str, expect: Expect) {
392 let (tokens, _) = lex(input);
393 let mut parser = Parser::new(input, &tokens);
394 let root = parser.start();
395 parser.parse_stmt();
396 parser.skip_trivia();
397 root.complete(&mut parser, ROOT);
398 let parse: Parse = parser.finish(vec![]);
399 let output = format!("{:#?}", parse.syntax());
400 expect.assert_eq(&output);
401 }
402
403 #[test]
408 fn parse_stmt_let_simple() {
409 check_stmt("let x = 1;", expect![[r#"
410 ROOT@0..10
411 LET_STMT@0..10
412 KW_LET@0..3 "let"
413 WHITESPACE@3..4 " "
414 IDENT_PATTERN@4..5
415 IDENT@4..5 "x"
416 WHITESPACE@5..6 " "
417 EQ@6..7 "="
418 WHITESPACE@7..8 " "
419 LITERAL_INT@8..9
420 INTEGER@8..9 "1"
421 SEMICOLON@9..10 ";"
422 "#]]);
423 }
424
425 #[test]
426 fn parse_stmt_let_typed() {
427 check_stmt("let x: u32 = 42;", expect![[r#"
428 ROOT@0..16
429 LET_STMT@0..16
430 KW_LET@0..3 "let"
431 WHITESPACE@3..4 " "
432 IDENT_PATTERN@4..5
433 IDENT@4..5 "x"
434 COLON@5..6 ":"
435 WHITESPACE@6..7 " "
436 TYPE_PRIMITIVE@7..10
437 KW_U32@7..10 "u32"
438 WHITESPACE@10..11 " "
439 EQ@11..12 "="
440 WHITESPACE@12..13 " "
441 LITERAL_INT@13..15
442 INTEGER@13..15 "42"
443 SEMICOLON@15..16 ";"
444 "#]]);
445 }
446
447 #[test]
448 fn parse_stmt_let_tuple_destructure() {
449 check_stmt("let (a, b) = tuple;", expect![[r#"
450 ROOT@0..19
451 LET_STMT@0..19
452 KW_LET@0..3 "let"
453 WHITESPACE@3..4 " "
454 TUPLE_PATTERN@4..10
455 L_PAREN@4..5 "("
456 IDENT_PATTERN@5..6
457 IDENT@5..6 "a"
458 COMMA@6..7 ","
459 WHITESPACE@7..8 " "
460 IDENT_PATTERN@8..9
461 IDENT@8..9 "b"
462 R_PAREN@9..10 ")"
463 WHITESPACE@10..11 " "
464 EQ@11..12 "="
465 WHITESPACE@12..13 " "
466 PATH_EXPR@13..18
467 IDENT@13..18 "tuple"
468 SEMICOLON@18..19 ";"
469 "#]]);
470 }
471
472 #[test]
477 fn parse_stmt_const() {
478 check_stmt("const MAX: u32 = 100;", expect![[r#"
479 ROOT@0..21
480 CONST_STMT@0..21
481 KW_CONST@0..5 "const"
482 WHITESPACE@5..6 " "
483 IDENT@6..9 "MAX"
484 COLON@9..10 ":"
485 WHITESPACE@10..11 " "
486 TYPE_PRIMITIVE@11..14
487 KW_U32@11..14 "u32"
488 WHITESPACE@14..15 " "
489 EQ@15..16 "="
490 WHITESPACE@16..17 " "
491 LITERAL_INT@17..20
492 INTEGER@17..20 "100"
493 SEMICOLON@20..21 ";"
494 "#]]);
495 }
496
497 #[test]
502 fn parse_stmt_return_value() {
503 check_stmt("return 42;", expect![[r#"
504 ROOT@0..10
505 RETURN_STMT@0..10
506 KW_RETURN@0..6 "return"
507 WHITESPACE@6..7 " "
508 LITERAL_INT@7..9
509 INTEGER@7..9 "42"
510 SEMICOLON@9..10 ";"
511 "#]]);
512 }
513
514 #[test]
515 fn parse_stmt_return_empty() {
516 check_stmt("return;", expect![[r#"
517 ROOT@0..7
518 RETURN_STMT@0..7
519 KW_RETURN@0..6 "return"
520 SEMICOLON@6..7 ";"
521 "#]]);
522 }
523
524 #[test]
529 fn parse_stmt_assign() {
530 check_stmt("x = 1;", expect![[r#"
531 ROOT@0..6
532 ASSIGN_STMT@0..6
533 PATH_EXPR@0..2
534 IDENT@0..1 "x"
535 WHITESPACE@1..2 " "
536 EQ@2..3 "="
537 WHITESPACE@3..4 " "
538 LITERAL_INT@4..5
539 INTEGER@4..5 "1"
540 SEMICOLON@5..6 ";"
541 "#]]);
542 }
543
544 #[test]
545 fn parse_stmt_assign_add() {
546 check_stmt("x += 1;", expect![[r#"
547 ROOT@0..7
548 COMPOUND_ASSIGN_STMT@0..7
549 PATH_EXPR@0..2
550 IDENT@0..1 "x"
551 WHITESPACE@1..2 " "
552 PLUS_EQ@2..4 "+="
553 WHITESPACE@4..5 " "
554 LITERAL_INT@5..6
555 INTEGER@5..6 "1"
556 SEMICOLON@6..7 ";"
557 "#]]);
558 }
559
560 #[test]
565 fn parse_stmt_if_simple() {
566 check_stmt("if cond { }", expect![[r#"
567 ROOT@0..11
568 IF_STMT@0..11
569 KW_IF@0..2 "if"
570 WHITESPACE@2..3 " "
571 PATH_EXPR@3..8
572 IDENT@3..7 "cond"
573 WHITESPACE@7..8 " "
574 BLOCK@8..11
575 L_BRACE@8..9 "{"
576 WHITESPACE@9..10 " "
577 R_BRACE@10..11 "}"
578 "#]]);
579 }
580
581 #[test]
582 fn parse_stmt_if_else() {
583 check_stmt("if a { } else { }", expect![[r#"
584 ROOT@0..17
585 IF_STMT@0..17
586 KW_IF@0..2 "if"
587 WHITESPACE@2..3 " "
588 PATH_EXPR@3..5
589 IDENT@3..4 "a"
590 WHITESPACE@4..5 " "
591 BLOCK@5..8
592 L_BRACE@5..6 "{"
593 WHITESPACE@6..7 " "
594 R_BRACE@7..8 "}"
595 WHITESPACE@8..9 " "
596 KW_ELSE@9..13 "else"
597 BLOCK@13..17
598 WHITESPACE@13..14 " "
599 L_BRACE@14..15 "{"
600 WHITESPACE@15..16 " "
601 R_BRACE@16..17 "}"
602 "#]]);
603 }
604
605 #[test]
610 fn parse_stmt_for() {
611 check_stmt("for i in 0..10 { }", expect![[r#"
612 ROOT@0..18
613 FOR_STMT@0..18
614 KW_FOR@0..3 "for"
615 WHITESPACE@3..4 " "
616 IDENT@4..5 "i"
617 WHITESPACE@5..6 " "
618 KW_IN@6..8 "in"
619 WHITESPACE@8..9 " "
620 LITERAL_INT@9..10
621 INTEGER@9..10 "0"
622 DOT_DOT@10..12 ".."
623 LITERAL_INT@12..14
624 INTEGER@12..14 "10"
625 BLOCK@14..18
626 WHITESPACE@14..15 " "
627 L_BRACE@15..16 "{"
628 WHITESPACE@16..17 " "
629 R_BRACE@17..18 "}"
630 "#]]);
631 }
632
633 #[test]
638 fn parse_stmt_assert() {
639 check_stmt("assert(x);", expect![[r#"
640 ROOT@0..10
641 ASSERT_STMT@0..10
642 KW_ASSERT@0..6 "assert"
643 L_PAREN@6..7 "("
644 PATH_EXPR@7..8
645 IDENT@7..8 "x"
646 R_PAREN@8..9 ")"
647 SEMICOLON@9..10 ";"
648 "#]]);
649 }
650
651 #[test]
652 fn parse_stmt_assert_eq() {
653 check_stmt("assert_eq(a, b);", expect![[r#"
654 ROOT@0..16
655 ASSERT_EQ_STMT@0..16
656 KW_ASSERT_EQ@0..9 "assert_eq"
657 L_PAREN@9..10 "("
658 PATH_EXPR@10..11
659 IDENT@10..11 "a"
660 COMMA@11..12 ","
661 WHITESPACE@12..13 " "
662 PATH_EXPR@13..14
663 IDENT@13..14 "b"
664 R_PAREN@14..15 ")"
665 SEMICOLON@15..16 ";"
666 "#]]);
667 }
668
669 #[test]
674 fn parse_stmt_block() {
675 check_stmt("{ let x = 1; }", expect![[r#"
676 ROOT@0..14
677 BLOCK@0..14
678 L_BRACE@0..1 "{"
679 WHITESPACE@1..2 " "
680 LET_STMT@2..12
681 KW_LET@2..5 "let"
682 WHITESPACE@5..6 " "
683 IDENT_PATTERN@6..7
684 IDENT@6..7 "x"
685 WHITESPACE@7..8 " "
686 EQ@8..9 "="
687 WHITESPACE@9..10 " "
688 LITERAL_INT@10..11
689 INTEGER@10..11 "1"
690 SEMICOLON@11..12 ";"
691 WHITESPACE@12..13 " "
692 R_BRACE@13..14 "}"
693 "#]]);
694 }
695
696 #[test]
697 fn parse_stmt_expr() {
698 check_stmt("foo();", expect![[r#"
699 ROOT@0..6
700 EXPR_STMT@0..6
701 CALL_EXPR@0..5
702 PATH_EXPR@0..3
703 IDENT@0..3 "foo"
704 L_PAREN@3..4 "("
705 R_PAREN@4..5 ")"
706 SEMICOLON@5..6 ";"
707 "#]]);
708 }
709
710 #[test]
715 fn parse_stmt_let_wildcard() {
716 check_stmt("let _ = 1;", expect![[r#"
717 ROOT@0..10
718 LET_STMT@0..10
719 KW_LET@0..3 "let"
720 WHITESPACE@3..4 " "
721 WILDCARD_PATTERN@4..5
722 UNDERSCORE@4..5 "_"
723 WHITESPACE@5..6 " "
724 EQ@6..7 "="
725 WHITESPACE@7..8 " "
726 LITERAL_INT@8..9
727 INTEGER@8..9 "1"
728 SEMICOLON@9..10 ";"
729 "#]]);
730 }
731
732 #[test]
733 fn parse_stmt_let_tuple_wildcard() {
734 check_stmt("let (_, x) = pair;", expect![[r#"
735 ROOT@0..18
736 LET_STMT@0..18
737 KW_LET@0..3 "let"
738 WHITESPACE@3..4 " "
739 TUPLE_PATTERN@4..10
740 L_PAREN@4..5 "("
741 WILDCARD_PATTERN@5..6
742 UNDERSCORE@5..6 "_"
743 COMMA@6..7 ","
744 WHITESPACE@7..8 " "
745 IDENT_PATTERN@8..9
746 IDENT@8..9 "x"
747 R_PAREN@9..10 ")"
748 WHITESPACE@10..11 " "
749 EQ@11..12 "="
750 WHITESPACE@12..13 " "
751 PATH_EXPR@13..17
752 IDENT@13..17 "pair"
753 SEMICOLON@17..18 ";"
754 "#]]);
755 }
756
757 #[test]
762 fn parse_stmt_if_else_if() {
763 check_stmt("if a { } else if b { } else { }", expect![[r#"
764 ROOT@0..31
765 IF_STMT@0..31
766 KW_IF@0..2 "if"
767 WHITESPACE@2..3 " "
768 PATH_EXPR@3..5
769 IDENT@3..4 "a"
770 WHITESPACE@4..5 " "
771 BLOCK@5..8
772 L_BRACE@5..6 "{"
773 WHITESPACE@6..7 " "
774 R_BRACE@7..8 "}"
775 WHITESPACE@8..9 " "
776 KW_ELSE@9..13 "else"
777 IF_STMT@13..31
778 WHITESPACE@13..14 " "
779 KW_IF@14..16 "if"
780 WHITESPACE@16..17 " "
781 PATH_EXPR@17..19
782 IDENT@17..18 "b"
783 WHITESPACE@18..19 " "
784 BLOCK@19..22
785 L_BRACE@19..20 "{"
786 WHITESPACE@20..21 " "
787 R_BRACE@21..22 "}"
788 WHITESPACE@22..23 " "
789 KW_ELSE@23..27 "else"
790 BLOCK@27..31
791 WHITESPACE@27..28 " "
792 L_BRACE@28..29 "{"
793 WHITESPACE@29..30 " "
794 R_BRACE@30..31 "}"
795 "#]]);
796 }
797
798 #[test]
799 fn parse_stmt_if_else_if_chain() {
800 check_stmt("if a { } else if b { } else if c { } else { }", expect![[r#"
801 ROOT@0..45
802 IF_STMT@0..45
803 KW_IF@0..2 "if"
804 WHITESPACE@2..3 " "
805 PATH_EXPR@3..5
806 IDENT@3..4 "a"
807 WHITESPACE@4..5 " "
808 BLOCK@5..8
809 L_BRACE@5..6 "{"
810 WHITESPACE@6..7 " "
811 R_BRACE@7..8 "}"
812 WHITESPACE@8..9 " "
813 KW_ELSE@9..13 "else"
814 IF_STMT@13..45
815 WHITESPACE@13..14 " "
816 KW_IF@14..16 "if"
817 WHITESPACE@16..17 " "
818 PATH_EXPR@17..19
819 IDENT@17..18 "b"
820 WHITESPACE@18..19 " "
821 BLOCK@19..22
822 L_BRACE@19..20 "{"
823 WHITESPACE@20..21 " "
824 R_BRACE@21..22 "}"
825 WHITESPACE@22..23 " "
826 KW_ELSE@23..27 "else"
827 IF_STMT@27..45
828 WHITESPACE@27..28 " "
829 KW_IF@28..30 "if"
830 WHITESPACE@30..31 " "
831 PATH_EXPR@31..33
832 IDENT@31..32 "c"
833 WHITESPACE@32..33 " "
834 BLOCK@33..36
835 L_BRACE@33..34 "{"
836 WHITESPACE@34..35 " "
837 R_BRACE@35..36 "}"
838 WHITESPACE@36..37 " "
839 KW_ELSE@37..41 "else"
840 BLOCK@41..45
841 WHITESPACE@41..42 " "
842 L_BRACE@42..43 "{"
843 WHITESPACE@43..44 " "
844 R_BRACE@44..45 "}"
845 "#]]);
846 }
847
848 #[test]
853 fn parse_stmt_for_typed() {
854 check_stmt("for i: u32 in 0..10 { }", expect![[r#"
855 ROOT@0..23
856 FOR_STMT@0..23
857 KW_FOR@0..3 "for"
858 WHITESPACE@3..4 " "
859 IDENT@4..5 "i"
860 COLON@5..6 ":"
861 WHITESPACE@6..7 " "
862 TYPE_PRIMITIVE@7..10
863 KW_U32@7..10 "u32"
864 WHITESPACE@10..11 " "
865 KW_IN@11..13 "in"
866 WHITESPACE@13..14 " "
867 LITERAL_INT@14..15
868 INTEGER@14..15 "0"
869 DOT_DOT@15..17 ".."
870 LITERAL_INT@17..19
871 INTEGER@17..19 "10"
872 BLOCK@19..23
873 WHITESPACE@19..20 " "
874 L_BRACE@20..21 "{"
875 WHITESPACE@21..22 " "
876 R_BRACE@22..23 "}"
877 "#]]);
878 }
879
880 #[test]
885 fn parse_stmt_assign_sub() {
886 check_stmt("x -= 1;", expect![[r#"
887 ROOT@0..7
888 COMPOUND_ASSIGN_STMT@0..7
889 PATH_EXPR@0..2
890 IDENT@0..1 "x"
891 WHITESPACE@1..2 " "
892 MINUS_EQ@2..4 "-="
893 WHITESPACE@4..5 " "
894 LITERAL_INT@5..6
895 INTEGER@5..6 "1"
896 SEMICOLON@6..7 ";"
897 "#]]);
898 }
899
900 #[test]
901 fn parse_stmt_assign_mul() {
902 check_stmt("x *= 2;", expect![[r#"
903 ROOT@0..7
904 COMPOUND_ASSIGN_STMT@0..7
905 PATH_EXPR@0..2
906 IDENT@0..1 "x"
907 WHITESPACE@1..2 " "
908 STAR_EQ@2..4 "*="
909 WHITESPACE@4..5 " "
910 LITERAL_INT@5..6
911 INTEGER@5..6 "2"
912 SEMICOLON@6..7 ";"
913 "#]]);
914 }
915
916 #[test]
917 fn parse_stmt_assign_div() {
918 check_stmt("x /= 2;", expect![[r#"
919 ROOT@0..7
920 COMPOUND_ASSIGN_STMT@0..7
921 PATH_EXPR@0..2
922 IDENT@0..1 "x"
923 WHITESPACE@1..2 " "
924 SLASH_EQ@2..4 "/="
925 WHITESPACE@4..5 " "
926 LITERAL_INT@5..6
927 INTEGER@5..6 "2"
928 SEMICOLON@6..7 ";"
929 "#]]);
930 }
931
932 #[test]
933 fn parse_stmt_assign_pow() {
934 check_stmt("x **= 2;", expect![[r#"
935 ROOT@0..8
936 COMPOUND_ASSIGN_STMT@0..8
937 PATH_EXPR@0..2
938 IDENT@0..1 "x"
939 WHITESPACE@1..2 " "
940 STAR2_EQ@2..5 "**="
941 WHITESPACE@5..6 " "
942 LITERAL_INT@6..7
943 INTEGER@6..7 "2"
944 SEMICOLON@7..8 ";"
945 "#]]);
946 }
947
948 #[test]
949 fn parse_stmt_assign_bitor() {
950 check_stmt("x |= 1;", expect![[r#"
951 ROOT@0..7
952 COMPOUND_ASSIGN_STMT@0..7
953 PATH_EXPR@0..2
954 IDENT@0..1 "x"
955 WHITESPACE@1..2 " "
956 PIPE_EQ@2..4 "|="
957 WHITESPACE@4..5 " "
958 LITERAL_INT@5..6
959 INTEGER@5..6 "1"
960 SEMICOLON@6..7 ";"
961 "#]]);
962 }
963
964 #[test]
965 fn parse_stmt_assign_bitand() {
966 check_stmt("x &= 1;", expect![[r#"
967 ROOT@0..7
968 COMPOUND_ASSIGN_STMT@0..7
969 PATH_EXPR@0..2
970 IDENT@0..1 "x"
971 WHITESPACE@1..2 " "
972 AMP_EQ@2..4 "&="
973 WHITESPACE@4..5 " "
974 LITERAL_INT@5..6
975 INTEGER@5..6 "1"
976 SEMICOLON@6..7 ";"
977 "#]]);
978 }
979
980 #[test]
981 fn parse_stmt_assign_shl() {
982 check_stmt("x <<= 1;", expect![[r#"
983 ROOT@0..8
984 COMPOUND_ASSIGN_STMT@0..8
985 PATH_EXPR@0..2
986 IDENT@0..1 "x"
987 WHITESPACE@1..2 " "
988 SHL_EQ@2..5 "<<="
989 WHITESPACE@5..6 " "
990 LITERAL_INT@6..7
991 INTEGER@6..7 "1"
992 SEMICOLON@7..8 ";"
993 "#]]);
994 }
995
996 #[test]
997 fn parse_stmt_assign_shr() {
998 check_stmt("x >>= 1;", expect![[r#"
999 ROOT@0..8
1000 COMPOUND_ASSIGN_STMT@0..8
1001 PATH_EXPR@0..2
1002 IDENT@0..1 "x"
1003 WHITESPACE@1..2 " "
1004 SHR_EQ@2..5 ">>="
1005 WHITESPACE@5..6 " "
1006 LITERAL_INT@6..7
1007 INTEGER@6..7 "1"
1008 SEMICOLON@7..8 ";"
1009 "#]]);
1010 }
1011
1012 #[test]
1017 fn parse_stmt_assert_neq() {
1018 check_stmt("assert_neq(a, b);", expect![[r#"
1019 ROOT@0..17
1020 ASSERT_NEQ_STMT@0..17
1021 KW_ASSERT_NEQ@0..10 "assert_neq"
1022 L_PAREN@10..11 "("
1023 PATH_EXPR@11..12
1024 IDENT@11..12 "a"
1025 COMMA@12..13 ","
1026 WHITESPACE@13..14 " "
1027 PATH_EXPR@14..15
1028 IDENT@14..15 "b"
1029 R_PAREN@15..16 ")"
1030 SEMICOLON@16..17 ";"
1031 "#]]);
1032 }
1033
1034 #[test]
1039 fn parse_stmt_expr_call() {
1040 check_stmt("foo(x);", expect![[r#"
1041 ROOT@0..7
1042 EXPR_STMT@0..7
1043 CALL_EXPR@0..6
1044 PATH_EXPR@0..3
1045 IDENT@0..3 "foo"
1046 L_PAREN@3..4 "("
1047 PATH_EXPR@4..5
1048 IDENT@4..5 "x"
1049 R_PAREN@5..6 ")"
1050 SEMICOLON@6..7 ";"
1051 "#]]);
1052 }
1053}