@@ -102,23 +102,26 @@ use std::rc::Rc;
102
102
use std:: collections:: HashMap ;
103
103
use std:: collections:: hash_map:: Entry :: { Occupied , Vacant } ;
104
104
105
- // To avoid costly uniqueness checks, we require that `MatchSeq` always has
106
- // a nonempty body.
105
+ // To avoid costly uniqueness checks, we require that `MatchSeq` always has a nonempty body.
107
106
107
+ /// Either a sequence of token trees or a single one. This is used as the representation of the
108
+ /// sequence of tokens that make up a matcher.
108
109
#[ derive( Clone ) ]
109
110
enum TokenTreeOrTokenTreeVec {
110
111
Tt ( TokenTree ) ,
111
112
TtSeq ( Vec < TokenTree > ) ,
112
113
}
113
114
114
115
impl TokenTreeOrTokenTreeVec {
116
+ /// Returns the number of constituent token trees of `self`.
115
117
fn len ( & self ) -> usize {
116
118
match * self {
117
119
TtSeq ( ref v) => v. len ( ) ,
118
120
Tt ( ref tt) => tt. len ( ) ,
119
121
}
120
122
}
121
123
124
+ /// The the `index`-th token tree of `self`.
122
125
fn get_tt ( & self , index : usize ) -> TokenTree {
123
126
match * self {
124
127
TtSeq ( ref v) => v[ index] . clone ( ) ,
@@ -127,36 +130,90 @@ impl TokenTreeOrTokenTreeVec {
127
130
}
128
131
}
129
132
130
- /// an unzipping of `TokenTree`s
133
+ /// An unzipping of `TokenTree`s... see the `stack` field of `MatcherPos`.
134
+ ///
135
+ /// This is used by `inner_parse_loop` to keep track of delimited submatchers that we have
136
+ /// descended into.
131
137
#[ derive( Clone ) ]
132
138
struct MatcherTtFrame {
139
+ /// The "parent" matcher that we are descending into.
133
140
elts : TokenTreeOrTokenTreeVec ,
141
+ /// The position of the "dot" in `elts` at the time we descended.
134
142
idx : usize ,
135
143
}
136
144
145
+ /// Represents a single "position" (aka "matcher position", aka "item"), as described in the module
146
+ /// documentation.
137
147
#[ derive( Clone ) ]
138
148
struct MatcherPos {
139
- stack : Vec < MatcherTtFrame > ,
149
+ /// The token or sequence of tokens that make up the matcher
140
150
top_elts : TokenTreeOrTokenTreeVec ,
141
- sep : Option < Token > ,
151
+ /// The position of the "dot" in this matcher
142
152
idx : usize ,
143
- up : Option < Box < MatcherPos > > ,
153
+ /// The beginning position in the source that the beginning of this matcher corresponds to. In
154
+ /// other words, the token in the source at `sp_lo` is matched against the first token of the
155
+ /// matcher.
156
+ sp_lo : BytePos ,
157
+
158
+ /// For each named metavar in the matcher, we keep track of token trees matched against the
159
+ /// metavar by the black box parser. In particular, there may be more than one match per
160
+ /// metavar if we are in a repetition (each repetition matches each of the variables).
161
+ /// Moreover, matchers and repetitions can be nested; the `matches` field is shared (hence the
162
+ /// `Rc`) among all "nested" matchers. `match_lo`, `match_cur`, and `match_hi` keep track of
163
+ /// the current position of the `self` matcher position in the shared `matches` list.
144
164
matches : Vec < Rc < Vec < NamedMatch > > > ,
165
+ /// The position in `matches` corresponding to the first metavar in this matcher's sequence of
166
+ /// token trees. In other words, the first metavar in the first token of `top_elts` corresponds
167
+ /// to `matches[match_lo]`.
145
168
match_lo : usize ,
169
+ /// The position in `matches` corresponding to the metavar we are currently trying to match
170
+ /// against the source token stream. `match_lo <= match_cur <= match_hi`.
146
171
match_cur : usize ,
172
+ /// Similar to `match_lo` except `match_hi` is the position in `matches` of the _last_ metavar
173
+ /// in this matcher.
147
174
match_hi : usize ,
148
- sp_lo : BytePos ,
175
+
176
+ // Specifically used if we are matching a repetition. If we aren't both should be `None`.
177
+ /// The separator if we are in a repetition
178
+ sep : Option < Token > ,
179
+ /// The "parent" matcher position if we are in a repetition. That is, the matcher position just
180
+ /// before we enter the sequence.
181
+ up : Option < Box < MatcherPos > > ,
182
+
183
+ // Specifically used to "unzip" token trees. By "unzip", we mean to unwrap the delimiters from
184
+ // a delimited token tree (e.g. something wrapped in `(` `)`) or to get the contents of a doc
185
+ // comment...
186
+ /// When matching against matchers with nested delimited submatchers (e.g. `pat ( pat ( .. )
187
+ /// pat ) pat`), we need to keep track of the matchers we are descending into. This stack does
188
+ /// that where the bottom of the stack is the outermost matcher.
189
+ // Also, throughout the comments, this "descent" is often referred to as "unzipping"...
190
+ stack : Vec < MatcherTtFrame > ,
149
191
}
150
192
151
193
impl MatcherPos {
194
+ /// Add `m` as a named match for the `idx`-th metavar.
152
195
fn push_match ( & mut self , idx : usize , m : NamedMatch ) {
153
196
let matches = Rc :: make_mut ( & mut self . matches [ idx] ) ;
154
197
matches. push ( m) ;
155
198
}
156
199
}
157
200
201
+ /// Represents the possible results of an attempted parse.
202
+ pub enum ParseResult < T > {
203
+ /// Parsed successfully.
204
+ Success ( T ) ,
205
+ /// Arm failed to match. If the second parameter is `token::Eof`, it indicates an unexpected
206
+ /// end of macro invocation. Otherwise, it indicates that no rules expected the given token.
207
+ Failure ( syntax_pos:: Span , Token ) ,
208
+ /// Fatal error (malformed macro?). Abort compilation.
209
+ Error ( syntax_pos:: Span , String ) ,
210
+ }
211
+
212
+ /// A `ParseResult` where the `Success` variant contains a mapping of `Ident`s to `NamedMatch`es.
213
+ /// This represents the mapping of metavars to the token trees they bind to.
158
214
pub type NamedParseResult = ParseResult < HashMap < Ident , Rc < NamedMatch > > > ;
159
215
216
+ /// Count how many metavars are named in the given matcher `ms`.
160
217
pub fn count_names ( ms : & [ TokenTree ] ) -> usize {
161
218
ms. iter ( ) . fold ( 0 , |count, elt| {
162
219
count + match * elt {
@@ -169,20 +226,38 @@ pub fn count_names(ms: &[TokenTree]) -> usize {
169
226
} )
170
227
}
171
228
229
+ /// Initialize `len` empty shared `Vec`s to be used to store matches of metavars.
230
+ fn create_matches ( len : usize ) -> Vec < Rc < Vec < NamedMatch > > > {
231
+ ( 0 ..len) . into_iter ( ) . map ( |_| Rc :: new ( Vec :: new ( ) ) ) . collect ( )
232
+ }
233
+
234
+ /// Generate the top-level matcher position in which the "dot" is before the first token of the
235
+ /// matcher `ms` and we are going to start matching at position `lo` in the source.
172
236
fn initial_matcher_pos ( ms : Vec < TokenTree > , lo : BytePos ) -> Box < MatcherPos > {
173
237
let match_idx_hi = count_names ( & ms[ ..] ) ;
174
238
let matches = create_matches ( match_idx_hi) ;
175
239
Box :: new ( MatcherPos {
176
- stack : vec ! [ ] ,
177
- top_elts : TtSeq ( ms) ,
178
- sep : None ,
240
+ // Start with the top level matcher given to us
241
+ top_elts : TtSeq ( ms) , // "elts" is an abbr. for "elements"
242
+ // The "dot" is before the first token of the matcher
179
243
idx : 0 ,
180
- up : None ,
244
+ // We start matching with byte `lo` in the source code
245
+ sp_lo : lo,
246
+
247
+ // Initialize `matches` to a bunch of empty `Vec`s -- one for each metavar in `top_elts`.
248
+ // `match_lo` for `top_elts` is 0 and `match_hi` is `matches.len()`. `match_cur` is 0 since
249
+ // we haven't actually matched anything yet.
181
250
matches,
182
251
match_lo : 0 ,
183
252
match_cur : 0 ,
184
253
match_hi : match_idx_hi,
185
- sp_lo : lo,
254
+
255
+ // Haven't descended into any delimiters, so empty stack
256
+ stack : vec ! [ ] ,
257
+
258
+ // Haven't descended into any sequences, so both of these are `None`
259
+ sep : None ,
260
+ up : None ,
186
261
} )
187
262
}
188
263
@@ -202,7 +277,6 @@ fn initial_matcher_pos(ms: Vec<TokenTree>, lo: BytePos) -> Box<MatcherPos> {
202
277
/// token tree. The depth of the `NamedMatch` structure will therefore depend
203
278
/// only on the nesting depth of `ast::TTSeq`s in the originating
204
279
/// token tree it was derived from.
205
-
206
280
#[ derive( Debug , Clone ) ]
207
281
pub enum NamedMatch {
208
282
MatchedSeq ( Rc < Vec < NamedMatch > > , syntax_pos:: Span ) ,
@@ -260,16 +334,6 @@ fn nameize<I: Iterator<Item = NamedMatch>>(
260
334
Success ( ret_val)
261
335
}
262
336
263
- pub enum ParseResult < T > {
264
- Success ( T ) ,
265
- /// Arm failed to match. If the second parameter is `token::Eof`, it
266
- /// indicates an unexpected end of macro invocation. Otherwise, it
267
- /// indicates that no rules expected the given token.
268
- Failure ( syntax_pos:: Span , Token ) ,
269
- /// Fatal error (malformed macro?). Abort compilation.
270
- Error ( syntax_pos:: Span , String ) ,
271
- }
272
-
273
337
pub fn parse_failure_msg ( tok : Token ) -> String {
274
338
match tok {
275
339
token:: Eof => "unexpected end of macro invocation" . to_string ( ) ,
@@ -291,10 +355,6 @@ fn token_name_eq(t1: &Token, t2: &Token) -> bool {
291
355
}
292
356
}
293
357
294
- fn create_matches ( len : usize ) -> Vec < Rc < Vec < NamedMatch > > > {
295
- ( 0 ..len) . into_iter ( ) . map ( |_| Rc :: new ( Vec :: new ( ) ) ) . collect ( )
296
- }
297
-
298
358
fn inner_parse_loop (
299
359
sess : & ParseSess ,
300
360
cur_items : & mut SmallVector < Box < MatcherPos > > ,
@@ -429,14 +489,14 @@ fn inner_parse_loop(
429
489
Success ( ( ) )
430
490
}
431
491
432
- /// Parse the given set of token trees (`ms`), possibly consuming additional token trees from the
433
- /// tokenstream (`tts`) .
492
+ /// Use the given sequence of token trees (`ms`) as a matcher. Match the given token stream `tts`
493
+ /// against it and return the match .
434
494
///
435
495
/// # Parameters
436
496
///
437
497
/// - `sess`: The session into which errors are emitted
438
- /// - `tts`: The tokenstream from which additional token trees may be consumed if needed
439
- /// - `ms`: The token trees we want to parse as macros
498
+ /// - `tts`: The tokenstream we are matching against the pattern `ms`
499
+ /// - `ms`: A sequence of token trees representing a pattern against which we are matching
440
500
/// - `directory`: Information about the file locations (needed for the black-box parser)
441
501
/// - `recurse_into_modules`: Whether or not to recurse into modules (needed for the black-box
442
502
/// parser)
@@ -451,10 +511,10 @@ pub fn parse(
451
511
let mut parser = Parser :: new ( sess, tts, directory, recurse_into_modules, true ) ;
452
512
453
513
// A queue of possible matcher positions. We initialize it with the matcher position in which
454
- // the "dot" is before the first token of the first token tree. `inner_parse_loop` then
514
+ // the "dot" is before the first token of the first token tree in `ms` . `inner_parse_loop` then
455
515
// processes all of these possible matcher positions and produces posible next positions into
456
- // `next_items`. After some post-processing, the contents of `next_items` replenish
457
- // `cur_items` and we start over again.
516
+ // `next_items`. After some post-processing, the contents of `next_items` replenish `cur_items`
517
+ // and we start over again.
458
518
let mut cur_items = SmallVector :: one ( initial_matcher_pos ( ms. to_owned ( ) , parser. span . lo ( ) ) ) ;
459
519
let mut next_items = Vec :: new ( ) ;
460
520
0 commit comments