Skip to content

Commit cc4e344

Browse files
committed
Produce CloseDelim and pop the stack at the same time.
This makes `CloseDelim` handling more like `OpenDelim` handling, which produces `OpenDelim` and pushes the stack at the same time. It requires some adjustment to `parse_token_tree` now that we don't remain within the frame after getting the `CloseDelim`.
1 parent 7a89255 commit cc4e344

File tree

1 file changed

+34
-27
lines changed
  • compiler/rustc_parse/src/parser

1 file changed

+34
-27
lines changed

compiler/rustc_parse/src/parser/mod.rs

+34-27
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,12 @@ impl<'a> Drop for Parser<'a> {
208208

209209
#[derive(Clone)]
210210
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]`.
211215
frame: TokenCursorFrame,
216+
// Additional frames that enclose `frame`.
212217
stack: Vec<TokenCursorFrame>,
213218
desugar_doc_comments: bool,
214219
// Counts the number of calls to `{,inlined_}next`.
@@ -242,17 +247,11 @@ struct TokenCursorFrame {
242247
delim: token::DelimToken,
243248
span: DelimSpan,
244249
tree_cursor: tokenstream::Cursor,
245-
need_to_produce_close_delim: bool,
246250
}
247251

248252
impl TokenCursorFrame {
249253
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() }
256255
}
257256
}
258257

@@ -265,6 +264,9 @@ impl TokenCursor {
265264
#[inline(always)]
266265
fn inlined_next(&mut self, desugar_doc_comments: bool) -> (Token, Spacing) {
267266
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.
268270
if let Some((tree, spacing)) = self.frame.tree_cursor.next_with_spacing() {
269271
match tree {
270272
TokenTree::Token(token) => match (desugar_doc_comments, &token) {
@@ -283,15 +285,14 @@ impl TokenCursor {
283285
// No open delimeter to return; continue on to the next iteration.
284286
}
285287
};
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-
);
292288
} else if let Some(frame) = self.stack.pop() {
289+
let delim = self.frame.delim;
290+
let span = self.frame.span;
293291
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.
295296
} else {
296297
return (Token::new(token::Eof, DUMMY_SP), Spacing::Alone);
297298
}
@@ -430,6 +431,8 @@ impl<'a> Parser<'a> {
430431
desugar_doc_comments: bool,
431432
subparser_name: Option<&'static str>,
432433
) -> Self {
434+
// Note: because of the way `TokenCursor::inlined_next` is structured, the `span` and
435+
// `delim` arguments here are never used.
433436
let start_frame = TokenCursorFrame::new(DelimSpan::dummy(), token::NoDelim, tokens);
434437

435438
let mut parser = Parser {
@@ -1192,24 +1195,28 @@ impl<'a> Parser<'a> {
11921195
pub(crate) fn parse_token_tree(&mut self) -> TokenTree {
11931196
match self.token.kind {
11941197
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;
11961203

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 {
12021211
// Advance one token at a time, so `TokenCursor::next()`
12031212
// can capture these tokens if necessary.
12041213
self.bump();
1214+
if self.token_cursor.stack.len() == target_depth {
1215+
debug_assert!(matches!(self.token.kind, token::CloseDelim(_)));
1216+
break;
1217+
}
12051218
}
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+
12131220
// Consume close delimiter
12141221
self.bump();
12151222
TokenTree::Delimited(span, delim, stream)

0 commit comments

Comments
 (0)