diff options
author | Aleksey Kladov <[email protected]> | 2018-08-08 19:14:18 +0100 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2018-08-08 19:14:18 +0100 |
commit | a5dc5f1b5cc7932477225128b2c6c9e8dff9cd73 (patch) | |
tree | 5fde33bb0e3887a015e08315ca562d6757a7e8c1 /src | |
parent | 1fa5b2ffbc0f1dd3cfc45adff0329e1bdd46c131 (diff) |
Improve tree building
Diffstat (limited to 'src')
-rw-r--r-- | src/yellow/builder.rs | 39 | ||||
-rw-r--r-- | src/yellow/green.rs | 35 | ||||
-rw-r--r-- | src/yellow/mod.rs | 2 |
3 files changed, 30 insertions, 46 deletions
diff --git a/src/yellow/builder.rs b/src/yellow/builder.rs index dbe646cd7..70869952c 100644 --- a/src/yellow/builder.rs +++ b/src/yellow/builder.rs | |||
@@ -1,14 +1,14 @@ | |||
1 | use { | 1 | use { |
2 | parser_impl::Sink, | 2 | parser_impl::Sink, |
3 | yellow::{GreenNode, GreenNodeBuilder, SyntaxError, SyntaxNode, SyntaxRoot}, | 3 | yellow::{GreenNode, SyntaxError, SyntaxNode, SyntaxRoot}, |
4 | SyntaxKind, TextRange, TextUnit, | 4 | SyntaxKind, TextRange, TextUnit, |
5 | }; | 5 | }; |
6 | 6 | ||
7 | pub(crate) struct GreenBuilder<'a> { | 7 | pub(crate) struct GreenBuilder<'a> { |
8 | text: &'a str, | 8 | text: &'a str, |
9 | stack: Vec<GreenNodeBuilder>, | 9 | parents: Vec<(SyntaxKind, usize)>, |
10 | children: Vec<GreenNode>, | ||
10 | pos: TextUnit, | 11 | pos: TextUnit, |
11 | root: Option<GreenNode>, | ||
12 | errors: Vec<SyntaxError>, | 12 | errors: Vec<SyntaxError>, |
13 | } | 13 | } |
14 | 14 | ||
@@ -18,9 +18,9 @@ impl<'a> Sink<'a> for GreenBuilder<'a> { | |||
18 | fn new(text: &'a str) -> Self { | 18 | fn new(text: &'a str) -> Self { |
19 | GreenBuilder { | 19 | GreenBuilder { |
20 | text, | 20 | text, |
21 | stack: Vec::new(), | 21 | parents: Vec::new(), |
22 | children: Vec::new(), | ||
22 | pos: 0.into(), | 23 | pos: 0.into(), |
23 | root: None, | ||
24 | errors: Vec::new(), | 24 | errors: Vec::new(), |
25 | } | 25 | } |
26 | } | 26 | } |
@@ -29,23 +29,24 @@ impl<'a> Sink<'a> for GreenBuilder<'a> { | |||
29 | let range = TextRange::offset_len(self.pos, len); | 29 | let range = TextRange::offset_len(self.pos, len); |
30 | self.pos += len; | 30 | self.pos += len; |
31 | let text = &self.text[range]; | 31 | let text = &self.text[range]; |
32 | let leaf = GreenNodeBuilder::new_leaf(kind, text); | 32 | self.children.push( |
33 | let parent = self.stack.last_mut().unwrap(); | 33 | GreenNode::new_leaf(kind, text) |
34 | parent.push_child(leaf) | 34 | ); |
35 | } | 35 | } |
36 | 36 | ||
37 | fn start_internal(&mut self, kind: SyntaxKind) { | 37 | fn start_internal(&mut self, kind: SyntaxKind) { |
38 | self.stack.push(GreenNodeBuilder::new_internal(kind)) | 38 | let len = self.children.len(); |
39 | self.parents.push((kind, len)); | ||
39 | } | 40 | } |
40 | 41 | ||
41 | fn finish_internal(&mut self) { | 42 | fn finish_internal(&mut self) { |
42 | let builder = self.stack.pop().unwrap(); | 43 | let (kind, first_child) = self.parents.pop().unwrap(); |
43 | let node = builder.build(); | 44 | let children = self.children |
44 | if let Some(parent) = self.stack.last_mut() { | 45 | .drain(first_child..) |
45 | parent.push_child(node); | 46 | .collect(); |
46 | } else { | 47 | self.children.push( |
47 | self.root = Some(node); | 48 | GreenNode::new_branch(kind, children) |
48 | } | 49 | ); |
49 | } | 50 | } |
50 | 51 | ||
51 | fn error(&mut self, message: String) { | 52 | fn error(&mut self, message: String) { |
@@ -55,8 +56,10 @@ impl<'a> Sink<'a> for GreenBuilder<'a> { | |||
55 | }) | 56 | }) |
56 | } | 57 | } |
57 | 58 | ||
58 | fn finish(self) -> SyntaxNode { | 59 | fn finish(mut self) -> SyntaxNode { |
59 | let root = SyntaxRoot::new(self.root.unwrap(), self.errors); | 60 | assert_eq!(self.children.len(), 1); |
61 | let root = self.children.pop().unwrap(); | ||
62 | let root = SyntaxRoot::new(root, self.errors); | ||
60 | SyntaxNode::new_owned(root) | 63 | SyntaxNode::new_owned(root) |
61 | } | 64 | } |
62 | } | 65 | } |
diff --git a/src/yellow/green.rs b/src/yellow/green.rs index 26df76af6..5b4ce313a 100644 --- a/src/yellow/green.rs +++ b/src/yellow/green.rs | |||
@@ -12,6 +12,14 @@ pub(crate) enum GreenNode { | |||
12 | } | 12 | } |
13 | 13 | ||
14 | impl GreenNode { | 14 | impl GreenNode { |
15 | pub(crate) fn new_leaf(kind: SyntaxKind, text: &str) -> GreenNode { | ||
16 | GreenNode::Leaf(GreenLeaf::new(kind, text)) | ||
17 | } | ||
18 | |||
19 | pub(crate) fn new_branch(kind: SyntaxKind, children: Vec<GreenNode>) -> GreenNode { | ||
20 | GreenNode::Branch(Arc::new(GreenBranch::new(kind, children))) | ||
21 | } | ||
22 | |||
15 | pub fn kind(&self) -> SyntaxKind { | 23 | pub fn kind(&self) -> SyntaxKind { |
16 | match self { | 24 | match self { |
17 | GreenNode::Leaf(l) => l.kind(), | 25 | GreenNode::Leaf(l) => l.kind(), |
@@ -46,33 +54,6 @@ impl GreenNode { | |||
46 | } | 54 | } |
47 | } | 55 | } |
48 | 56 | ||
49 | pub(crate) struct GreenNodeBuilder { | ||
50 | kind: SyntaxKind, | ||
51 | children: Vec<GreenNode>, | ||
52 | } | ||
53 | |||
54 | impl GreenNodeBuilder { | ||
55 | pub(crate) fn new_leaf(kind: SyntaxKind, text: &str) -> GreenNode { | ||
56 | GreenNode::Leaf(GreenLeaf::new(kind, text)) | ||
57 | } | ||
58 | |||
59 | pub(crate) fn new_internal(kind: SyntaxKind) -> GreenNodeBuilder { | ||
60 | GreenNodeBuilder { | ||
61 | kind, | ||
62 | children: Vec::new(), | ||
63 | } | ||
64 | } | ||
65 | |||
66 | pub(crate) fn push_child(&mut self, node: GreenNode) { | ||
67 | self.children.push(node) | ||
68 | } | ||
69 | |||
70 | pub(crate) fn build(self) -> GreenNode { | ||
71 | let branch = GreenBranch::new(self.kind, self.children); | ||
72 | GreenNode::Branch(Arc::new(branch)) | ||
73 | } | ||
74 | } | ||
75 | |||
76 | #[test] | 57 | #[test] |
77 | fn assert_send_sync() { | 58 | fn assert_send_sync() { |
78 | fn f<T: Send + Sync>() {} | 59 | fn f<T: Send + Sync>() {} |
diff --git a/src/yellow/mod.rs b/src/yellow/mod.rs index f20be356d..1b5d4e4df 100644 --- a/src/yellow/mod.rs +++ b/src/yellow/mod.rs | |||
@@ -6,7 +6,7 @@ mod syntax; | |||
6 | pub use self::syntax::{SyntaxNode, SyntaxNodeRef, SyntaxRoot, TreeRoot}; | 6 | pub use self::syntax::{SyntaxNode, SyntaxNodeRef, SyntaxRoot, TreeRoot}; |
7 | pub(crate) use self::{ | 7 | pub(crate) use self::{ |
8 | builder::GreenBuilder, | 8 | builder::GreenBuilder, |
9 | green::{GreenNode, GreenNodeBuilder}, | 9 | green::GreenNode, |
10 | red::RedNode, | 10 | red::RedNode, |
11 | syntax::SyntaxError, | 11 | syntax::SyntaxError, |
12 | }; | 12 | }; |