Add some useful comments to Parser::look_ahead.

This commit is contained in:
Nicholas Nethercote 2023-08-09 15:02:30 +10:00
parent 04cf6b4ac5
commit e8f733370f

View File

@ -1052,33 +1052,48 @@ pub fn bump(&mut self) {
} }
/// Look-ahead `dist` tokens of `self.token` and get access to that token there. /// Look-ahead `dist` tokens of `self.token` and get access to that token there.
/// When `dist == 0` then the current token is looked at. /// When `dist == 0` then the current token is looked at. `Eof` will be
/// returned if the look-ahead is any distance past the end of the tokens.
pub fn look_ahead<R>(&self, dist: usize, looker: impl FnOnce(&Token) -> R) -> R { pub fn look_ahead<R>(&self, dist: usize, looker: impl FnOnce(&Token) -> R) -> R {
if dist == 0 { if dist == 0 {
return looker(&self.token); return looker(&self.token);
} }
let tree_cursor = &self.token_cursor.tree_cursor;
if let Some(&(_, delim, span)) = self.token_cursor.stack.last() if let Some(&(_, delim, span)) = self.token_cursor.stack.last()
&& delim != Delimiter::Invisible && delim != Delimiter::Invisible
{ {
// We are not in the outermost token stream, and the token stream
// we are in has non-skipped delimiters. Look for skipped
// delimiters in the lookahead range.
let tree_cursor = &self.token_cursor.tree_cursor;
let all_normal = (0..dist).all(|i| { let all_normal = (0..dist).all(|i| {
let token = tree_cursor.look_ahead(i); let token = tree_cursor.look_ahead(i);
!matches!(token, Some(TokenTree::Delimited(_, Delimiter::Invisible, _))) !matches!(token, Some(TokenTree::Delimited(_, Delimiter::Invisible, _)))
}); });
if all_normal { if all_normal {
// There were no skipped delimiters. Do lookahead by plain indexing.
return match tree_cursor.look_ahead(dist - 1) { return match tree_cursor.look_ahead(dist - 1) {
Some(tree) => match tree { Some(tree) => {
TokenTree::Token(token, _) => looker(token), // Indexing stayed within the current token stream.
TokenTree::Delimited(dspan, delim, _) => { match tree {
looker(&Token::new(token::OpenDelim(*delim), dspan.open)) TokenTree::Token(token, _) => looker(token),
TokenTree::Delimited(dspan, delim, _) => {
looker(&Token::new(token::OpenDelim(*delim), dspan.open))
}
} }
}, }
None => looker(&Token::new(token::CloseDelim(delim), span.close)), None => {
// Indexing went past the end of the current token
// stream. Use the close delimiter, no matter how far
// ahead `dist` went.
looker(&Token::new(token::CloseDelim(delim), span.close))
}
}; };
} }
} }
// We are in a more complex case. Just clone the token cursor and use
// `next`, skipping delimiters as necessary. Slow but simple.
let mut cursor = self.token_cursor.clone(); let mut cursor = self.token_cursor.clone();
let mut i = 0; let mut i = 0;
let mut token = Token::dummy(); let mut token = Token::dummy();