@@ -8,3 +8,159 @@ crate mod macro_check;
8
8
crate mod macro_parser;
9
9
crate mod macro_rules;
10
10
crate 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