@@ -161,6 +161,12 @@ struct MatcherPos {
161
161
/// Moreover, matchers and repetitions can be nested; the `matches` field is shared (hence the
162
162
/// `Rc`) among all "nested" matchers. `match_lo`, `match_cur`, and `match_hi` keep track of
163
163
/// the current position of the `self` matcher position in the shared `matches` list.
164
+ ///
165
+ /// Also, note that while we are descending into a sequence, matchers are given their own
166
+ /// `matches` vector. Only once we reach the end of a full repetition of the sequence do we add
167
+ /// all bound matches from the submatcher into the shared top-level `matches` vector. If `sep`
168
+ /// and `up` are `Some`, then `matches` is _not_ the shared top-level list. Instead, if one
169
+ /// wants the shared `matches`, one should use `up.matches`.
164
170
matches : Vec < Rc < Vec < NamedMatch > > > ,
165
171
/// The position in `matches` corresponding to the first metavar in this matcher's sequence of
166
172
/// token trees. In other words, the first metavar in the first token of `top_elts` corresponds
@@ -255,7 +261,7 @@ fn initial_matcher_pos(ms: Vec<TokenTree>, lo: BytePos) -> Box<MatcherPos> {
255
261
// Haven't descended into any delimiters, so empty stack
256
262
stack : vec ! [ ] ,
257
263
258
- // Haven't descended into any sequences, so both of these are `None`
264
+ // Haven't descended into any sequences, so both of these are `None`.
259
265
sep : None ,
260
266
up : None ,
261
267
} )
@@ -355,6 +361,28 @@ fn token_name_eq(t1: &Token, t2: &Token) -> bool {
355
361
}
356
362
}
357
363
364
+ /// Process the matcher positions of `cur_items` until it is empty. In the process, this will
365
+ /// produce more items in `next_items`, `eof_items`, and `bb_items`.
366
+ ///
367
+ /// For more info about the how this happens, see the module-level doc comments and the inline
368
+ /// comments of this function.
369
+ ///
370
+ /// # Parameters
371
+ ///
372
+ /// - `sess`: the parsing session into which errors are emitted.
373
+ /// - `cur_items`: the set of current items to be processed. This should be empty by the end of a
374
+ /// successful execution of this function.
375
+ /// - `next_items`: the set of newly generated items. These are used to replenish `cur_items` in
376
+ /// the function `parse`.
377
+ /// - `eof_items`: the set of items that would be valid if this was the EOF.
378
+ /// - `bb_items`: the set of items that are waiting for the black-box parser.
379
+ /// - `token`: the current token of the parser.
380
+ /// - `span`: the `Span` in the source code corresponding to the token trees we are trying to match
381
+ /// against the matcher positions in `cur_items`.
382
+ ///
383
+ /// # Returns
384
+ ///
385
+ /// A `ParseResult`. Note that matches are kept track of through the items generated.
358
386
fn inner_parse_loop (
359
387
sess : & ParseSess ,
360
388
cur_items : & mut SmallVector < Box < MatcherPos > > ,
@@ -364,8 +392,11 @@ fn inner_parse_loop(
364
392
token : & Token ,
365
393
span : syntax_pos:: Span ,
366
394
) -> ParseResult < ( ) > {
395
+ // Pop items from `cur_items` until it is empty.
367
396
while let Some ( mut item) = cur_items. pop ( ) {
368
- // When unzipped trees end, remove them
397
+ // When unzipped trees end, remove them. This corresponds to backtracking out of a
398
+ // delimited submatcher into which we already descended. In backtracking out again, we need
399
+ // to advance the "dot" past the delimiters in the outer matcher.
369
400
while item. idx >= item. top_elts . len ( ) {
370
401
match item. stack . pop ( ) {
371
402
Some ( MatcherTtFrame { elts, idx } ) => {
@@ -376,37 +407,46 @@ fn inner_parse_loop(
376
407
}
377
408
}
378
409
410
+ // Get the current position of the "dot" (`idx`) in `item` and the number of token trees in
411
+ // the matcher (`len`).
379
412
let idx = item. idx ;
380
413
let len = item. top_elts . len ( ) ;
381
414
382
- // at end of sequence
415
+ // If `idx >= len`, then we are at or past the end of the matcher of `item`.
383
416
if idx >= len {
384
- // We are repeating iff there is a parent
417
+ // We are repeating iff there is a parent. If the matcher is inside of a repetition,
418
+ // then we could be at the end of a sequence or at the beginning of the next
419
+ // repetition.
385
420
if item. up . is_some ( ) {
386
- // Disregarding the separator, add the "up" case to the tokens that should be
387
- // examined.
388
- // (remove this condition to make trailing seps ok)
421
+ // At this point, regardless of whether there is a separator, we should add all
422
+ // matches from the complete repetition of the sequence to the shared, top-level
423
+ // `matches` list (actually, `up.matches`, which could itself not be the top-level,
424
+ // but anyway...). Moreover, we add another item to `cur_items` in which the "dot"
425
+ // is at the end of the `up` matcher. This ensures that the "dot" in the `up`
426
+ // matcher is also advanced sufficiently.
427
+ //
428
+ // NOTE: removing the condition `idx == len` allows trailing separators.
389
429
if idx == len {
430
+ // Get the `up` matcher
390
431
let mut new_pos = item. up . clone ( ) . unwrap ( ) ;
391
432
392
- // update matches (the MBE "parse tree") by appending
393
- // each tree as a subtree.
394
-
395
- // Only touch the binders we have actually bound
433
+ // Add matches from this repetition to the `matches` of `up`
396
434
for idx in item. match_lo ..item. match_hi {
397
435
let sub = item. matches [ idx] . clone ( ) ;
398
436
let span = span. with_lo ( item. sp_lo ) ;
399
437
new_pos. push_match ( idx, MatchedSeq ( sub, span) ) ;
400
438
}
401
439
440
+ // Move the "dot" past the repetition in `up`
402
441
new_pos. match_cur = item. match_hi ;
403
442
new_pos. idx += 1 ;
404
443
cur_items. push ( new_pos) ;
405
444
}
406
445
407
- // Check if we need a separator
446
+ // Check if we need a separator.
408
447
if idx == len && item. sep . is_some ( ) {
409
- // We have a separator, and it is the current token.
448
+ // We have a separator, and it is the current token. We can advance past the
449
+ // separator token.
410
450
if item. sep
411
451
. as_ref ( )
412
452
. map ( |sep| token_name_eq ( token, sep) )
@@ -415,14 +455,18 @@ fn inner_parse_loop(
415
455
item. idx += 1 ;
416
456
next_items. push ( item) ;
417
457
}
418
- } else {
419
- // we don't need a separator
458
+ }
459
+ // We don't need a separator. Move the "dot" back to the beginning of the matcher
460
+ // and try to match again.
461
+ else {
420
462
item. match_cur = item. match_lo ;
421
463
item. idx = 0 ;
422
464
cur_items. push ( item) ;
423
465
}
424
- } else {
425
- // We aren't repeating, so we must be potentially at the end of the input.
466
+ }
467
+ // If we are not in a repetition, then being at the end of a matcher means that we have
468
+ // reached the potential end of the input.
469
+ else {
426
470
eof_items. push ( item) ;
427
471
}
428
472
} else {
0 commit comments