1use crate::ast::{self, Delimiter, Kind};
2use crate::compile::{ErrorKind, Result};
3
4use super::{Checkpoint, Parser};
5
6use Kind::*;
7
8trait ExprCx {
9 fn recover(&self, p: &mut Parser<'_>) -> Result<()>;
10}
11
12struct ErrorCx;
14
15impl ExprCx for ErrorCx {
16 fn recover(&self, p: &mut Parser<'_>) -> Result<()> {
17 Err(p.expected_at(0, Kind::Expr)?)
18 }
19}
20
21#[derive(Default)]
22struct Modifiers {
23 is_pub: bool,
24 is_const: bool,
25 is_async: bool,
26}
27
28#[derive(Debug, Clone, Copy)]
29enum Brace {
30 Yes,
31 No,
32}
33
34#[derive(Debug, Clone, Copy)]
35enum Binary {
36 Yes,
37 No,
38}
39
40#[derive(Debug, Clone, Copy)]
41enum Range {
42 Yes,
43 No,
44}
45
46macro_rules! __ws {
47 () => {
48 $crate::ast::Kind::Whitespace
49 | $crate::ast::Kind::Comment
50 | $crate::ast::Kind::MultilineComment(..)
51 };
52}
53
54macro_rules! __object_key {
55 () => {
56 K![ident] | K![str]
57 };
58}
59
60pub(crate) use __object_key as object_key;
61pub(crate) use __ws as ws;
62
63macro_rules! lit {
64 () => {
65 K![true] | K![false] | K![number] | K![str] | K![bytestr] | K![char] | K![byte]
66 };
67}
68
69macro_rules! path_component {
70 () => {
71 K![::] | K![ident] | K![super] | K![crate] | K![self] | K![Self]
72 }
73}
74
75pub(super) fn root(p: &mut Parser<'_>) -> Result<()> {
76 p.open(Root)?;
77
78 while !p.is_eof()? {
79 stmt(p)?;
80 }
81
82 p.flush_ws()?;
83 p.close()?;
84 Ok(())
85}
86
87pub(super) fn exprs(p: &mut Parser<'_>, separator: Kind) -> Result<()> {
89 p.open(Root)?;
90
91 while !p.is_eof()? {
92 expr(p)?;
93 p.bump_while(separator)?;
94 }
95
96 p.flush_ws()?;
97 p.close()?;
98 Ok(())
99}
100
101pub(super) fn format(p: &mut Parser<'_>) -> Result<()> {
103 p.open(Root)?;
104 expr(p)?;
105
106 while !p.is_eof()? {
107 p.bump()?;
108 }
109
110 p.flush_ws()?;
111 p.close()?;
112 Ok(())
113}
114
115#[tracing::instrument(skip_all)]
116fn stmt(p: &mut Parser<'_>) -> Result<()> {
117 struct StmtCx;
118
119 #[tracing::instrument(skip(p))]
120 fn is_stmt_recovering(p: &mut Parser<'_>) -> Result<bool> {
121 let is = match p.peek()? {
122 Eof => false,
123 K![;] => false,
124 K![let] => false,
125 K![use] => false,
126 K![struct] => false,
127 K![enum] => false,
128 K![fn] => false,
129 K![impl] => false,
130 K![mod] => false,
131 K![ident] => false,
132 K![pub] => false,
133 K![const] => false,
134 K![async] => false,
135 K![#] => !matches!(p.nth(1)?, K!['['] | K![!]),
136 _ => true,
137 };
138
139 Ok(is)
140 }
141
142 impl ExprCx for StmtCx {
143 fn recover(&self, p: &mut Parser<'_>) -> Result<()> {
144 while is_stmt_recovering(p)? {
145 p.bump()?;
146 }
147
148 Ok(())
149 }
150 }
151
152 inner_attributes(p)?;
153
154 let c = p.checkpoint()?;
155 attributes(p)?;
156
157 let inner_c = p.checkpoint()?;
158 let m = modifiers(p)?;
159
160 let cx = StmtCx;
161
162 let kind = match p.peek()? {
163 K![let] => {
164 local(p, &cx)?;
165 Local
166 }
167 K![use] => {
168 item_use(p)?;
169 p.close_at(&inner_c, ItemUse)?;
170 Item
171 }
172 K![struct] => {
173 item_struct(p)?;
174 p.close_at(&inner_c, ItemStruct)?;
175 Item
176 }
177 K![enum] => {
178 item_enum(p)?;
179 p.close_at(&inner_c, ItemEnum)?;
180 Item
181 }
182 K![fn] => {
183 item_fn(p)?;
184 p.close_at(&inner_c, ItemFn)?;
185 Item
186 }
187 K![impl] => {
188 item_impl(p)?;
189 p.close_at(&inner_c, ItemImpl)?;
190 Item
191 }
192 K![mod] => {
193 if item_mod(p)? {
194 p.close_at(&inner_c, ItemMod)?;
195 } else {
196 p.close_at(&inner_c, ItemFileMod)?;
197 }
198
199 Item
200 }
201 K![ident] if m.is_const => {
202 item_const(p)?;
203 p.close_at(&inner_c, ItemConst)?;
204 Item
205 }
206 _ => {
207 labels(p)?;
208
209 if matches!(
210 outer_expr_with(p, Brace::Yes, Range::Yes, Binary::Yes, &cx)?,
211 Error
212 ) {
213 Error
214 } else {
215 Expr
216 }
217 }
218 };
219
220 p.close_at(&c, kind)?;
221 p.bump_while(K![;])?;
222 Ok(())
223}
224
225#[tracing::instrument(skip_all)]
226fn item_const(p: &mut Parser<'_>) -> Result<()> {
227 p.bump()?;
228 p.bump_if(K![=])?;
229 expr(p)?;
230 Ok(())
231}
232
233#[tracing::instrument(skip_all)]
234fn inner_attributes(p: &mut Parser<'_>) -> Result<()> {
235 while matches!((p.peek()?, p.glued(1)?), (K![#], K![!])) {
236 let c = p.checkpoint()?;
237
238 p.bump()?;
239 p.bump_if(K![!])?;
240
241 if p.bump_if(K!['['])? {
242 token_stream(p, brackets)?;
243 p.bump()?;
244 }
245
246 p.close_at(&c, InnerAttribute)?;
247 }
248
249 Ok(())
250}
251
252#[tracing::instrument(skip_all)]
253fn attributes(p: &mut Parser<'_>) -> Result<()> {
254 while matches!((p.peek()?, p.glued(1)?), (K![#], K!['['])) {
255 let c = p.checkpoint()?;
256
257 p.bump()?;
258
259 if p.bump_if(K!['['])? {
260 token_stream(p, brackets)?;
261 p.bump()?;
262 }
263
264 p.close_at(&c, Attribute)?;
265 }
266
267 Ok(())
268}
269
270#[tracing::instrument(skip_all)]
271fn modifiers(p: &mut Parser<'_>) -> Result<Modifiers> {
272 let c = p.checkpoint()?;
273
274 let mut mods = Modifiers::default();
275 let mut has_mods = false;
276
277 loop {
278 match p.peek()? {
279 K![pub] => {
280 mods.is_pub = true;
281 p.bump()?;
282
283 if p.peek()? == K!['('] {
284 let c = p.checkpoint()?;
285 p.bump()?;
286
287 let kind = match p.peek()? {
288 K![super] => {
289 p.bump()?;
290 ModifierSuper
291 }
292 K![self] => {
293 p.bump()?;
294 ModifierSelf
295 }
296 K![crate] => {
297 p.bump()?;
298 ModifierCrate
299 }
300 K![in] => {
301 p.bump()?;
302 path(p)?;
303 ModifierIn
304 }
305 _ => Error,
306 };
307
308 p.bump_if(K![')'])?;
309 p.close_at(&c, kind)?;
310 }
311 }
312 K![const] => {
313 mods.is_const = true;
314 p.bump()?;
315 }
316 K![async] => {
317 mods.is_async = true;
318 p.bump()?;
319 }
320 K![move] => {
321 p.bump()?;
322 }
323 _ => {
324 break;
325 }
326 }
327
328 has_mods = true;
329 }
330
331 if has_mods {
332 p.close_at(&c, Modifiers)?;
333 }
334
335 Ok(mods)
336}
337
338#[tracing::instrument(skip_all)]
339fn local(p: &mut Parser<'_>, cx: &dyn ExprCx) -> Result<()> {
340 p.bump()?;
341 pat(p)?;
342 p.bump_if(K![=])?;
343 expr_with(p, Brace::Yes, Range::Yes, Binary::Yes, cx)?;
344 Ok(())
345}
346
347#[tracing::instrument(skip_all)]
348fn item_struct(p: &mut Parser<'_>) -> Result<()> {
349 p.bump()?;
350
351 if matches!(p.peek()?, K![ident]) {
352 p.bump()?;
353 }
354
355 match p.peek()? {
356 K!['{'] => {
357 struct_body(p)?;
358 }
359 K!['('] => {
360 tuple_body(p)?;
361 }
362 _ => {
363 empty_body(p)?;
364 }
365 }
366
367 Ok(())
368}
369
370#[tracing::instrument(skip_all)]
371fn item_use(p: &mut Parser<'_>) -> Result<()> {
372 p.bump()?;
373
374 loop {
375 match p.peek()? {
376 path_component!() | K![*] => {
377 p.bump()?;
378 }
379 K!['{'] => {
380 let c = p.checkpoint()?;
381 p.bump()?;
382
383 while matches!(p.peek()?, path_component!() | K!['{'] | K![*]) {
384 let c = p.checkpoint()?;
385 item_use(p)?;
386 p.close_at(&c, ItemUsePath)?;
387 p.bump_while(K![,])?;
388 }
389
390 p.bump_if(K!['}'])?;
391 p.close_at(&c, ItemUseGroup)?;
392 }
393 K![as] => {
394 p.bump()?;
395 p.bump_if_matches(|k| matches!(k, K![ident]))?;
396 }
397 _ => break,
398 }
399 }
400
401 Ok(())
402}
403
404#[tracing::instrument(skip_all)]
405fn item_enum(p: &mut Parser<'_>) -> Result<()> {
406 p.bump()?;
407
408 if matches!(p.peek()?, K![ident]) {
409 p.bump()?;
410 }
411
412 if p.bump_if(K!['{'])? {
413 while matches!(p.peek()?, K![ident]) {
414 let variant = p.checkpoint()?;
415
416 p.bump()?;
417
418 match p.peek()? {
419 K!['{'] => {
420 struct_body(p)?;
421 }
422 K!['('] => {
423 tuple_body(p)?;
424 }
425 _ => {
426 p.empty(EmptyBody)?;
427 }
428 }
429
430 p.close_at(&variant, Variant)?;
431 p.bump_while(K![,])?;
432 }
433
434 p.bump_if(K!['}'])?;
435 }
436
437 Ok(())
438}
439
440#[tracing::instrument(skip_all)]
441fn empty_body(p: &mut Parser<'_>) -> Result<()> {
442 let c = p.checkpoint()?;
443 p.close_at(&c, EmptyBody)?;
444 Ok(())
445}
446
447#[tracing::instrument(skip_all)]
448fn struct_body(p: &mut Parser<'_>) -> Result<()> {
449 let c = p.checkpoint()?;
450
451 p.bump()?;
452
453 while matches!(p.peek()?, K![ident]) {
454 let c = p.checkpoint()?;
455 p.bump()?;
456 p.close_at(&c, Field)?;
457 p.bump_while(K![,])?;
458 }
459
460 p.bump_if(K!['}'])?;
461 p.close_at(&c, StructBody)?;
462 Ok(())
463}
464
465#[tracing::instrument(skip_all)]
466fn tuple_body(p: &mut Parser<'_>) -> Result<()> {
467 let c = p.checkpoint()?;
468
469 p.bump()?;
470
471 while matches!(p.peek()?, K![ident]) {
472 let c = p.checkpoint()?;
473 p.bump()?;
474 p.close_at(&c, Field)?;
475 p.bump_while(K![,])?;
476 }
477
478 p.bump_if(K![')'])?;
479 p.close_at(&c, TupleBody)?;
480 Ok(())
481}
482
483#[tracing::instrument(skip_all)]
484fn item_fn(p: &mut Parser<'_>) -> Result<()> {
485 p.bump()?;
486
487 if matches!(p.peek()?, K![ident]) {
488 p.bump()?;
489 }
490
491 if p.peek()? == K!['('] {
492 let c = p.checkpoint()?;
493 p.bump()?;
494
495 p.bump_while(K![,])?;
496
497 while is_pat(p)? {
498 pat(p)?;
499 p.bump_while(K![,])?;
500 }
501
502 p.bump_if(K![')'])?;
503 p.close_at(&c, FnArgs)?;
504 }
505
506 if p.peek()? == K!['{'] {
507 block(p)?;
508 }
509
510 Ok(())
511}
512
513#[tracing::instrument(skip_all)]
514fn item_impl(p: &mut Parser<'_>) -> Result<()> {
515 p.bump()?;
516
517 if matches!(p.peek()?, path_component!()) {
518 path(p)?;
519 }
520
521 block(p)?;
522 Ok(())
523}
524
525#[tracing::instrument(skip_all)]
526fn item_mod(p: &mut Parser<'_>) -> Result<bool> {
527 p.bump()?;
528
529 if matches!(p.peek()?, K![ident]) {
530 p.bump()?;
531 }
532
533 if matches!(p.peek()?, K!['{']) {
534 block(p)?;
535 Ok(true)
536 } else {
537 Ok(false)
538 }
539}
540
541#[tracing::instrument(skip_all)]
542fn is_pat(p: &mut Parser<'_>) -> Result<bool> {
543 Ok(match p.peek()? {
544 path_component!() => true,
545 lit!() => true,
546 K![_] => true,
547 K!['('] => true,
548 K!['['] => true,
549 K![-] => matches!(p.glued(1)?, K![number]),
550 K![#] => matches!(p.glued(1)?, K!['{']),
551 _ => false,
552 })
553}
554
555#[tracing::instrument(skip_all)]
556fn pat(p: &mut Parser<'_>) -> Result<()> {
557 let c = p.checkpoint()?;
558 attributes(p)?;
559
560 match p.peek()? {
561 lit!() => {
562 let c = p.checkpoint()?;
563 p.bump()?;
564 p.close_at(&c, Lit)?;
565 }
566 K![-] => {
567 let c = p.checkpoint()?;
568 p.bump()?;
569
570 if matches!(p.peek()?, K![number]) {
571 p.bump()?;
572 }
573
574 p.close_at(&c, Lit)?;
575 }
576 K![_] => {
577 let c = p.checkpoint()?;
578 p.bump()?;
579 p.close_at(&c, PatIgnore)?;
580 }
581 path_component!() => {
582 let c = p.checkpoint()?;
583 path(p)?;
584
585 match p.peek()? {
586 K!['{'] => {
587 pat_object(p)?;
588 p.close_at(&c, PatObject)?;
589 }
590 K!['('] => {
591 pat_parens(p, K![')'])?;
592 p.close_at(&c, PatTuple)?;
593 }
594 _ => {}
595 }
596 }
597 K!['['] => {
598 let c = p.checkpoint()?;
599 pat_parens(p, K![']'])?;
600 p.close_at(&c, PatArray)?;
601 }
602 K!['('] => {
603 let c = p.checkpoint()?;
604 pat_parens(p, K![')'])?;
605 p.close_at(&c, PatTuple)?;
606 }
607 K![#] if matches!(p.glued(1)?, K!['{']) => {
608 let c = p.checkpoint()?;
609 p.bump()?;
610 p.close_at(&c, AnonymousObjectKey)?;
611 pat_object(p)?;
612 p.close_at(&c, PatObject)?;
613 }
614 _ => {
615 let c = p.checkpoint()?;
616 p.close_at(&c, Error)?;
617 }
618 }
619
620 p.close_at(&c, Pat)?;
621 Ok(())
622}
623
624fn is_expr(p: &mut Parser<'_>) -> Result<bool> {
625 is_expr_with(p, Brace::Yes, Range::Yes)
626}
627
628#[tracing::instrument(skip(p))]
629fn is_expr_with(p: &mut Parser<'_>, brace: Brace, range: Range) -> Result<bool> {
630 Ok(match p.peek()? {
631 path_component!() => true,
632 K![async] => true,
633 K![break] => true,
634 K![continue] => true,
635 K![for] => true,
636 K![if] => true,
637 K![let] => true,
638 K![loop] => true,
639 K![match] => true,
640 K![return] => true,
641 K![select] => true,
642 K![while] => true,
643 lit!() => true,
644 K![||] | K![|] => true,
645 K![#] => true,
646 K![-] => true,
647 K![!] => true,
648 K![&] => true,
649 K![*] => true,
650 K!['label] => matches!(p.glued(1)?, K![:]),
651 Kind::Open(Delimiter::Empty) => true,
652 K!['('] => true,
653 K!['['] => true,
654 K!['{'] => matches!(brace, Brace::Yes),
655 K![..] => matches!(range, Range::Yes),
656 K![..=] => matches!(range, Range::Yes),
657 TemplateString => true,
658 _ => false,
659 })
660}
661
662#[tracing::instrument(skip_all)]
663fn expr(p: &mut Parser<'_>) -> Result<()> {
664 let c = p.checkpoint()?;
665 attributes(p)?;
666 modifiers(p)?;
667 labels(p)?;
668 let cx = ErrorCx;
669 outer_expr_with(p, Brace::Yes, Range::Yes, Binary::Yes, &cx)?;
670 p.close_at(&c, Expr)?;
671 Ok(())
672}
673
674#[tracing::instrument(skip_all)]
675fn expr_with(
676 p: &mut Parser<'_>,
677 brace: Brace,
678 range: Range,
679 binary: Binary,
680 cx: &dyn ExprCx,
681) -> Result<()> {
682 let c = p.checkpoint()?;
683 attributes(p)?;
684 modifiers(p)?;
685 labels(p)?;
686 outer_expr_with(p, brace, range, binary, cx)?;
687 p.close_at(&c, Expr)?;
688 Ok(())
689}
690
691fn is_range(kind: Kind) -> bool {
692 match kind {
693 ExprRangeTo => true,
694 ExprRangeToInclusive => true,
695 ExprRangeFull => true,
696 ExprRange => true,
697 ExprRangeInclusive => true,
698 ExprRangeFrom => true,
699 _ => false,
700 }
701}
702
703fn outer_expr_with(
704 p: &mut Parser<'_>,
705 brace: Brace,
706 range: Range,
707 binary: Binary,
708 cx: &dyn ExprCx,
709) -> Result<Kind> {
710 let c = p.checkpoint()?;
711 let mut kind = expr_primary(p, brace, range, cx)?;
712
713 if is_range(kind) {
714 return Ok(kind);
715 }
716
717 kind = expr_chain(p, &c, kind)?;
718
719 if p.peek()? == K![=] {
720 p.close_at(&c, Expr)?;
721 p.bump()?;
722 expr_with(p, brace, Range::Yes, Binary::Yes, cx)?;
723 p.close_at(&c, ExprAssign)?;
724 return Ok(ExprAssign);
725 }
726
727 if matches!(binary, Binary::Yes) {
728 let slice = p.array::<2>()?;
729 let lookahead = ast::BinOp::from_slice(&slice);
730
731 kind = if expr_binary(p, lookahead, 0, brace, cx)? {
732 p.close_at(&c, ExprBinary)?;
733 ExprBinary
734 } else {
735 kind
736 };
737 }
738
739 if matches!(range, Range::Yes) {
740 kind = expr_range(p, &c, kind, brace)?;
741 }
742
743 Ok(kind)
744}
745
746fn labels(p: &mut Parser<'_>) -> Result<()> {
747 while matches!(p.peek()?, K!['label]) {
748 p.bump()?;
749 p.bump_while(K![:])?;
750 }
751
752 Ok(())
753}
754
755#[tracing::instrument(skip_all)]
756fn expr_primary(p: &mut Parser<'_>, brace: Brace, range: Range, cx: &dyn ExprCx) -> Result<Kind> {
757 let c = p.checkpoint()?;
758
759 let kind = match p.peek()? {
760 lit!() => {
761 p.bump()?;
762 Lit
763 }
764 path_component!() => {
765 path(p)?;
766
767 match p.peek()? {
768 K!['{'] if matches!(brace, Brace::Yes) => {
769 expr_object(p)?;
770 ExprObject
771 }
772 K![!] if matches!(p.glued(1)?, K!['(']) => {
773 p.bump()?;
774 p.bump()?;
775 token_stream(p, parens)?;
776 p.bump()?;
777 ExprMacroCall
778 }
779 K![!] if matches!(p.glued(1)?, K!['{']) => {
780 p.bump()?;
781 p.bump()?;
782 token_stream(p, braces)?;
783 p.bump()?;
784 ExprMacroCall
785 }
786 _ => return Ok(Path),
787 }
788 }
789 Kind::Open(Delimiter::Empty) => empty_group(p)?,
790 K!['('] => expr_tuple_or_group(p)?,
791 K!['['] => {
792 parenthesized(p, is_expr, expr, K![']'])?;
793 ExprArray
794 }
795 K!['{'] => {
796 block_with(p)?;
797 Block
798 }
799 TemplateString => {
800 p.bump()?;
801 TemplateString
802 }
803 K![||] => {
804 p.push(ClosureArguments)?;
805 expr_with(p, brace, range, Binary::Yes, cx)?;
806 ExprClosure
807 }
808 K![|] => {
809 let args = p.checkpoint()?;
810 parenthesized(p, is_pat, pat, K![|])?;
811 p.close_at(&args, ClosureArguments)?;
812
813 expr_with(p, brace, range, Binary::Yes, cx)?;
814 ExprClosure
815 }
816 K![-] if matches!(p.glued(1)?, K![number]) => {
817 p.bump()?;
818 p.bump()?;
819 Lit
820 }
821 K![!] | K![-] | K![&] | K![*] => {
822 p.bump()?;
823 outer_expr_with(p, brace, range, Binary::No, cx)?;
824 ExprUnary
825 }
826 K![if] => {
827 expr_if(p)?;
828 ExprIf
829 }
830 K![while] => {
831 expr_while(p)?;
832 ExprWhile
833 }
834 K![loop] => {
835 expr_loop(p)?;
836 ExprLoop
837 }
838 K![break] => {
839 p.bump()?;
840
841 labels(p)?;
842
843 if is_expr_with(p, brace, range)? {
844 let cx = ErrorCx;
845 expr_with(p, brace, range, Binary::Yes, &cx)?;
846 }
847
848 ExprBreak
849 }
850 K![continue] => {
851 p.bump()?;
852 labels(p)?;
853 ExprContinue
854 }
855 K![return] => {
856 p.bump()?;
857
858 if is_expr_with(p, brace, range)? {
859 let cx = ErrorCx;
860 expr_with(p, brace, range, Binary::Yes, &cx)?;
861 }
862
863 ExprReturn
864 }
865 K![yield] => {
866 p.bump()?;
867
868 if is_expr_with(p, brace, range)? {
869 let cx = ErrorCx;
870 expr_with(p, brace, range, Binary::Yes, &cx)?;
871 }
872
873 ExprYield
874 }
875 K![for] => {
876 expr_for(p)?;
877 ExprFor
878 }
879 K![select] => {
880 expr_select(p)?;
881 ExprSelect
882 }
883 K![match] => {
884 expr_match(p)?;
885 ExprMatch
886 }
887 K![..] if matches!(range, Range::Yes) => {
888 p.bump()?;
889
890 if is_expr_with(p, brace, Range::No)? {
891 let cx = ErrorCx;
892 outer_expr_with(p, brace, Range::No, Binary::Yes, &cx)?;
893 ExprRangeTo
894 } else {
895 ExprRangeFull
896 }
897 }
898 K![..=] if matches!(range, Range::Yes) => {
899 p.bump()?;
900 let cx = ErrorCx;
901 outer_expr_with(p, brace, Range::No, Binary::Yes, &cx)?;
902 ExprRangeToInclusive
903 }
904 K![#] if matches!(p.glued(1)?, K!['{']) => {
905 let key = p.checkpoint()?;
906 p.bump()?;
907 p.close_at(&key, AnonymousObjectKey)?;
908 expr_object(p)?;
909 ExprObject
910 }
911 _ => {
912 cx.recover(p)?;
913 Error
914 }
915 };
916
917 p.close_at(&c, kind)?;
918 Ok(kind)
919}
920
921fn kind_is_callable(kind: Kind) -> bool {
922 match kind {
923 ExprWhile => false,
924 ExprLoop => true,
925 ExprFor => false,
926 ExprIf => true,
927 ExprMatch => true,
928 ExprSelect => true,
929 _ => true,
930 }
931}
932
933#[tracing::instrument(skip_all)]
934fn expr_chain(p: &mut Parser<'_>, c: &Checkpoint, mut kind: Kind) -> Result<Kind> {
935 let mut before = p.checkpoint()?;
936 let mut has_chain = false;
937
938 while !p.is_eof()? {
939 let is_callable = kind_is_callable(kind);
940
941 let k = match p.peek()? {
942 K!['['] if is_callable => {
943 p.bump()?;
944 expr(p)?;
945 p.bump_if(K![']'])?;
946 ExprIndex
947 }
948 K!['('] if is_callable => {
950 parenthesized(p, is_expr, expr, K![')'])?;
951 ExprCall
952 }
953 K![?] => {
954 p.bump()?;
955 ExprTry
956 }
957 K![.] => {
958 p.bump()?;
959
960 match p.peek()? {
961 K![await] => {
963 p.bump()?;
964 ExprAwait
965 }
966 path_component!() => {
968 path(p)?;
969 ExprField
970 }
971 K![number] => {
973 p.bump()?;
974 ExprField
975 }
976 _ => Error,
977 }
978 }
979 _ => {
980 break;
981 }
982 };
983
984 p.close_at(&before, k)?;
985 kind = k;
986 before = p.checkpoint()?;
987 has_chain = true;
988 }
989
990 if has_chain {
991 p.close_at(c, ExprChain)?;
992 }
993
994 Ok(kind)
995}
996
997#[tracing::instrument(skip_all)]
998fn empty_group(p: &mut Parser<'_>) -> Result<Kind> {
999 p.bump()?;
1000 expr(p)?;
1001 p.bump_if(Kind::Close(Delimiter::Empty))?;
1002 Ok(ExprEmptyGroup)
1003}
1004
1005#[tracing::instrument(skip_all)]
1006fn expr_tuple_or_group(p: &mut Parser<'_>) -> Result<Kind> {
1007 p.bump()?;
1008
1009 let mut is_tuple = false;
1010
1011 while is_expr(p)? {
1012 expr(p)?;
1013
1014 if p.bump_while(K![,])? {
1015 is_tuple = true;
1016 }
1017 }
1018
1019 p.bump_if(K![')'])?;
1020 let kind = if is_tuple { ExprTuple } else { ExprGroup };
1021 Ok(kind)
1022}
1023
1024#[tracing::instrument(skip_all)]
1025fn expr_object(p: &mut Parser<'_>) -> Result<()> {
1026 p.bump()?;
1027
1028 while matches!(p.peek()?, object_key!()) {
1029 p.bump()?;
1030
1031 if p.bump_if(K![:])? {
1032 expr(p)?;
1033 }
1034
1035 p.bump_while(K![,])?;
1036 }
1037
1038 p.bump_if(K!['}'])?;
1039 Ok(())
1040}
1041
1042#[tracing::instrument(skip_all)]
1043fn pat_object(p: &mut Parser<'_>) -> Result<()> {
1044 p.bump()?;
1045
1046 loop {
1047 match p.peek()? {
1048 K![..] => {
1049 p.bump()?;
1050 }
1051 object_key!() => {
1052 p.bump()?;
1053
1054 if p.bump_if(K![:])? {
1055 pat(p)?;
1056 }
1057
1058 p.bump_while(K![,])?;
1059 }
1060 _ => {
1061 break;
1062 }
1063 }
1064 }
1065
1066 p.bump_if(K!['}'])?;
1067 Ok(())
1068}
1069
1070#[tracing::instrument(skip_all)]
1071fn expr_if(p: &mut Parser<'_>) -> Result<()> {
1072 p.bump()?;
1073 condition(p)?;
1074 block(p)?;
1075
1076 while p.peek()? == K![else] {
1077 let c = p.checkpoint()?;
1078 p.bump()?;
1079
1080 let else_if = if p.bump_if(K![if])? {
1081 condition(p)?;
1082 true
1083 } else {
1084 false
1085 };
1086
1087 block(p)?;
1088
1089 if else_if {
1090 p.close_at(&c, ExprElseIf)?;
1091 } else {
1092 p.close_at(&c, ExprElse)?;
1093 }
1094 }
1095
1096 Ok(())
1097}
1098
1099#[tracing::instrument(skip_all)]
1100fn expr_while(p: &mut Parser<'_>) -> Result<()> {
1101 p.bump()?;
1102 condition(p)?;
1103 block(p)?;
1104 Ok(())
1105}
1106
1107#[tracing::instrument(skip_all)]
1108fn expr_loop(p: &mut Parser<'_>) -> Result<()> {
1109 p.bump()?;
1110 block(p)?;
1111 Ok(())
1112}
1113
1114#[tracing::instrument(skip_all)]
1115fn expr_for(p: &mut Parser<'_>) -> Result<()> {
1116 p.bump()?;
1117 pat(p)?;
1118
1119 if p.bump_if(K![in])? {
1120 let cx = ErrorCx;
1121 expr_with(p, Brace::No, Range::Yes, Binary::Yes, &cx)?;
1122 }
1123
1124 block(p)?;
1125 Ok(())
1126}
1127
1128#[tracing::instrument(skip_all)]
1129fn expr_match(p: &mut Parser<'_>) -> Result<()> {
1130 p.bump()?;
1131
1132 let cx = ErrorCx;
1133 expr_with(p, Brace::No, Range::Yes, Binary::Yes, &cx)?;
1134
1135 if matches!(p.peek()?, K!['{']) {
1136 p.bump()?;
1137
1138 while is_pat(p)? {
1139 let c = p.checkpoint()?;
1140 pat(p)?;
1141
1142 if p.bump_if(K![if])? {
1143 expr(p)?;
1144 }
1145
1146 if p.bump_if(K![=>])? {
1147 expr(p)?;
1148 }
1149
1150 p.close_at(&c, ExprMatchArm)?;
1151 p.bump_while(K![,])?;
1152 }
1153
1154 p.bump_if(K!['}'])?;
1155 }
1156
1157 Ok(())
1158}
1159
1160#[tracing::instrument(skip_all)]
1161fn expr_select(p: &mut Parser<'_>) -> Result<()> {
1162 p.bump()?;
1163
1164 if matches!(p.peek()?, K!['{']) {
1165 p.bump()?;
1166
1167 while is_pat(p)? || p.peek()? == K![default] {
1168 let c = p.checkpoint()?;
1169
1170 match p.peek()? {
1171 K![default] => {
1172 p.bump()?;
1173 }
1174 _ => {
1175 pat(p)?;
1176
1177 if p.bump_if(K![=])? {
1178 expr(p)?;
1179 }
1180 }
1181 }
1182
1183 if p.bump_if(K![=>])? {
1184 expr(p)?;
1185 }
1186
1187 p.close_at(&c, ExprSelectArm)?;
1188 p.bump_while(K![,])?;
1189 }
1190
1191 p.bump_if(K!['}'])?;
1192 }
1193
1194 Ok(())
1195}
1196
1197#[tracing::instrument(skip_all)]
1198fn condition(p: &mut Parser<'_>) -> Result<()> {
1199 if p.peek()? == K![let] {
1200 let c = p.checkpoint()?;
1201 p.bump()?;
1202 pat(p)?;
1203
1204 if p.peek()? == K![=] {
1205 p.bump()?;
1206 let cx = ErrorCx;
1207 expr_with(p, Brace::No, Range::Yes, Binary::Yes, &cx)?;
1208 }
1209
1210 p.close_at(&c, Condition)?;
1211 } else {
1212 let cx = ErrorCx;
1213 expr_with(p, Brace::No, Range::Yes, Binary::Yes, &cx)?;
1214 }
1215
1216 Ok(())
1217}
1218
1219#[tracing::instrument(skip_all)]
1220fn path(p: &mut Parser<'_>) -> Result<()> {
1221 let c = p.checkpoint()?;
1222
1223 while matches!(p.peek()?, path_component!()) {
1224 let has_generics = matches!(p.peek()?, K![::]);
1228 p.bump()?;
1229
1230 while has_generics && matches!(p.peek()?, K![<]) {
1233 let c = p.checkpoint()?;
1234 p.bump()?;
1235
1236 while matches!(p.peek()?, path_component!()) {
1237 path(p)?;
1239 p.bump_while(K![,])?;
1240 }
1241
1242 p.bump_if(K![>])?;
1243 p.close_at(&c, PathGenerics)?;
1244 }
1245 }
1246
1247 p.close_at(&c, Path)?;
1248 Ok(())
1249}
1250
1251#[tracing::instrument(skip_all)]
1252fn expr_binary(
1253 p: &mut Parser<'_>,
1254 mut lookahead: Option<ast::BinOp>,
1255 min_precedence: usize,
1256 brace: Brace,
1257 cx: &dyn ExprCx,
1258) -> Result<bool> {
1259 let mut has_any = false;
1260
1261 while let Some(op) = lookahead.take() {
1262 let precedence = op.precedence();
1263
1264 if precedence < min_precedence {
1265 break;
1266 }
1267
1268 let op_c = p.checkpoint()?;
1269 op.advance(p)?;
1270 p.close_at(&op_c, ExprOperator)?;
1271
1272 let c = p.checkpoint()?;
1273 outer_expr_with(p, brace, Range::No, Binary::No, cx)?;
1274
1275 has_any = true;
1276
1277 let slice = p.array::<2>()?;
1278 lookahead = ast::BinOp::from_slice(&slice);
1279
1280 while let Some(next) = lookahead {
1281 match (precedence, next.precedence()) {
1282 (lh, rh) if lh < rh => {
1283 if expr_binary(p, Some(next), lh + 1, brace, cx)? {
1285 p.close_at(&c, ExprBinary)?;
1286 }
1287
1288 let slice = p.array::<2>()?;
1289 lookahead = ast::BinOp::from_slice(&slice);
1290 continue;
1291 }
1292 (lh, rh) if lh == rh => {
1293 if !next.is_assoc() {
1294 return Err(p.error(c.span(), ErrorKind::PrecedenceGroupRequired)?);
1295 }
1296 }
1297 _ => {}
1298 };
1299
1300 break;
1301 }
1302 }
1303
1304 Ok(has_any)
1305}
1306
1307#[tracing::instrument(skip_all)]
1308fn expr_range(p: &mut Parser<'_>, c: &Checkpoint, kind: Kind, brace: Brace) -> Result<Kind> {
1309 let kind = match p.peek()? {
1310 K![..] => {
1311 p.bump()?;
1312
1313 if is_expr_with(p, brace, Range::No)? {
1314 let cx = ErrorCx;
1315 outer_expr_with(p, brace, Range::No, Binary::Yes, &cx)?;
1316 ExprRange
1317 } else {
1318 ExprRangeFrom
1319 }
1320 }
1321 K![..=] => {
1322 p.bump()?;
1323
1324 if is_expr_with(p, brace, Range::No)? {
1325 let cx = ErrorCx;
1326 outer_expr_with(p, brace, Range::No, Binary::Yes, &cx)?;
1327 ExprRangeInclusive
1328 } else {
1329 Error
1330 }
1331 }
1332 _ => {
1333 return Ok(kind);
1334 }
1335 };
1336
1337 p.close_at(c, kind)?;
1338 Ok(kind)
1339}
1340#[tracing::instrument(skip_all)]
1341fn block(p: &mut Parser<'_>) -> Result<()> {
1342 let c = p.checkpoint()?;
1343 block_with(p)?;
1344 p.close_at(&c, Block)?;
1345 Ok(())
1346}
1347
1348#[tracing::instrument(skip_all)]
1349fn block_with(p: &mut Parser<'_>) -> Result<()> {
1350 if p.bump_if(K!['{'])? {
1351 let c = p.checkpoint()?;
1352
1353 while !matches!(p.peek()?, K!['}'] | Eof) {
1354 stmt(p)?;
1355 }
1356
1357 p.close_at(&c, BlockBody)?;
1358 }
1359
1360 p.bump_if(K!['}'])?;
1361 Ok(())
1362}
1363
1364#[tracing::instrument(skip(p))]
1365fn pat_parens(p: &mut Parser, end: Kind) -> Result<()> {
1366 p.bump()?;
1367
1368 while is_pat(p)? || p.peek()? == K![..] {
1369 match p.peek()? {
1370 K![..] => {
1371 p.bump()?;
1372 }
1373 _ => {
1374 pat(p)?;
1375 }
1376 }
1377
1378 p.bump_while(K![,])?;
1379 }
1380
1381 p.bump_if(end)?;
1382 Ok(())
1383}
1384
1385#[tracing::instrument(skip(p, is, parser))]
1386fn parenthesized(
1387 p: &mut Parser,
1388 is: fn(&mut Parser<'_>) -> Result<bool>,
1389 parser: fn(&mut Parser<'_>) -> Result<()>,
1390 end: Kind,
1391) -> Result<()> {
1392 p.bump()?;
1393
1394 while is(p)? {
1395 parser(p)?;
1396 p.bump_while(K![,])?;
1397 }
1398
1399 p.bump_if(end)?;
1400 Ok(())
1401}
1402
1403fn brackets(kind: Kind) -> i32 {
1404 match kind {
1405 K!['['] => 1,
1406 K![']'] => -1,
1407 _ => 0,
1408 }
1409}
1410
1411fn parens(kind: Kind) -> i32 {
1412 match kind {
1413 K!['('] => 1,
1414 K![')'] => -1,
1415 _ => 0,
1416 }
1417}
1418
1419fn braces(kind: Kind) -> i32 {
1420 match kind {
1421 K!['{'] => 1,
1422 K!['}'] => -1,
1423 _ => 0,
1424 }
1425}
1426
1427#[tracing::instrument(skip_all)]
1429fn token_stream(p: &mut Parser<'_>, matcher: fn(Kind) -> i32) -> Result<()> {
1430 let c = p.checkpoint()?;
1431
1432 let mut level = 1u32;
1433
1434 while level > 0 {
1435 let m = matcher(p.peek()?);
1436
1437 level = level.wrapping_add_signed(m);
1438
1439 if level == 0 {
1440 break;
1441 }
1442
1443 p.bump()?;
1444 }
1445
1446 p.close_at(&c, TokenStream)?;
1447 Ok(())
1448}