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`.
This commit is contained in:
parent
7a89255b20
commit
cc4e3443ec
1 changed files with 35 additions and 28 deletions
|
@ -208,7 +208,12 @@ impl<'a> Drop for Parser<'a> {
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
struct TokenCursor {
|
struct TokenCursor {
|
||||||
|
// The current (innermost) frame. `frame` and `stack` could be combined,
|
||||||
|
// but it's faster to have them separately to access `frame` directly
|
||||||
|
// rather than via something like `stack.last().unwrap()` or
|
||||||
|
// `stack[stack.len() - 1]`.
|
||||||
frame: TokenCursorFrame,
|
frame: TokenCursorFrame,
|
||||||
|
// Additional frames that enclose `frame`.
|
||||||
stack: Vec<TokenCursorFrame>,
|
stack: Vec<TokenCursorFrame>,
|
||||||
desugar_doc_comments: bool,
|
desugar_doc_comments: bool,
|
||||||
// Counts the number of calls to `{,inlined_}next`.
|
// Counts the number of calls to `{,inlined_}next`.
|
||||||
|
@ -242,17 +247,11 @@ struct TokenCursorFrame {
|
||||||
delim: token::DelimToken,
|
delim: token::DelimToken,
|
||||||
span: DelimSpan,
|
span: DelimSpan,
|
||||||
tree_cursor: tokenstream::Cursor,
|
tree_cursor: tokenstream::Cursor,
|
||||||
need_to_produce_close_delim: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TokenCursorFrame {
|
impl TokenCursorFrame {
|
||||||
fn new(span: DelimSpan, delim: DelimToken, tts: TokenStream) -> Self {
|
fn new(span: DelimSpan, delim: DelimToken, tts: TokenStream) -> Self {
|
||||||
TokenCursorFrame {
|
TokenCursorFrame { delim, span, tree_cursor: tts.into_trees() }
|
||||||
delim,
|
|
||||||
span,
|
|
||||||
tree_cursor: tts.into_trees(),
|
|
||||||
need_to_produce_close_delim: delim != DelimToken::NoDelim,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -265,6 +264,9 @@ impl TokenCursor {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn inlined_next(&mut self, desugar_doc_comments: bool) -> (Token, Spacing) {
|
fn inlined_next(&mut self, desugar_doc_comments: bool) -> (Token, Spacing) {
|
||||||
loop {
|
loop {
|
||||||
|
// FIXME: we currently don't return `NoDelim` open/close delims. To fix #67062 we will
|
||||||
|
// need to, whereupon the `delim != DelimToken::NoDelim` conditions below can be
|
||||||
|
// removed, as well as the loop.
|
||||||
if let Some((tree, spacing)) = self.frame.tree_cursor.next_with_spacing() {
|
if let Some((tree, spacing)) = self.frame.tree_cursor.next_with_spacing() {
|
||||||
match tree {
|
match tree {
|
||||||
TokenTree::Token(token) => match (desugar_doc_comments, &token) {
|
TokenTree::Token(token) => match (desugar_doc_comments, &token) {
|
||||||
|
@ -283,15 +285,14 @@ impl TokenCursor {
|
||||||
// No open delimeter to return; continue on to the next iteration.
|
// No open delimeter to return; continue on to the next iteration.
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
} else if self.frame.need_to_produce_close_delim {
|
|
||||||
self.frame.need_to_produce_close_delim = false;
|
|
||||||
return (
|
|
||||||
Token::new(token::CloseDelim(self.frame.delim), self.frame.span.close),
|
|
||||||
Spacing::Alone,
|
|
||||||
);
|
|
||||||
} else if let Some(frame) = self.stack.pop() {
|
} else if let Some(frame) = self.stack.pop() {
|
||||||
|
let delim = self.frame.delim;
|
||||||
|
let span = self.frame.span;
|
||||||
self.frame = frame;
|
self.frame = frame;
|
||||||
// Back to the parent frame; continue on to the next iteration.
|
if delim != DelimToken::NoDelim {
|
||||||
|
return (Token::new(token::CloseDelim(delim), span.close), Spacing::Alone);
|
||||||
|
}
|
||||||
|
// No close delimiter to return; continue on to the next iteration.
|
||||||
} else {
|
} else {
|
||||||
return (Token::new(token::Eof, DUMMY_SP), Spacing::Alone);
|
return (Token::new(token::Eof, DUMMY_SP), Spacing::Alone);
|
||||||
}
|
}
|
||||||
|
@ -430,6 +431,8 @@ impl<'a> Parser<'a> {
|
||||||
desugar_doc_comments: bool,
|
desugar_doc_comments: bool,
|
||||||
subparser_name: Option<&'static str>,
|
subparser_name: Option<&'static str>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
|
// Note: because of the way `TokenCursor::inlined_next` is structured, the `span` and
|
||||||
|
// `delim` arguments here are never used.
|
||||||
let start_frame = TokenCursorFrame::new(DelimSpan::dummy(), token::NoDelim, tokens);
|
let start_frame = TokenCursorFrame::new(DelimSpan::dummy(), token::NoDelim, tokens);
|
||||||
|
|
||||||
let mut parser = Parser {
|
let mut parser = Parser {
|
||||||
|
@ -1192,24 +1195,28 @@ impl<'a> Parser<'a> {
|
||||||
pub(crate) fn parse_token_tree(&mut self) -> TokenTree {
|
pub(crate) fn parse_token_tree(&mut self) -> TokenTree {
|
||||||
match self.token.kind {
|
match self.token.kind {
|
||||||
token::OpenDelim(..) => {
|
token::OpenDelim(..) => {
|
||||||
let depth = self.token_cursor.stack.len();
|
// Grab the tokens from this frame.
|
||||||
|
|
||||||
// We keep advancing the token cursor until we hit
|
|
||||||
// the matching `CloseDelim` token.
|
|
||||||
while !(depth == self.token_cursor.stack.len()
|
|
||||||
&& matches!(self.token.kind, token::CloseDelim(_)))
|
|
||||||
{
|
|
||||||
// Advance one token at a time, so `TokenCursor::next()`
|
|
||||||
// can capture these tokens if necessary.
|
|
||||||
self.bump();
|
|
||||||
}
|
|
||||||
// We are still inside the frame corresponding
|
|
||||||
// to the delimited stream we captured, so grab
|
|
||||||
// the tokens from this frame.
|
|
||||||
let frame = &self.token_cursor.frame;
|
let frame = &self.token_cursor.frame;
|
||||||
let stream = frame.tree_cursor.stream.clone();
|
let stream = frame.tree_cursor.stream.clone();
|
||||||
let span = frame.span;
|
let span = frame.span;
|
||||||
let delim = frame.delim;
|
let delim = frame.delim;
|
||||||
|
|
||||||
|
// Advance the token cursor through the entire delimited
|
||||||
|
// sequence. After getting the `OpenDelim` we are *within* the
|
||||||
|
// delimited sequence, i.e. at depth `d`. After getting the
|
||||||
|
// matching `CloseDelim` we are *after* the delimited sequence,
|
||||||
|
// i.e. at depth `d - 1`.
|
||||||
|
let target_depth = self.token_cursor.stack.len() - 1;
|
||||||
|
loop {
|
||||||
|
// Advance one token at a time, so `TokenCursor::next()`
|
||||||
|
// can capture these tokens if necessary.
|
||||||
|
self.bump();
|
||||||
|
if self.token_cursor.stack.len() == target_depth {
|
||||||
|
debug_assert!(matches!(self.token.kind, token::CloseDelim(_)));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Consume close delimiter
|
// Consume close delimiter
|
||||||
self.bump();
|
self.bump();
|
||||||
TokenTree::Delimited(span, delim, stream)
|
TokenTree::Delimited(span, delim, stream)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue