Improve debug_dump performance
This commit is contained in:
parent
5d8cef4c0e
commit
8105c14454
@ -33,9 +33,7 @@ fn main() -> Result<()> {
|
||||
.get_matches();
|
||||
match matches.subcommand() {
|
||||
("parse", _) => {
|
||||
let start = Instant::now();
|
||||
let tree = parse()?;
|
||||
eprintln!("elapsed {:?}", start.elapsed());
|
||||
println!("{}", tree);
|
||||
}
|
||||
("render-test", Some(matches)) => {
|
||||
@ -53,7 +51,9 @@ fn main() -> Result<()> {
|
||||
|
||||
fn parse() -> Result<String> {
|
||||
let text = read_stdin()?;
|
||||
let start = Instant::now();
|
||||
let file = libsyntax2::parse(text);
|
||||
eprintln!("elapsed {:?}", start.elapsed());
|
||||
let tree = libsyntax2::utils::dump_tree(&file);
|
||||
Ok(tree)
|
||||
}
|
||||
|
@ -8,12 +8,12 @@ pub fn preorder<'a>(root: SyntaxNodeRef<'a>) -> impl Iterator<Item = SyntaxNodeR
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
enum WalkEvent<'a> {
|
||||
pub enum WalkEvent<'a> {
|
||||
Enter(SyntaxNodeRef<'a>),
|
||||
Exit(SyntaxNodeRef<'a>),
|
||||
}
|
||||
|
||||
fn walk<'a>(root: SyntaxNodeRef<'a>) -> impl Iterator<Item = WalkEvent<'a>> {
|
||||
pub fn walk<'a>(root: SyntaxNodeRef<'a>) -> impl Iterator<Item = WalkEvent<'a>> {
|
||||
let mut done = false;
|
||||
::itertools::unfold(WalkEvent::Enter(root), move |pos| {
|
||||
if done {
|
||||
|
@ -41,8 +41,6 @@ pub use {
|
||||
yellow::{SyntaxNode, SyntaxNodeRef, SyntaxRoot, TreeRoot},
|
||||
};
|
||||
|
||||
pub(crate) use yellow::SyntaxError;
|
||||
|
||||
pub fn parse(text: String) -> SyntaxNode {
|
||||
let tokens = tokenize(&text);
|
||||
parser::parse::<yellow::GreenBuilder>(text, &tokens)
|
||||
|
78
src/utils.rs
78
src/utils.rs
@ -1,46 +1,48 @@
|
||||
use std::{collections::BTreeSet, fmt::Write};
|
||||
use {SyntaxError, SyntaxNode, SyntaxNodeRef};
|
||||
use std::{fmt::Write};
|
||||
use {
|
||||
SyntaxNode,
|
||||
algo::walk::{WalkEvent, walk},
|
||||
};
|
||||
|
||||
/// Parse a file and create a string representation of the resulting parse tree.
|
||||
pub fn dump_tree(syntax: &SyntaxNode) -> String {
|
||||
let syntax = syntax.as_ref();
|
||||
let mut errors: BTreeSet<_> = syntax.root.errors.iter().cloned().collect();
|
||||
let mut result = String::new();
|
||||
go(syntax, &mut result, 0, &mut errors);
|
||||
return result;
|
||||
let mut errors: Vec<_> = syntax.root.errors.iter().cloned().collect();
|
||||
errors.sort_by_key(|e| e.offset);
|
||||
let mut err_pos = 0;
|
||||
let mut level = 0;
|
||||
let mut buf = String::new();
|
||||
macro_rules! indent {
|
||||
() => {
|
||||
for _ in 0..level {
|
||||
buf.push_str(" ");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
fn go(
|
||||
node: SyntaxNodeRef,
|
||||
buff: &mut String,
|
||||
level: usize,
|
||||
errors: &mut BTreeSet<SyntaxError>,
|
||||
) {
|
||||
buff.push_str(&String::from(" ").repeat(level));
|
||||
writeln!(buff, "{:?}", node).unwrap();
|
||||
let my_errors: Vec<_> = errors
|
||||
.iter()
|
||||
.filter(|e| e.offset == node.range().start())
|
||||
.cloned()
|
||||
.collect();
|
||||
for err in my_errors {
|
||||
errors.remove(&err);
|
||||
buff.push_str(&String::from(" ").repeat(level));
|
||||
writeln!(buff, "err: `{}`", err.message).unwrap();
|
||||
}
|
||||
|
||||
for child in node.children() {
|
||||
go(child, buff, level + 1, errors)
|
||||
}
|
||||
|
||||
let my_errors: Vec<_> = errors
|
||||
.iter()
|
||||
.filter(|e| e.offset == node.range().end())
|
||||
.cloned()
|
||||
.collect();
|
||||
for err in my_errors {
|
||||
errors.remove(&err);
|
||||
buff.push_str(&String::from(" ").repeat(level));
|
||||
writeln!(buff, "err: `{}`", err.message).unwrap();
|
||||
for event in walk(syntax) {
|
||||
match event {
|
||||
WalkEvent::Enter(node) => {
|
||||
indent!();
|
||||
writeln!(buf, "{:?}", node).unwrap();
|
||||
if node.first_child().is_none() {
|
||||
let off = node.range().end();
|
||||
while err_pos < errors.len() && errors[err_pos].offset <= off {
|
||||
indent!();
|
||||
writeln!(buf, "err: `{}`", errors[err_pos].message).unwrap();
|
||||
err_pos += 1;
|
||||
}
|
||||
}
|
||||
level += 1;
|
||||
},
|
||||
WalkEvent::Exit(_) => level -= 1,
|
||||
}
|
||||
}
|
||||
|
||||
assert_eq!(level, 0);
|
||||
for err in errors[err_pos..].iter() {
|
||||
writeln!(buf, "err: `{}`", err.message).unwrap();
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
FILE@[0; 21)
|
||||
err: `expected item`
|
||||
ERROR@[0; 3)
|
||||
IF_KW@[0; 2)
|
||||
err: `expected item`
|
||||
WHITESPACE@[2; 3)
|
||||
err: `expected item`
|
||||
ERROR@[3; 10)
|
||||
|
@ -9,8 +9,8 @@ FILE@[0; 12)
|
||||
WHITESPACE@[3; 4)
|
||||
IDENT@[4; 7) "foo"
|
||||
COLONCOLON@[7; 9)
|
||||
err: `expected SEMI`
|
||||
err: `expected identifier`
|
||||
err: `expected SEMI`
|
||||
err: `expected item`
|
||||
PATH_SEGMENT@[9; 9)
|
||||
ERROR@[9; 11)
|
||||
|
@ -1,7 +1,7 @@
|
||||
FILE@[0; 31)
|
||||
err: `expected item`
|
||||
ERROR@[0; 3)
|
||||
R_CURLY@[0; 1)
|
||||
err: `expected item`
|
||||
WHITESPACE@[1; 3)
|
||||
STRUCT_ITEM@[3; 14)
|
||||
STRUCT_KW@[3; 9)
|
||||
|
@ -13,8 +13,8 @@ FILE@[0; 18)
|
||||
L_PAREN@[10; 11)
|
||||
R_PAREN@[11; 12)
|
||||
WHITESPACE@[12; 13)
|
||||
err: `expected SEMI`
|
||||
err: `expected `;` or `]``
|
||||
err: `expected SEMI`
|
||||
err: `expected item`
|
||||
ERROR@[13; 15)
|
||||
INT_NUMBER@[13; 15)
|
||||
|
@ -8,8 +8,8 @@ FILE@[0; 20)
|
||||
EQ@[7; 8)
|
||||
WHITESPACE@[8; 9)
|
||||
UNSAFE_KW@[9; 15)
|
||||
err: `expected SEMI`
|
||||
err: `expected `fn``
|
||||
err: `expected SEMI`
|
||||
WHITESPACE@[15; 16)
|
||||
err: `expected item`
|
||||
ERROR@[16; 17)
|
||||
|
Loading…
x
Reference in New Issue
Block a user