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]
testutils = { path = "./tests/testutils" }
[profile.release]
debug = true

View file

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

View file

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

View file

@ -12,6 +12,14 @@ pub(crate) enum 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 {
match self {
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]
fn assert_send_sync() {
fn f<T: Send + Sync>() {}

View file

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