@@ -8,3 +8,159 @@ crate mod macro_check;
88crate mod macro_parser;
99crate mod macro_rules;
1010crate mod quoted;
11+
12+ use crate :: ast;
13+ use crate :: parse:: token:: { self , Token , TokenKind } ;
14+ use crate :: tokenstream:: { DelimSpan } ;
15+
16+ use syntax_pos:: { BytePos , Span } ;
17+
18+ use rustc_data_structures:: sync:: Lrc ;
19+
20+ /// Contains the sub-token-trees of a "delimited" token tree, such as the contents of `(`. Note
21+ /// that the delimiter itself might be `NoDelim`.
22+ #[ derive( Clone , PartialEq , RustcEncodable , RustcDecodable , Debug ) ]
23+ crate struct Delimited {
24+ crate delim : token:: DelimToken ,
25+ crate tts : Vec < TokenTree > ,
26+ }
27+
28+ impl Delimited {
29+ /// Returns a `self::TokenTree` with a `Span` corresponding to the opening delimiter.
30+ crate fn open_tt ( & self , span : Span ) -> TokenTree {
31+ let open_span = if span. is_dummy ( ) {
32+ span
33+ } else {
34+ span. with_hi ( span. lo ( ) + BytePos ( self . delim . len ( ) as u32 ) )
35+ } ;
36+ TokenTree :: token ( token:: OpenDelim ( self . delim ) , open_span)
37+ }
38+
39+ /// Returns a `self::TokenTree` with a `Span` corresponding to the closing delimiter.
40+ crate fn close_tt ( & self , span : Span ) -> TokenTree {
41+ let close_span = if span. is_dummy ( ) {
42+ span
43+ } else {
44+ span. with_lo ( span. hi ( ) - BytePos ( self . delim . len ( ) as u32 ) )
45+ } ;
46+ TokenTree :: token ( token:: CloseDelim ( self . delim ) , close_span)
47+ }
48+ }
49+
50+ #[ derive( Clone , PartialEq , RustcEncodable , RustcDecodable , Debug ) ]
51+ crate struct SequenceRepetition {
52+ /// The sequence of token trees
53+ crate tts : Vec < TokenTree > ,
54+ /// The optional separator
55+ crate separator : Option < Token > ,
56+ /// Whether the sequence can be repeated zero (*), or one or more times (+)
57+ crate kleene : KleeneToken ,
58+ /// The number of `Match`s that appear in the sequence (and subsequences)
59+ crate num_captures : usize ,
60+ }
61+
62+ #[ derive( Clone , PartialEq , RustcEncodable , RustcDecodable , Debug , Copy ) ]
63+ crate struct KleeneToken {
64+ crate span : Span ,
65+ crate op : KleeneOp ,
66+ }
67+
68+ impl KleeneToken {
69+ crate fn new ( op : KleeneOp , span : Span ) -> KleeneToken {
70+ KleeneToken { span, op }
71+ }
72+ }
73+
74+ /// A Kleene-style [repetition operator](http://en.wikipedia.org/wiki/Kleene_star)
75+ /// for token sequences.
76+ #[ derive( Clone , PartialEq , RustcEncodable , RustcDecodable , Hash , Debug , Copy ) ]
77+ crate enum KleeneOp {
78+ /// Kleene star (`*`) for zero or more repetitions
79+ ZeroOrMore ,
80+ /// Kleene plus (`+`) for one or more repetitions
81+ OneOrMore ,
82+ /// Kleene optional (`?`) for zero or one reptitions
83+ ZeroOrOne ,
84+ }
85+
86+ /// Similar to `tokenstream::TokenTree`, except that `$i`, `$i:ident`, and `$(...)`
87+ /// are "first-class" token trees. Useful for parsing macros.
88+ #[ derive( Debug , Clone , PartialEq , RustcEncodable , RustcDecodable ) ]
89+ crate enum TokenTree {
90+ Token ( Token ) ,
91+ Delimited ( DelimSpan , Lrc < Delimited > ) ,
92+ /// A kleene-style repetition sequence
93+ Sequence ( DelimSpan , Lrc < SequenceRepetition > ) ,
94+ /// e.g., `$var`
95+ MetaVar ( Span , ast:: Ident ) ,
96+ /// e.g., `$var:expr`. This is only used in the left hand side of MBE macros.
97+ MetaVarDecl (
98+ Span ,
99+ ast:: Ident , /* name to bind */
100+ ast:: Ident , /* kind of nonterminal */
101+ ) ,
102+ }
103+
104+ impl TokenTree {
105+ /// Return the number of tokens in the tree.
106+ crate fn len ( & self ) -> usize {
107+ match * self {
108+ TokenTree :: Delimited ( _, ref delimed) => match delimed. delim {
109+ token:: NoDelim => delimed. tts . len ( ) ,
110+ _ => delimed. tts . len ( ) + 2 ,
111+ } ,
112+ TokenTree :: Sequence ( _, ref seq) => seq. tts . len ( ) ,
113+ _ => 0 ,
114+ }
115+ }
116+
117+ /// Returns `true` if the given token tree is delimited.
118+ crate fn is_delimited ( & self ) -> bool {
119+ match * self {
120+ TokenTree :: Delimited ( ..) => true ,
121+ _ => false ,
122+ }
123+ }
124+
125+ /// Returns `true` if the given token tree is a token of the given kind.
126+ crate fn is_token ( & self , expected_kind : & TokenKind ) -> bool {
127+ match self {
128+ TokenTree :: Token ( Token { kind : actual_kind, .. } ) => actual_kind == expected_kind,
129+ _ => false ,
130+ }
131+ }
132+
133+ /// Gets the `index`-th sub-token-tree. This only makes sense for delimited trees and sequences.
134+ crate fn get_tt ( & self , index : usize ) -> TokenTree {
135+ match ( self , index) {
136+ ( & TokenTree :: Delimited ( _, ref delimed) , _) if delimed. delim == token:: NoDelim => {
137+ delimed. tts [ index] . clone ( )
138+ }
139+ ( & TokenTree :: Delimited ( span, ref delimed) , _) => {
140+ if index == 0 {
141+ return delimed. open_tt ( span. open ) ;
142+ }
143+ if index == delimed. tts . len ( ) + 1 {
144+ return delimed. close_tt ( span. close ) ;
145+ }
146+ delimed. tts [ index - 1 ] . clone ( )
147+ }
148+ ( & TokenTree :: Sequence ( _, ref seq) , _) => seq. tts [ index] . clone ( ) ,
149+ _ => panic ! ( "Cannot expand a token tree" ) ,
150+ }
151+ }
152+
153+ /// Retrieves the `TokenTree`'s span.
154+ crate fn span ( & self ) -> Span {
155+ match * self {
156+ TokenTree :: Token ( Token { span, .. } )
157+ | TokenTree :: MetaVar ( span, _)
158+ | TokenTree :: MetaVarDecl ( span, _, _) => span,
159+ TokenTree :: Delimited ( span, _) | TokenTree :: Sequence ( span, _) => span. entire ( ) ,
160+ }
161+ }
162+
163+ crate fn token ( kind : TokenKind , span : Span ) -> TokenTree {
164+ TokenTree :: Token ( Token :: new ( kind, span) )
165+ }
166+ }
0 commit comments