1use crate::grammar::types::type_;
2
3use super::*;
4
5pub(crate) const LITERAL_FIRST: TokenSet = TokenSet::new(&[
21 T![true],
22 T![false],
23 INT_NUMBER,
24 FLOAT_NUMBER,
25 BYTE,
26 CHAR,
27 STRING,
28 BYTE_STRING,
29 C_STRING,
30]);
31
32pub(crate) fn literal(p: &mut Parser<'_>) -> Option<CompletedMarker> {
33 if !p.at_ts(LITERAL_FIRST) {
34 return None;
35 }
36 let m = p.start();
37 p.bump_any();
38 Some(m.complete(p, LITERAL))
39}
40
41pub(super) const ATOM_EXPR_FIRST: TokenSet =
43 LITERAL_FIRST.union(paths::PATH_FIRST).union(TokenSet::new(&[
44 T!['('],
45 T!['{'],
46 T!['['],
47 T![|],
48 T![async],
49 T![break],
50 T![const],
51 T![continue],
52 T![do],
53 T![gen],
54 T![for],
55 T![if],
56 T![let],
57 T![loop],
58 T![match],
59 T![move],
60 T![return],
61 T![become],
62 T![static],
63 T![try],
64 T![unsafe],
65 T![while],
66 T![yield],
67 LIFETIME_IDENT,
68 ]));
69
70pub(in crate::grammar) const EXPR_RECOVERY_SET: TokenSet =
71 TokenSet::new(&[T!['}'], T![')'], T![']'], T![,]]);
72
73pub(super) fn atom_expr(
74 p: &mut Parser<'_>,
75 r: Restrictions,
76) -> Option<(CompletedMarker, BlockLike)> {
77 if let Some(m) = literal(p) {
78 return Some((m, BlockLike::NotBlock));
79 }
80 if p.at_contextual_kw(T![builtin]) && p.nth_at(1, T![#]) {
81 return Some((builtin_expr(p)?, BlockLike::NotBlock));
82 }
83 if paths::is_path_start(p) {
84 return Some(path_expr(p, r));
85 }
86 let la = p.nth(1);
87 let done = match p.current() {
88 T!['('] => tuple_expr(p),
89 T!['['] => array_expr(p),
90 T![if] => if_expr(p),
91 T![let] => let_expr(p),
92 T![_] => {
93 let m = p.start();
99 p.bump(T![_]);
100 m.complete(p, UNDERSCORE_EXPR)
101 }
102 T![loop] => loop_expr(p, None),
103 T![while] => while_expr(p, None),
104 T![try] => try_block_expr(p, None),
107 T![match] => match_expr(p),
108 T![return] => return_expr(p),
109 T![become] => become_expr(p),
110 T![yield] => yield_expr(p),
111 T![do] if p.nth_at_contextual_kw(1, T![yeet]) => yeet_expr(p),
112 T![continue] => continue_expr(p),
113 T![break] => break_expr(p, r),
114
115 LIFETIME_IDENT if la == T![:] => {
116 let m = p.start();
117 label(p);
118 match p.current() {
119 T![loop] => loop_expr(p, Some(m)),
120 T![for] => for_expr(p, Some(m)),
121 T![while] => while_expr(p, Some(m)),
122 T!['{'] => {
125 stmt_list(p);
126 m.complete(p, BLOCK_EXPR)
127 }
128 _ => {
129 p.error("expected a loop or block");
134 m.complete(p, ERROR);
135 return None;
136 }
137 }
138 }
139 T![const] | T![unsafe] | T![async] | T![gen] if la == T!['{'] => {
145 let m = p.start();
146 p.bump_any();
147 stmt_list(p);
148 m.complete(p, BLOCK_EXPR)
149 }
150 T![async] if la == T![gen] && p.nth(2) == T!['{'] => {
158 let m = p.start();
159 p.bump(T![async]);
160 p.eat(T![gen]);
161 stmt_list(p);
162 m.complete(p, BLOCK_EXPR)
163 }
164 T![async] | T![gen] if la == T![move] && p.nth(2) == T!['{'] => {
165 let m = p.start();
166 p.bump_any();
167 p.bump(T![move]);
168 stmt_list(p);
169 m.complete(p, BLOCK_EXPR)
170 }
171 T![async] if la == T![gen] && p.nth(2) == T![move] && p.nth(3) == T!['{'] => {
172 let m = p.start();
173 p.bump(T![async]);
174 p.bump(T![gen]);
175 p.bump(T![move]);
176 stmt_list(p);
177 m.complete(p, BLOCK_EXPR)
178 }
179 T!['{'] => {
180 let m = p.start();
187 stmt_list(p);
188 m.complete(p, BLOCK_EXPR)
189 }
190
191 T![const] | T![static] | T![async] | T![move] | T![|] => closure_expr(p),
192 T![for] if la == T![<] => closure_expr(p),
193 T![for] => for_expr(p, None),
194
195 _ => {
196 p.err_and_bump("expected expression");
197 return None;
198 }
199 };
200 let blocklike =
201 if BlockLike::is_blocklike(done.kind()) { BlockLike::Block } else { BlockLike::NotBlock };
202 Some((done, blocklike))
203}
204
205fn tuple_expr(p: &mut Parser<'_>) -> CompletedMarker {
212 assert!(p.at(T!['(']));
213 let m = p.start();
214 p.expect(T!['(']);
215
216 let mut saw_comma = false;
217 let mut saw_expr = false;
218
219 if p.eat(T![,]) {
224 p.error("expected expression");
225 saw_comma = true;
226 }
227
228 while !p.at(EOF) && !p.at(T![')']) {
229 saw_expr = true;
230
231 if expr(p).is_none() {
234 break;
235 }
236
237 if !p.at(T![')']) {
238 saw_comma = true;
239 p.expect(T![,]);
240 }
241 }
242 p.expect(T![')']);
243 m.complete(p, if saw_expr && !saw_comma { PAREN_EXPR } else { TUPLE_EXPR })
244}
245
246fn builtin_expr(p: &mut Parser<'_>) -> Option<CompletedMarker> {
253 let m = p.start();
254 p.bump_remap(T![builtin]);
255 p.bump(T![#]);
256 if p.eat_contextual_kw(T![offset_of]) {
257 p.expect(T!['(']);
258 type_(p);
259 p.expect(T![,]);
260 let wrapped_in_parens = p.eat(T!['(']);
265 while !p.at(EOF) && !p.at(T![')']) {
270 name_ref_mod_path_or_index(p);
271 if !p.at(T![')']) {
272 p.expect(T![.]);
273 }
274 }
275 p.expect(T![')']);
276 if wrapped_in_parens {
277 p.expect(T![')']);
278 }
279 Some(m.complete(p, OFFSET_OF_EXPR))
280 } else if p.eat_contextual_kw(T![format_args]) {
281 p.expect(T!['(']);
282 expr(p);
283 if p.eat(T![,]) {
284 while !p.at(EOF) && !p.at(T![')']) {
285 let m = p.start();
286 if p.at(IDENT) && p.nth_at(1, T![=]) && !p.nth_at(2, T![=]) {
287 name(p);
288 p.bump(T![=]);
289 }
290 if expr(p).is_none() {
291 m.abandon(p);
292 break;
293 }
294 m.complete(p, FORMAT_ARGS_ARG);
295
296 if !p.at(T![')']) {
297 p.expect(T![,]);
298 }
299 }
300 }
301 p.expect(T![')']);
302 Some(m.complete(p, FORMAT_ARGS_EXPR))
303 } else if p.eat_contextual_kw(T![asm])
304 || p.eat_contextual_kw(T![global_asm])
305 || p.eat_contextual_kw(T![naked_asm])
306 {
307 parse_asm_expr(p, m)
314 } else {
315 m.abandon(p);
316 None
317 }
318}
319
320pub(crate) fn parse_asm_expr(p: &mut Parser<'_>, m: Marker) -> Option<CompletedMarker> {
332 p.expect(T!['(']);
333 if expr(p).is_none() {
334 p.err_and_bump("expected asm template");
335 }
336 let mut allow_templates = true;
337 while !p.at(EOF) && !p.at(T![')']) {
338 p.expect(T![,]);
339 if p.at(T![')']) {
341 break;
342 }
343
344 let op_n = p.start();
345 if p.eat_contextual_kw(T![clobber_abi]) {
347 parse_clobber_abi(p);
348 op_n.complete(p, ASM_CLOBBER_ABI);
349 allow_templates = false;
350 continue;
351 }
352
353 if p.eat_contextual_kw(T![options]) {
355 parse_options(p);
356 op_n.complete(p, ASM_OPTIONS);
357 allow_templates = false;
358 continue;
359 }
360
361 if p.at(T![ident]) && p.nth_at(1, T![=]) {
363 name(p);
364 p.bump(T![=]);
365 allow_templates = false;
366 }
367
368 let op = p.start();
369 let dir_spec = p.start();
370 if p.eat(T![in]) || p.eat_contextual_kw(T![out]) || p.eat_contextual_kw(T![lateout]) {
371 dir_spec.complete(p, ASM_DIR_SPEC);
372 parse_reg(p);
373 let op_expr = p.start();
374 expr(p);
375 op_expr.complete(p, ASM_OPERAND_EXPR);
376 op.complete(p, ASM_REG_OPERAND);
377 op_n.complete(p, ASM_OPERAND_NAMED);
378 } else if p.eat_contextual_kw(T![inout]) || p.eat_contextual_kw(T![inlateout]) {
379 dir_spec.complete(p, ASM_DIR_SPEC);
380 parse_reg(p);
381 let op_expr = p.start();
382 expr(p);
383 if p.eat(T![=>]) {
384 expr(p);
385 }
386 op_expr.complete(p, ASM_OPERAND_EXPR);
387 op.complete(p, ASM_REG_OPERAND);
388 op_n.complete(p, ASM_OPERAND_NAMED);
389 } else if p.eat_contextual_kw(T![label]) {
390 dir_spec.abandon(p);
395 block_expr(p);
396 op.complete(p, ASM_LABEL);
397 op_n.complete(p, ASM_OPERAND_NAMED);
398 } else if p.eat(T![const]) {
399 dir_spec.abandon(p);
400 expr(p);
401 op.complete(p, ASM_CONST);
402 op_n.complete(p, ASM_OPERAND_NAMED);
403 } else if p.eat_contextual_kw(T![sym]) {
404 dir_spec.abandon(p);
405 paths::type_path(p);
406 op.complete(p, ASM_SYM);
407 op_n.complete(p, ASM_OPERAND_NAMED);
408 } else if allow_templates {
409 dir_spec.abandon(p);
410 op.abandon(p);
411 op_n.abandon(p);
412 if expr(p).is_none() {
413 p.err_and_bump("expected asm template");
414 }
415 continue;
416 } else {
417 dir_spec.abandon(p);
418 op.abandon(p);
419 op_n.abandon(p);
420
421 if p.at(T!['{']) {
423 p.error("expected asm operand");
424 expr(p);
431 } else {
432 p.err_and_bump("expected asm operand");
433 }
434
435 if p.at(T!['}']) {
436 break;
437 }
438 continue;
439 };
440 allow_templates = false;
441 }
442 p.expect(T![')']);
443 Some(m.complete(p, ASM_EXPR))
444}
445
446fn parse_options(p: &mut Parser<'_>) {
447 p.expect(T!['(']);
448
449 while !p.eat(T![')']) && !p.at(EOF) {
450 const OPTIONS: &[SyntaxKind] = &[
451 T![pure],
452 T![nomem],
453 T![readonly],
454 T![preserves_flags],
455 T![noreturn],
456 T![nostack],
457 T![may_unwind],
458 T![att_syntax],
459 T![raw],
460 ];
461 let m = p.start();
462 if !OPTIONS.iter().any(|&syntax| p.eat_contextual_kw(syntax)) {
463 p.err_and_bump("expected asm option");
464 m.abandon(p);
465 continue;
466 }
467 m.complete(p, ASM_OPTION);
468
469 if p.eat(T![')']) {
471 break;
472 }
473 p.expect(T![,]);
474 }
475}
476
477fn parse_clobber_abi(p: &mut Parser<'_>) {
478 p.expect(T!['(']);
479
480 while !p.eat(T![')']) && !p.at(EOF) {
481 if !p.expect(T![string]) {
482 break;
483 }
484
485 if p.eat(T![')']) {
487 break;
488 }
489 p.expect(T![,]);
490 }
491}
492
493fn parse_reg(p: &mut Parser<'_>) {
494 p.expect(T!['(']);
495 if p.at_ts(PATH_NAME_REF_KINDS) {
496 let m = p.start();
497 name_ref_mod_path(p);
498 m.complete(p, ASM_REG_SPEC);
499 } else if p.at(T![string]) {
500 let m = p.start();
501 p.bump_any();
502 m.complete(p, ASM_REG_SPEC);
503 } else {
504 p.err_and_bump("expected register name");
505 }
506 p.expect(T![')']);
507}
508
509fn array_expr(p: &mut Parser<'_>) -> CompletedMarker {
517 assert!(p.at(T!['[']));
518 let m = p.start();
519
520 let mut n_exprs = 0u32;
521 let mut has_semi = false;
522
523 p.bump(T!['[']);
524 while !p.at(EOF) && !p.at(T![']']) {
525 n_exprs += 1;
526
527 if expr(p).is_none() {
530 break;
531 }
532
533 if n_exprs == 1 && p.eat(T![;]) {
534 has_semi = true;
535 continue;
536 }
537
538 if has_semi || !p.at(T![']']) && !p.expect(T![,]) {
539 break;
540 }
541 }
542 p.expect(T![']']);
543
544 m.complete(p, ARRAY_EXPR)
545}
546
547fn closure_expr(p: &mut Parser<'_>) -> CompletedMarker {
564 assert!(match p.current() {
565 T![const] | T![static] | T![async] | T![move] | T![|] => true,
566 T![for] => p.nth(1) == T![<],
567 _ => false,
568 });
569
570 let m = p.start();
571
572 if p.at(T![for]) {
575 types::for_binder(p);
576 }
577 p.eat(T![const]);
580 p.eat(T![static]);
581 p.eat(T![async]);
582 p.eat(T![gen]);
583 p.eat(T![move]);
584
585 if !p.at(T![|]) {
586 p.error("expected `|`");
587 return m.complete(p, CLOSURE_EXPR);
588 }
589 params::param_list_closure(p);
590 if opt_ret_type(p) {
591 while p.at(T![>]) {
594 p.err_and_bump("expected a curly brace");
596 }
597 block_expr(p);
600 } else if p.at_ts(EXPR_FIRST) {
601 expr(p);
604 } else {
605 p.error("expected expression");
606 }
607 m.complete(p, CLOSURE_EXPR)
608}
609
610fn if_expr(p: &mut Parser<'_>) -> CompletedMarker {
619 assert!(p.at(T![if]));
620 let m = p.start();
621 p.bump(T![if]);
622 expr_no_struct(p);
623 block_expr(p);
624 if p.eat(T![else]) {
625 if p.at(T![if]) {
626 if_expr(p);
627 } else {
628 block_expr(p);
629 }
630 }
631 m.complete(p, IF_EXPR)
632}
633
634fn label(p: &mut Parser<'_>) {
641 assert!(p.at(LIFETIME_IDENT) && p.nth(1) == T![:]);
642 let m = p.start();
643 lifetime(p);
644 p.bump_any();
645 m.complete(p, LABEL);
646}
647
648fn loop_expr(p: &mut Parser<'_>, m: Option<Marker>) -> CompletedMarker {
653 assert!(p.at(T![loop]));
654 let m = m.unwrap_or_else(|| p.start());
655 p.bump(T![loop]);
656 block_expr(p);
657 m.complete(p, LOOP_EXPR)
658}
659
660fn while_expr(p: &mut Parser<'_>, m: Option<Marker>) -> CompletedMarker {
667 assert!(p.at(T![while]));
668 let m = m.unwrap_or_else(|| p.start());
669 p.bump(T![while]);
670 expr_no_struct(p);
671 block_expr(p);
672 m.complete(p, WHILE_EXPR)
673}
674
675fn for_expr(p: &mut Parser<'_>, m: Option<Marker>) -> CompletedMarker {
680 assert!(p.at(T![for]));
681 let m = m.unwrap_or_else(|| p.start());
682 p.bump(T![for]);
683 patterns::pattern(p);
684 p.expect(T![in]);
685 expr_no_struct(p);
686 block_expr(p);
687 m.complete(p, FOR_EXPR)
688}
689
690fn let_expr(p: &mut Parser<'_>) -> CompletedMarker {
696 let m = p.start();
697 p.bump(T![let]);
698 patterns::pattern(p);
699 p.expect(T![=]);
700 expr_let(p);
701 m.complete(p, LET_EXPR)
702}
703
704fn match_expr(p: &mut Parser<'_>) -> CompletedMarker {
712 assert!(p.at(T![match]));
713 let m = p.start();
714 p.bump(T![match]);
715 expr_no_struct(p);
716 if p.at(T!['{']) {
717 match_arm_list(p);
718 } else {
719 p.error("expected `{`");
720 }
721 m.complete(p, MATCH_EXPR)
722}
723
724pub(crate) fn match_arm_list(p: &mut Parser<'_>) {
737 assert!(p.at(T!['{']));
738 let m = p.start();
739 p.eat(T!['{']);
740
741 attributes::inner_attrs(p);
751
752 while !p.at(EOF) && !p.at(T!['}']) {
753 if p.at(T!['{']) {
754 error_block(p, "expected match arm");
755 continue;
756 }
757 if p.at(T![,]) {
758 p.err_and_bump("expected pattern");
759 continue;
760 }
761 match_arm(p);
762 }
763 p.expect(T!['}']);
764 m.complete(p, MATCH_ARM_LIST);
765}
766
767fn match_arm(p: &mut Parser<'_>) {
778 let m = p.start();
779 attributes::outer_attrs(p);
793
794 patterns::pattern_top_r(p, TokenSet::new(&[T![=], T![if]]));
795 if p.at(T![if]) {
796 match_guard(p);
797 }
798 p.expect(T![=>]);
799 if p.eat(T![,]) {
800 p.error("expected expression");
801 } else {
802 let blocklike = match expr_stmt(p, None) {
803 Some((_, blocklike)) => blocklike,
804 None => BlockLike::NotBlock,
805 };
806
807 if !p.eat(T![,]) && !blocklike.is_block() && !p.at(T!['}']) {
816 p.error("expected `,`");
817 }
818 }
819 m.complete(p, MATCH_ARM);
820}
821
822fn match_guard(p: &mut Parser<'_>) -> CompletedMarker {
830 assert!(p.at(T![if]));
831 let m = p.start();
832 p.bump(T![if]);
833 if p.at(T![=]) {
834 p.error("expected expression");
835 } else {
836 expr(p);
837 }
838 m.complete(p, MATCH_GUARD)
839}
840
841pub(crate) fn block_expr(p: &mut Parser<'_>) {
847 if !p.at(T!['{']) {
848 p.error("expected a block");
849 return;
850 }
851 let m = p.start();
852 stmt_list(p);
853 m.complete(p, BLOCK_EXPR);
854}
855
856fn stmt_list(p: &mut Parser<'_>) -> CompletedMarker {
857 assert!(p.at(T!['{']));
858 let m = p.start();
859 p.bump(T!['{']);
860 expr_block_contents(p);
861 p.expect(T!['}']);
862 m.complete(p, STMT_LIST)
863}
864
865fn return_expr(p: &mut Parser<'_>) -> CompletedMarker {
871 assert!(p.at(T![return]));
872 let m = p.start();
873 p.bump(T![return]);
874 if p.at_ts(EXPR_FIRST) {
875 expr(p);
876 }
877 m.complete(p, RETURN_EXPR)
878}
879
880fn become_expr(p: &mut Parser<'_>) -> CompletedMarker {
885 assert!(p.at(T![become]));
886 let m = p.start();
887 p.bump(T![become]);
888 expr(p);
889 m.complete(p, BECOME_EXPR)
890}
891
892fn yield_expr(p: &mut Parser<'_>) -> CompletedMarker {
898 assert!(p.at(T![yield]));
899 let m = p.start();
900 p.bump(T![yield]);
901 if p.at_ts(EXPR_FIRST) {
902 expr(p);
903 }
904 m.complete(p, YIELD_EXPR)
905}
906
907fn yeet_expr(p: &mut Parser<'_>) -> CompletedMarker {
913 assert!(p.at(T![do]));
914 assert!(p.nth_at_contextual_kw(1, T![yeet]));
915 let m = p.start();
916 p.bump(T![do]);
917 p.bump_remap(T![yeet]);
918 if p.at_ts(EXPR_FIRST) {
919 expr(p);
920 }
921 m.complete(p, YEET_EXPR)
922}
923
924fn continue_expr(p: &mut Parser<'_>) -> CompletedMarker {
932 assert!(p.at(T![continue]));
933 let m = p.start();
934 p.bump(T![continue]);
935 if p.at(LIFETIME_IDENT) {
936 lifetime(p);
937 }
938 m.complete(p, CONTINUE_EXPR)
939}
940
941fn break_expr(p: &mut Parser<'_>, r: Restrictions) -> CompletedMarker {
951 assert!(p.at(T![break]));
952 let m = p.start();
953 p.bump(T![break]);
954 if p.at(LIFETIME_IDENT) {
955 lifetime(p);
956 }
957 if p.at_ts(EXPR_FIRST) && !(r.forbid_structs && p.at(T!['{'])) {
965 expr(p);
966 }
967 m.complete(p, BREAK_EXPR)
968}
969
970fn try_block_expr(p: &mut Parser<'_>, m: Option<Marker>) -> CompletedMarker {
975 assert!(p.at(T![try]));
976 let m = m.unwrap_or_else(|| p.start());
977 p.bump(T![try]);
978 if p.at(T!['{']) {
979 stmt_list(p);
980 } else {
981 p.error("expected a block");
982 }
983 m.complete(p, BLOCK_EXPR)
984}