10
10
11
11
// The Rust abstract syntax tree.
12
12
13
- use codemap:: { Span , Spanned , DUMMY_SP , ExpnId } ;
13
+ use codemap:: { Span , Spanned , DUMMY_SP , ExpnId , respan } ;
14
14
use abi:: Abi ;
15
15
use ast_util;
16
16
use owned_slice:: OwnedSlice ;
@@ -713,6 +713,19 @@ impl Delimited {
713
713
}
714
714
}
715
715
716
+ /// A sequence of token treesee
717
+ #[ deriving( Clone , PartialEq , Eq , Encodable , Decodable , Hash , Show ) ]
718
+ pub struct SequenceRepetition {
719
+ /// The sequence of token trees
720
+ pub tts : Vec < TokenTree > ,
721
+ /// The optional separator
722
+ pub separator : Option < token:: Token > ,
723
+ /// Whether the sequence can be repeated zero (*), or one or more times (+)
724
+ pub op : KleeneOp ,
725
+ /// The number of `MatchNt`s that appear in the sequence (and subsequences)
726
+ pub num_captures : uint ,
727
+ }
728
+
716
729
/// A Kleene-style [repetition operator](http://en.wikipedia.org/wiki/Kleene_star)
717
730
/// for token sequences.
718
731
#[ deriving( Clone , PartialEq , Eq , Encodable , Decodable , Hash , Show ) ]
@@ -727,14 +740,12 @@ pub enum KleeneOp {
727
740
/// be passed to syntax extensions using a uniform type.
728
741
///
729
742
/// If the syntax extension is an MBE macro, it will attempt to match its
730
- /// LHS "matchers" against the provided token tree, and if it finds a
743
+ /// LHS token tree against the provided token tree, and if it finds a
731
744
/// match, will transcribe the RHS token tree, splicing in any captured
732
- /// ` macro_parser::matched_nonterminals` into the `TtNonterminal `s it finds.
745
+ /// macro_parser::matched_nonterminals into the `SubstNt `s it finds.
733
746
///
734
- /// The RHS of an MBE macro is the only place a `TtNonterminal` or `TtSequence`
735
- /// makes any real sense. You could write them elsewhere but nothing
736
- /// else knows what to do with them, so you'll probably get a syntax
737
- /// error.
747
+ /// The RHS of an MBE macro is the only place `SubstNt`s are substituted.
748
+ /// Nothing special happens to misnamed or misplaced `SubstNt`s.
738
749
#[ deriving( Clone , PartialEq , Eq , Encodable , Decodable , Hash , Show ) ]
739
750
#[ doc="For macro invocations; parsing is delegated to the macro" ]
740
751
pub enum TokenTree {
@@ -743,90 +754,82 @@ pub enum TokenTree {
743
754
/// A delimited sequence of token trees
744
755
TtDelimited ( Span , Rc < Delimited > ) ,
745
756
746
- // These only make sense for right-hand-sides of MBE macros:
757
+ // This only makes sense in MBE macros.
747
758
748
- /// A Kleene-style repetition sequence with an optional separator.
749
- // FIXME(eddyb) #6308 Use Rc<[TokenTree]> after DST.
750
- TtSequence ( Span , Rc < Vec < TokenTree > > , Option < token:: Token > , KleeneOp ) ,
751
- /// A syntactic variable that will be filled in by macro expansion.
752
- TtNonterminal ( Span , Ident )
759
+ /// A kleene-style repetition sequence with a span
760
+ // FIXME(eddyb) #12938 Use DST.
761
+ TtSequence ( Span , Rc < SequenceRepetition > ) ,
753
762
}
754
763
755
764
impl TokenTree {
765
+ pub fn len ( & self ) -> uint {
766
+ match * self {
767
+ TtToken ( _, token:: DocComment ( _) ) => 2 ,
768
+ TtToken ( _, token:: SubstNt ( ..) ) => 2 ,
769
+ TtToken ( _, token:: MatchNt ( ..) ) => 3 ,
770
+ TtDelimited ( _, ref delimed) => {
771
+ delimed. tts . len ( ) + 2
772
+ }
773
+ TtSequence ( _, ref seq) => {
774
+ seq. tts . len ( )
775
+ }
776
+ TtToken ( ..) => 0
777
+ }
778
+ }
779
+
780
+ pub fn get_tt ( & self , index : uint ) -> TokenTree {
781
+ match ( self , index) {
782
+ ( & TtToken ( sp, token:: DocComment ( _) ) , 0 ) => {
783
+ TtToken ( sp, token:: Pound )
784
+ }
785
+ ( & TtToken ( sp, token:: DocComment ( name) ) , 1 ) => {
786
+ let doc = MetaNameValue ( token:: intern_and_get_ident ( "doc" ) ,
787
+ respan ( sp, LitStr ( token:: get_name ( name) , CookedStr ) ) ) ;
788
+ let doc = token:: NtMeta ( P ( respan ( sp, doc) ) ) ;
789
+ TtDelimited ( sp, Rc :: new ( Delimited {
790
+ delim : token:: Bracket ,
791
+ open_span : sp,
792
+ tts : vec ! [ TtToken ( sp, token:: Interpolated ( doc) ) ] ,
793
+ close_span : sp,
794
+ } ) )
795
+ }
796
+ ( & TtDelimited ( _, ref delimed) , _) => {
797
+ if index == 0 {
798
+ return delimed. open_tt ( ) ;
799
+ }
800
+ if index == delimed. tts . len ( ) + 1 {
801
+ return delimed. close_tt ( ) ;
802
+ }
803
+ delimed. tts [ index - 1 ] . clone ( )
804
+ }
805
+ ( & TtToken ( sp, token:: SubstNt ( name, name_st) ) , _) => {
806
+ let v = [ TtToken ( sp, token:: Dollar ) ,
807
+ TtToken ( sp, token:: Ident ( name, name_st) ) ] ;
808
+ v[ index]
809
+ }
810
+ ( & TtToken ( sp, token:: MatchNt ( name, kind, name_st, kind_st) ) , _) => {
811
+ let v = [ TtToken ( sp, token:: SubstNt ( name, name_st) ) ,
812
+ TtToken ( sp, token:: Colon ) ,
813
+ TtToken ( sp, token:: Ident ( kind, kind_st) ) ] ;
814
+ v[ index]
815
+ }
816
+ ( & TtSequence ( _, ref seq) , _) => {
817
+ seq. tts [ index] . clone ( )
818
+ }
819
+ _ => panic ! ( "Cannot expand a token tree" )
820
+ }
821
+ }
822
+
756
823
/// Returns the `Span` corresponding to this token tree.
757
824
pub fn get_span ( & self ) -> Span {
758
825
match * self {
759
- TtToken ( span, _) => span,
760
- TtDelimited ( span, _) => span,
761
- TtSequence ( span, _, _, _) => span,
762
- TtNonterminal ( span, _) => span,
826
+ TtToken ( span, _) => span,
827
+ TtDelimited ( span, _) => span,
828
+ TtSequence ( span, _) => span,
763
829
}
764
830
}
765
831
}
766
832
767
- // Matchers are nodes defined-by and recognized-by the main rust parser and
768
- // language, but they're only ever found inside syntax-extension invocations;
769
- // indeed, the only thing that ever _activates_ the rules in the rust parser
770
- // for parsing a matcher is a matcher looking for the 'matchers' nonterminal
771
- // itself. Matchers represent a small sub-language for pattern-matching
772
- // token-trees, and are thus primarily used by the macro-defining extension
773
- // itself.
774
- //
775
- // MatchTok
776
- // --------
777
- //
778
- // A matcher that matches a single token, denoted by the token itself. So
779
- // long as there's no $ involved.
780
- //
781
- //
782
- // MatchSeq
783
- // --------
784
- //
785
- // A matcher that matches a sequence of sub-matchers, denoted various
786
- // possible ways:
787
- //
788
- // $(M)* zero or more Ms
789
- // $(M)+ one or more Ms
790
- // $(M),+ one or more comma-separated Ms
791
- // $(A B C);* zero or more semi-separated 'A B C' seqs
792
- //
793
- //
794
- // MatchNonterminal
795
- // -----------------
796
- //
797
- // A matcher that matches one of a few interesting named rust
798
- // nonterminals, such as types, expressions, items, or raw token-trees. A
799
- // black-box matcher on expr, for example, binds an expr to a given ident,
800
- // and that ident can re-occur as an interpolation in the RHS of a
801
- // macro-by-example rule. For example:
802
- //
803
- // $foo:expr => 1 + $foo // interpolate an expr
804
- // $foo:tt => $foo // interpolate a token-tree
805
- // $foo:tt => bar! $foo // only other valid interpolation
806
- // // is in arg position for another
807
- // // macro
808
- //
809
- // As a final, horrifying aside, note that macro-by-example's input is
810
- // also matched by one of these matchers. Holy self-referential! It is matched
811
- // by a MatchSeq, specifically this one:
812
- //
813
- // $( $lhs:matchers => $rhs:tt );+
814
- //
815
- // If you understand that, you have closed the loop and understand the whole
816
- // macro system. Congratulations.
817
- pub type Matcher = Spanned < Matcher_ > ;
818
-
819
- #[ deriving( Clone , PartialEq , Eq , Encodable , Decodable , Hash , Show ) ]
820
- pub enum Matcher_ {
821
- /// Match one token
822
- MatchTok ( token:: Token ) ,
823
- /// Match repetitions of a sequence: body, separator, Kleene operator,
824
- /// lo, hi position-in-match-array used:
825
- MatchSeq ( Vec < Matcher > , Option < token:: Token > , KleeneOp , uint , uint ) ,
826
- /// Parse a Rust NT: name to bind, name of NT, position in match array:
827
- MatchNonterminal ( Ident , Ident , uint )
828
- }
829
-
830
833
pub type Mac = Spanned < Mac_ > ;
831
834
832
835
/// Represents a macro invocation. The Path indicates which macro
0 commit comments