diff options
| author | Jubilee Young <workingjubilee@gmail.com> | 2024-05-05 15:41:00 -0700 |
|---|---|---|
| committer | Jubilee Young <workingjubilee@gmail.com> | 2024-05-07 19:10:29 -0700 |
| commit | 5e67a3783c89ebb1f611e0351c9a36a579e49cec (patch) | |
| tree | 0d34f2a75fda1e7e59e40e54e1dc9b84e12bf425 /compiler/rustc_parse/src | |
| parent | c70290da0a27a4873823c0381ac698c6e7ed8b65 (diff) | |
| download | rust-5e67a3783c89ebb1f611e0351c9a36a579e49cec.tar.gz rust-5e67a3783c89ebb1f611e0351c9a36a579e49cec.zip | |
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.
Diffstat (limited to 'compiler/rustc_parse/src')
| -rw-r--r-- | compiler/rustc_parse/src/lib.rs | 1 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/mod.rs | 41 |
2 files changed, 42 insertions, 0 deletions
diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs index a46372d368f..0f973dfcd79 100644 --- a/compiler/rustc_parse/src/lib.rs +++ b/compiler/rustc_parse/src/lib.rs @@ -5,6 +5,7 @@ #![allow(rustc::untranslatable_diagnostic)] #![feature(array_windows)] #![feature(box_patterns)] +#![feature(debug_closure_helpers)] #![feature(if_let_guard)] #![feature(iter_intersperse)] #![feature(let_chains)] diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 2f688c60765..381250bd7d7 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -1537,6 +1537,47 @@ impl<'a> Parser<'a> { }) } + // 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) { self.expected_tokens.clear(); } |
