@@ -208,7 +208,12 @@ impl<'a> Drop for Parser<'a> {
208
208
209
209
#[ derive( Clone ) ]
210
210
struct TokenCursor {
211
+ // The current (innermost) frame. `frame` and `stack` could be combined,
212
+ // but it's faster to have them separately to access `frame` directly
213
+ // rather than via something like `stack.last().unwrap()` or
214
+ // `stack[stack.len() - 1]`.
211
215
frame : TokenCursorFrame ,
216
+ // Additional frames that enclose `frame`.
212
217
stack : Vec < TokenCursorFrame > ,
213
218
desugar_doc_comments : bool ,
214
219
// Counts the number of calls to `{,inlined_}next`.
@@ -242,17 +247,11 @@ struct TokenCursorFrame {
242
247
delim : token:: DelimToken ,
243
248
span : DelimSpan ,
244
249
tree_cursor : tokenstream:: Cursor ,
245
- need_to_produce_close_delim : bool ,
246
250
}
247
251
248
252
impl TokenCursorFrame {
249
253
fn new ( span : DelimSpan , delim : DelimToken , tts : TokenStream ) -> Self {
250
- TokenCursorFrame {
251
- delim,
252
- span,
253
- tree_cursor : tts. into_trees ( ) ,
254
- need_to_produce_close_delim : delim != DelimToken :: NoDelim ,
255
- }
254
+ TokenCursorFrame { delim, span, tree_cursor : tts. into_trees ( ) }
256
255
}
257
256
}
258
257
@@ -265,6 +264,9 @@ impl TokenCursor {
265
264
#[ inline( always) ]
266
265
fn inlined_next ( & mut self , desugar_doc_comments : bool ) -> ( Token , Spacing ) {
267
266
loop {
267
+ // FIXME: we currently don't return `NoDelim` open/close delims. To fix #67062 we will
268
+ // need to, whereupon the `delim != DelimToken::NoDelim` conditions below can be
269
+ // removed, as well as the loop.
268
270
if let Some ( ( tree, spacing) ) = self . frame . tree_cursor . next_with_spacing ( ) {
269
271
match tree {
270
272
TokenTree :: Token ( token) => match ( desugar_doc_comments, & token) {
@@ -283,15 +285,14 @@ impl TokenCursor {
283
285
// No open delimeter to return; continue on to the next iteration.
284
286
}
285
287
} ;
286
- } else if self . frame . need_to_produce_close_delim {
287
- self . frame . need_to_produce_close_delim = false ;
288
- return (
289
- Token :: new ( token:: CloseDelim ( self . frame . delim ) , self . frame . span . close ) ,
290
- Spacing :: Alone ,
291
- ) ;
292
288
} else if let Some ( frame) = self . stack . pop ( ) {
289
+ let delim = self . frame . delim ;
290
+ let span = self . frame . span ;
293
291
self . frame = frame;
294
- // Back to the parent frame; continue on to the next iteration.
292
+ if delim != DelimToken :: NoDelim {
293
+ return ( Token :: new ( token:: CloseDelim ( delim) , span. close ) , Spacing :: Alone ) ;
294
+ }
295
+ // No close delimiter to return; continue on to the next iteration.
295
296
} else {
296
297
return ( Token :: new ( token:: Eof , DUMMY_SP ) , Spacing :: Alone ) ;
297
298
}
@@ -430,6 +431,8 @@ impl<'a> Parser<'a> {
430
431
desugar_doc_comments : bool ,
431
432
subparser_name : Option < & ' static str > ,
432
433
) -> Self {
434
+ // Note: because of the way `TokenCursor::inlined_next` is structured, the `span` and
435
+ // `delim` arguments here are never used.
433
436
let start_frame = TokenCursorFrame :: new ( DelimSpan :: dummy ( ) , token:: NoDelim , tokens) ;
434
437
435
438
let mut parser = Parser {
@@ -1192,24 +1195,28 @@ impl<'a> Parser<'a> {
1192
1195
pub ( crate ) fn parse_token_tree ( & mut self ) -> TokenTree {
1193
1196
match self . token . kind {
1194
1197
token:: OpenDelim ( ..) => {
1195
- let depth = self . token_cursor . stack . len ( ) ;
1198
+ // Grab the tokens from this frame.
1199
+ let frame = & self . token_cursor . frame ;
1200
+ let stream = frame. tree_cursor . stream . clone ( ) ;
1201
+ let span = frame. span ;
1202
+ let delim = frame. delim ;
1196
1203
1197
- // We keep advancing the token cursor until we hit
1198
- // the matching `CloseDelim` token.
1199
- while !( depth == self . token_cursor . stack . len ( )
1200
- && matches ! ( self . token. kind, token:: CloseDelim ( _) ) )
1201
- {
1204
+ // Advance the token cursor through the entire delimited
1205
+ // sequence. After getting the `OpenDelim` we are *within* the
1206
+ // delimited sequence, i.e. at depth `d`. After getting the
1207
+ // matching `CloseDelim` we are *after* the delimited sequence,
1208
+ // i.e. at depth `d - 1`.
1209
+ let target_depth = self . token_cursor . stack . len ( ) - 1 ;
1210
+ loop {
1202
1211
// Advance one token at a time, so `TokenCursor::next()`
1203
1212
// can capture these tokens if necessary.
1204
1213
self . bump ( ) ;
1214
+ if self . token_cursor . stack . len ( ) == target_depth {
1215
+ debug_assert ! ( matches!( self . token. kind, token:: CloseDelim ( _) ) ) ;
1216
+ break ;
1217
+ }
1205
1218
}
1206
- // We are still inside the frame corresponding
1207
- // to the delimited stream we captured, so grab
1208
- // the tokens from this frame.
1209
- let frame = & self . token_cursor . frame ;
1210
- let stream = frame. tree_cursor . stream . clone ( ) ;
1211
- let span = frame. span ;
1212
- let delim = frame. delim ;
1219
+
1213
1220
// Consume close delimiter
1214
1221
self . bump ( ) ;
1215
1222
TokenTree :: Delimited ( span, delim, stream)
0 commit comments