compiler: add Parser::debug_lookahead
I tried debugging a parser-related issue but found it annoying to not be able to easily peek into the Parser's token stream. Add a convenience fn that offers an opinionated view into the parser, but one that is useful for answering basic questions about parser state.
This commit is contained in:
parent
c70290da0a
commit
5e67a3783c
@ -5,6 +5,7 @@
|
|||||||
#![allow(rustc::untranslatable_diagnostic)]
|
#![allow(rustc::untranslatable_diagnostic)]
|
||||||
#![feature(array_windows)]
|
#![feature(array_windows)]
|
||||||
#![feature(box_patterns)]
|
#![feature(box_patterns)]
|
||||||
|
#![feature(debug_closure_helpers)]
|
||||||
#![feature(if_let_guard)]
|
#![feature(if_let_guard)]
|
||||||
#![feature(iter_intersperse)]
|
#![feature(iter_intersperse)]
|
||||||
#![feature(let_chains)]
|
#![feature(let_chains)]
|
||||||
|
@ -1537,6 +1537,47 @@ fn is_import_coupler(&mut self) -> bool {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// debug view of the parser's token stream, up to `{lookahead}` tokens
|
||||||
|
pub fn debug_lookahead(&self, lookahead: usize) -> impl fmt::Debug + '_ {
|
||||||
|
struct DebugParser<'dbg> {
|
||||||
|
parser: &'dbg Parser<'dbg>,
|
||||||
|
lookahead: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Debug for DebugParser<'_> {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
let Self { parser, lookahead } = self;
|
||||||
|
let mut dbg_fmt = f.debug_struct("Parser"); // or at least, one view of
|
||||||
|
|
||||||
|
// we don't need N spans, but we want at least one, so print all of prev_token
|
||||||
|
dbg_fmt.field("prev_token", &parser.prev_token);
|
||||||
|
// make it easier to peek farther ahead by taking TokenKinds only until EOF
|
||||||
|
let tokens = (0..*lookahead)
|
||||||
|
.map(|i| parser.look_ahead(i, |tok| tok.kind.clone()))
|
||||||
|
.scan(parser.prev_token == TokenKind::Eof, |eof, tok| {
|
||||||
|
let current = eof.then_some(tok.clone()); // include a trailing EOF token
|
||||||
|
*eof |= &tok == &TokenKind::Eof;
|
||||||
|
current
|
||||||
|
});
|
||||||
|
dbg_fmt.field_with("tokens", |field| field.debug_list().entries(tokens).finish());
|
||||||
|
dbg_fmt.field("approx_token_stream_pos", &parser.num_bump_calls);
|
||||||
|
|
||||||
|
// some fields are interesting for certain values, as they relate to macro parsing
|
||||||
|
if let Some(subparser) = parser.subparser_name {
|
||||||
|
dbg_fmt.field("subparser_name", &subparser);
|
||||||
|
}
|
||||||
|
if let Recovery::Forbidden = parser.recovery {
|
||||||
|
dbg_fmt.field("recovery", &parser.recovery);
|
||||||
|
}
|
||||||
|
|
||||||
|
// imply there's "more to know" than this view
|
||||||
|
dbg_fmt.finish_non_exhaustive()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DebugParser { parser: self, lookahead }
|
||||||
|
}
|
||||||
|
|
||||||
pub fn clear_expected_tokens(&mut self) {
|
pub fn clear_expected_tokens(&mut self) {
|
||||||
self.expected_tokens.clear();
|
self.expected_tokens.clear();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user