@@ -465,15 +465,25 @@ fn replace_names(input: &str) -> Option<(String, HashMap<String, String>)> {
465
465
466
466
#[ derive( Debug , Clone ) ]
467
467
enum MacroArgKind {
468
+ /// e.g. `$x: expr`.
468
469
MetaVariable ( ast:: Ident , String ) ,
470
+ /// e.g. `$($foo: expr),*`
469
471
Repeat (
472
+ /// `()`, `[]` or `{}`.
470
473
DelimToken ,
474
+ /// Inner arguments inside delimiters.
471
475
Vec < ParsedMacroArg > ,
476
+ /// Something after the closing delimiter and the repeat token, if available.
472
477
Option < Box < ParsedMacroArg > > ,
478
+ /// The repeat token. This could be one of `*`, `+` or `?`.
473
479
Token ,
474
480
) ,
481
+ /// e.g. `[derive(Debug)]`
475
482
Delimited ( DelimToken , Vec < ParsedMacroArg > ) ,
483
+ /// A possible separator. e.g. `,` or `;`.
476
484
Separator ( String , String ) ,
485
+ /// Other random stuff that does not fit to other kinds.
486
+ /// e.g. `== foo` in `($x: expr == foo)`.
477
487
Other ( String , String ) ,
478
488
}
479
489
@@ -589,13 +599,21 @@ impl ParsedMacroArg {
589
599
}
590
600
}
591
601
602
+ /// Parses macro arguments on macro def.
592
603
struct MacroArgParser {
604
+ /// Holds either a name of the next metavariable, a separator or a junk.
605
+ buf : String ,
606
+ /// The start position on the current buffer.
593
607
lo : BytePos ,
608
+ /// The first token of the current buffer.
609
+ start_tok : Token ,
610
+ /// Set to true if we are parsing a metavariable or a repeat.
611
+ is_meta_var : bool ,
612
+ /// The position of the last token.
594
613
hi : BytePos ,
595
- buf : String ,
596
- is_arg : bool ,
614
+ /// The last token parsed.
597
615
last_tok : Token ,
598
- start_tok : Token ,
616
+ /// Holds the parsed arguments.
599
617
result : Vec < ParsedMacroArg > ,
600
618
}
601
619
@@ -612,7 +630,7 @@ impl MacroArgParser {
612
630
lo : BytePos ( 0 ) ,
613
631
hi : BytePos ( 0 ) ,
614
632
buf : String :: new ( ) ,
615
- is_arg : false ,
633
+ is_meta_var : false ,
616
634
last_tok : Token :: Eof ,
617
635
start_tok : Token :: Eof ,
618
636
result : vec ! [ ] ,
@@ -659,12 +677,70 @@ impl MacroArgParser {
659
677
} ) ;
660
678
661
679
self . buf . clear ( ) ;
662
- self . is_arg = false ;
680
+ self . is_meta_var = false ;
663
681
}
664
682
_ => unreachable ! ( ) ,
665
683
}
666
684
}
667
685
686
+ fn add_delimited ( & mut self , inner : Vec < ParsedMacroArg > , delim : DelimToken , span : Span ) {
687
+ self . result . push ( ParsedMacroArg {
688
+ kind : MacroArgKind :: Delimited ( delim, inner) ,
689
+ span,
690
+ } ) ;
691
+ }
692
+
693
+ // $($foo: expr),?
694
+ fn add_repeat (
695
+ & mut self ,
696
+ inner : Vec < ParsedMacroArg > ,
697
+ delim : DelimToken ,
698
+ iter : & mut Cursor ,
699
+ span : Span ,
700
+ ) {
701
+ let mut buffer = String :: new ( ) ;
702
+ let mut first = false ;
703
+ let mut lo = span. lo ( ) ;
704
+ let mut hi = span. hi ( ) ;
705
+
706
+ // Parse '*', '+' or '?.
707
+ while let Some ( ref tok) = iter. next ( ) {
708
+ self . set_last_tok ( tok) ;
709
+ if first {
710
+ first = false ;
711
+ lo = tok. span ( ) . lo ( ) ;
712
+ }
713
+
714
+ match tok {
715
+ TokenTree :: Token ( _, Token :: BinOp ( BinOpToken :: Plus ) )
716
+ | TokenTree :: Token ( _, Token :: Question )
717
+ | TokenTree :: Token ( _, Token :: BinOp ( BinOpToken :: Star ) ) => {
718
+ break ;
719
+ }
720
+ TokenTree :: Token ( sp, ref t) => {
721
+ buffer. push_str ( & pprust:: token_to_string ( t) ) ;
722
+ hi = sp. hi ( ) ;
723
+ }
724
+ _ => unreachable ! ( ) ,
725
+ }
726
+ }
727
+
728
+ // There could be some random stuff between ')' and '*', '+' or '?'.
729
+ let another = if buffer. trim ( ) . is_empty ( ) {
730
+ None
731
+ } else {
732
+ Some ( Box :: new ( ParsedMacroArg {
733
+ kind : MacroArgKind :: Other ( buffer, "" . to_owned ( ) ) ,
734
+ span : mk_sp ( lo, hi) ,
735
+ } ) )
736
+ } ;
737
+
738
+ self . result . push ( ParsedMacroArg {
739
+ kind : MacroArgKind :: Repeat ( delim, inner, another, self . last_tok . clone ( ) ) ,
740
+ span : mk_sp ( self . lo , self . hi ) ,
741
+ } ) ;
742
+ }
743
+
668
744
fn update_buffer ( & mut self , lo : BytePos , t : & Token ) {
669
745
if self . buf . is_empty ( ) {
670
746
self . lo = lo;
@@ -716,15 +792,15 @@ impl MacroArgParser {
716
792
}
717
793
718
794
// Start keeping the name of this metavariable in the buffer.
719
- self . is_arg = true ;
795
+ self . is_meta_var = true ;
720
796
self . lo = sp. lo ( ) ;
721
797
self . start_tok = Token :: Dollar ;
722
798
}
723
- TokenTree :: Token ( _, Token :: Colon ) if self . is_arg => {
799
+ TokenTree :: Token ( _, Token :: Colon ) if self . is_meta_var => {
724
800
self . add_meta_variable ( & mut iter) ;
725
801
}
726
802
TokenTree :: Token ( sp, ref t) => self . update_buffer ( sp. lo ( ) , t) ,
727
- TokenTree :: Delimited ( sp, ref delimited) => {
803
+ TokenTree :: Delimited ( sp, delimited) => {
728
804
if !self . buf . is_empty ( ) {
729
805
if next_space ( & self . last_tok ) == SpaceState :: Always {
730
806
self . add_separator ( ) ;
@@ -733,66 +809,24 @@ impl MacroArgParser {
733
809
}
734
810
}
735
811
812
+ // Parse the stuff inside delimiters.
736
813
let mut parser = MacroArgParser :: new ( ) ;
737
814
parser. lo = sp. lo ( ) ;
738
- let mut delimited_arg = parser. parse ( delimited. tts . clone ( ) ) ;
739
-
740
- if self . is_arg {
741
- // Parse '*' or '+'.
742
- let mut buffer = String :: new ( ) ;
743
- let mut first = false ;
744
- let mut lo = sp. lo ( ) ;
745
-
746
- while let Some ( ref next_tok) = iter. next ( ) {
747
- self . set_last_tok ( next_tok) ;
748
- if first {
749
- first = false ;
750
- lo = next_tok. span ( ) . lo ( ) ;
751
- }
752
-
753
- match next_tok {
754
- TokenTree :: Token ( _, Token :: BinOp ( BinOpToken :: Plus ) )
755
- | TokenTree :: Token ( _, Token :: Question )
756
- | TokenTree :: Token ( _, Token :: BinOp ( BinOpToken :: Star ) ) => {
757
- break ;
758
- }
759
- TokenTree :: Token ( _, ref t) => {
760
- buffer. push_str ( & pprust:: token_to_string ( t) )
761
- }
762
- _ => unreachable ! ( ) ,
763
- }
764
- }
815
+ let delimited_arg = parser. parse ( delimited. tts . clone ( ) ) ;
765
816
766
- let another = if buffer. trim ( ) . is_empty ( ) {
767
- None
768
- } else {
769
- Some ( Box :: new ( ParsedMacroArg {
770
- kind : MacroArgKind :: Other ( buffer, "" . to_owned ( ) ) ,
771
- span : mk_sp ( lo, self . hi ) ,
772
- } ) )
773
- } ;
774
-
775
- self . result . push ( ParsedMacroArg {
776
- kind : MacroArgKind :: Repeat (
777
- delimited. delim ,
778
- delimited_arg,
779
- another,
780
- self . last_tok . clone ( ) ,
781
- ) ,
782
- span : mk_sp ( self . lo , self . hi ) ,
783
- } ) ;
817
+ if self . is_meta_var {
818
+ self . add_repeat ( delimited_arg, delimited. delim , & mut iter, * sp) ;
784
819
} else {
785
- self . result . push ( ParsedMacroArg {
786
- kind : MacroArgKind :: Delimited ( delimited. delim , delimited_arg) ,
787
- span : * sp,
788
- } ) ;
820
+ self . add_delimited ( delimited_arg, delimited. delim , * sp) ;
789
821
}
790
822
}
791
823
}
792
824
793
825
self . set_last_tok ( tok) ;
794
826
}
795
827
828
+ // We are left with some stuff in the buffer. Since there is nothing
829
+ // left to separate, add this as `Other`.
796
830
if !self . buf . is_empty ( ) {
797
831
self . add_other ( ) ;
798
832
}
0 commit comments