Awesome
pegviz
Visualizer for https://crates.io/crates/peg parsers.
Screenshot
pegviz
reads peg's tracing markers and generates a collapsible HTML tree.
Left side:
- Green: matched rule
- Red: failed rule
Right side:
- Gray: previous input, for context
- Blue background: input matched by this rule
- White text: rest of input after matching
Format
pegviz
expects input in the following format:
[PEG_INPUT_START]
int a = 12 + 45;
[PEG_TRACE_START]
[PEG_TRACE] Attempting to match rule `translation_unit0` at 1:1
[PEG_TRACE] Attempting to match rule `list0` at 1:1
[PEG_TRACE] Attempting to match rule `node` at 1:1
[PEG_TRACE] Attempting to match rule `external_declaration` at 1:1
[PEG_TRACE] Attempting to match rule `declaration` at 1:1
[PEG_TRACE] Attempting to match rule `node` at 1:1
[PEG_TRACE] Attempting to match rule `declaration0` at 1:1
[PEG_TRACE] Attempting to match rule `gnu` at 1:1
[PEG_TRACE] Attempting to match rule `gnu_guard` at 1:1
[PEG_TRACE] Failed to match rule `gnu_guard` at 1:1
[PEG_TRACE] Failed to match rule `gnu` at 1:1
[PEG_TRACE] Attempting to match rule `_` at 1:1
[PEG_TRACE] Matched rule `_` at 1:1 to 1:1
The _START
and _STOP
marker are pegviz-specific, you'll need to add
them to your program. See the Integration section for more information.
Multiple traces may be processed, they'll all show up in the output file. Output that occurs between traces is ignored.
Compatibility
pegviz has been used with:
- peg 0.5.7
- peg 0.6.2
There are no tests. It's quickly thrown together.
Integration
In your crate, re-export the trace
feature:
# in Cargo.toml
[features]
trace = ["peg/trace"]
Then, in your parser, add a tracing
rule that captures all the input
and outputs the markers pegviz
is looking for:
peg::parser! { pub grammar example() for str {
rule traced<T>(e: rule<T>) -> T =
&(input:$([_]*) {
#[cfg(feature = "trace")]
println!("[PEG_INPUT_START]\n{}\n[PEG_TRACE_START]", input);
})
e:e()? {?
#[cfg(feature = "trace")]
println!("[PEG_TRACE_STOP]");
e.ok_or("")
}
pub rule toplevel() -> Toplevel = traced(<toplevel0()>)
}}
The above is the recommended way if you're maintaining the grammar and want to be able to turn on pegviz support anytime.
If you're debugging someone else's parser, you may want to print the start/stop markers and the source yourself, around the parser invocation, like so:
let source = std::fs::read_to_string(&source).unwrap();
println!("[PEG_INPUT_START]\n{}\n[PEG_TRACE_START]", source);
let res = lang_c::driver::parse_preprocessed(&config, source);
println!("[PEG_TRACE_STOP]");
Make sure you've installed pegviz
into your $PATH
:
cd pegviz/
cargo install --force --path .
While installing it, you may notice
pegviz
depends onpeg
. That's right! It's using a PEG to analyze PEG traces.
Then, simply run your program with the trace
Cargo feature enabled, and
pipe its standard output to pegviz
.
cd example/
cargo run --features trace | pegviz --output ./pegviz.html
Note that the --output
argument is mandatory.
The last step is to open the resulting HTML file in a browser and click around!
License
pegviz is released under the MIT License. See the LICENSE file for details.