Improve tree building

This commit is contained in:
Aleksey Kladov 2018-08-08 21:14:18 +03:00
parent 1fa5b2ffbc
commit a5dc5f1b5c
5 changed files with 34 additions and 46 deletions

View file

@ -16,3 +16,6 @@ parking_lot = "0.6.0"
[dev-dependencies] [dev-dependencies]
testutils = { path = "./tests/testutils" } testutils = { path = "./tests/testutils" }
[profile.release]
debug = true

View file

@ -47,6 +47,7 @@ fn main() -> Result<()> {
println!("{}", file.syntax_tree()); println!("{}", file.syntax_tree());
} }
eprintln!("parsing: {:?}", elapsed); eprintln!("parsing: {:?}", elapsed);
::std::mem::forget(file);
} }
("symbols", _) => { ("symbols", _) => {
let file = file()?; let file = file()?;

View file

@ -1,14 +1,14 @@
use { use {
parser_impl::Sink, parser_impl::Sink,
yellow::{GreenNode, GreenNodeBuilder, SyntaxError, SyntaxNode, SyntaxRoot}, yellow::{GreenNode, SyntaxError, SyntaxNode, SyntaxRoot},
SyntaxKind, TextRange, TextUnit, SyntaxKind, TextRange, TextUnit,
}; };
pub(crate) struct GreenBuilder<'a> { pub(crate) struct GreenBuilder<'a> {
text: &'a str, text: &'a str,
stack: Vec<GreenNodeBuilder>, parents: Vec<(SyntaxKind, usize)>,
children: Vec<GreenNode>,
pos: TextUnit, pos: TextUnit,
root: Option<GreenNode>,
errors: Vec<SyntaxError>, errors: Vec<SyntaxError>,
} }
@ -18,9 +18,9 @@ impl<'a> Sink<'a> for GreenBuilder<'a> {
fn new(text: &'a str) -> Self { fn new(text: &'a str) -> Self {
GreenBuilder { GreenBuilder {
text, text,
stack: Vec::new(), parents: Vec::new(),
children: Vec::new(),
pos: 0.into(), pos: 0.into(),
root: None,
errors: Vec::new(), errors: Vec::new(),
} }
} }
@ -29,23 +29,24 @@ impl<'a> Sink<'a> for GreenBuilder<'a> {
let range = TextRange::offset_len(self.pos, len); let range = TextRange::offset_len(self.pos, len);
self.pos += len; self.pos += len;
let text = &self.text[range]; let text = &self.text[range];
let leaf = GreenNodeBuilder::new_leaf(kind, text); self.children.push(
let parent = self.stack.last_mut().unwrap(); GreenNode::new_leaf(kind, text)
parent.push_child(leaf) );
} }
fn start_internal(&mut self, kind: SyntaxKind) { fn start_internal(&mut self, kind: SyntaxKind) {
self.stack.push(GreenNodeBuilder::new_internal(kind)) let len = self.children.len();
self.parents.push((kind, len));
} }
fn finish_internal(&mut self) { fn finish_internal(&mut self) {
let builder = self.stack.pop().unwrap(); let (kind, first_child) = self.parents.pop().unwrap();
let node = builder.build(); let children = self.children
if let Some(parent) = self.stack.last_mut() { .drain(first_child..)
parent.push_child(node); .collect();
} else { self.children.push(
self.root = Some(node); GreenNode::new_branch(kind, children)
} );
} }
fn error(&mut self, message: String) { fn error(&mut self, message: String) {
@ -55,8 +56,10 @@ impl<'a> Sink<'a> for GreenBuilder<'a> {
}) })
} }
fn finish(self) -> SyntaxNode { fn finish(mut self) -> SyntaxNode {
let root = SyntaxRoot::new(self.root.unwrap(), self.errors); assert_eq!(self.children.len(), 1);
let root = self.children.pop().unwrap();
let root = SyntaxRoot::new(root, self.errors);
SyntaxNode::new_owned(root) SyntaxNode::new_owned(root)
} }
} }

View file

@ -12,6 +12,14 @@ pub(crate) enum GreenNode {
} }
impl GreenNode { impl GreenNode {
pub(crate) fn new_leaf(kind: SyntaxKind, text: &str) -> GreenNode {
GreenNode::Leaf(GreenLeaf::new(kind, text))
}
pub(crate) fn new_branch(kind: SyntaxKind, children: Vec<GreenNode>) -> GreenNode {
GreenNode::Branch(Arc::new(GreenBranch::new(kind, children)))
}
pub fn kind(&self) -> SyntaxKind { pub fn kind(&self) -> SyntaxKind {
match self { match self {
GreenNode::Leaf(l) => l.kind(), GreenNode::Leaf(l) => l.kind(),
@ -46,33 +54,6 @@ impl GreenNode {
} }
} }
pub(crate) struct GreenNodeBuilder {
kind: SyntaxKind,
children: Vec<GreenNode>,
}
impl GreenNodeBuilder {
pub(crate) fn new_leaf(kind: SyntaxKind, text: &str) -> GreenNode {
GreenNode::Leaf(GreenLeaf::new(kind, text))
}
pub(crate) fn new_internal(kind: SyntaxKind) -> GreenNodeBuilder {
GreenNodeBuilder {
kind,
children: Vec::new(),
}
}
pub(crate) fn push_child(&mut self, node: GreenNode) {
self.children.push(node)
}
pub(crate) fn build(self) -> GreenNode {
let branch = GreenBranch::new(self.kind, self.children);
GreenNode::Branch(Arc::new(branch))
}
}
#[test] #[test]
fn assert_send_sync() { fn assert_send_sync() {
fn f<T: Send + Sync>() {} fn f<T: Send + Sync>() {}

View file

@ -6,7 +6,7 @@ mod syntax;
pub use self::syntax::{SyntaxNode, SyntaxNodeRef, SyntaxRoot, TreeRoot}; pub use self::syntax::{SyntaxNode, SyntaxNodeRef, SyntaxRoot, TreeRoot};
pub(crate) use self::{ pub(crate) use self::{
builder::GreenBuilder, builder::GreenBuilder,
green::{GreenNode, GreenNodeBuilder}, green::GreenNode,
red::RedNode, red::RedNode,
syntax::SyntaxError, syntax::SyntaxError,
}; };