diff options
author | Aleksey Kladov <[email protected]> | 2018-07-29 11:51:55 +0100 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2018-07-29 11:51:55 +0100 |
commit | c12450fb4e30c3418555e47d045bb9fd4318a10a (patch) | |
tree | e2dc508e1e415388392657cda3dfb00175cdabf2 /src/yellow/green.rs | |
parent | 8d9961b75377a7bd2656b5aa1451710de8c86f60 (diff) |
Introduce red-green syntax tree
Diffstat (limited to 'src/yellow/green.rs')
-rw-r--r-- | src/yellow/green.rs | 194 |
1 files changed, 194 insertions, 0 deletions
diff --git a/src/yellow/green.rs b/src/yellow/green.rs new file mode 100644 index 000000000..ede23b719 --- /dev/null +++ b/src/yellow/green.rs | |||
@@ -0,0 +1,194 @@ | |||
1 | use std::sync::Arc; | ||
2 | use text_unit::TextUnit; | ||
3 | use SyntaxKind; | ||
4 | |||
5 | type TokenText = String; | ||
6 | |||
7 | #[derive(Debug)] | ||
8 | pub(crate) struct GreenNode { | ||
9 | kind: SyntaxKind, | ||
10 | data: GreenNodeData, | ||
11 | } | ||
12 | |||
13 | impl GreenNode { | ||
14 | pub(crate) fn new_leaf(kind: SyntaxKind, text: TokenText) -> GreenNode { | ||
15 | GreenNode { | ||
16 | kind, | ||
17 | data: GreenNodeData::Leaf(GreenLeaf { text }), | ||
18 | } | ||
19 | } | ||
20 | |||
21 | pub(crate) fn new_branch( | ||
22 | kind: SyntaxKind, | ||
23 | ) -> GreenNode { | ||
24 | let branch = GreenBranch { | ||
25 | text_len: 0.into(), | ||
26 | leading_trivia: Trivias::default(), | ||
27 | children: Vec::new(), | ||
28 | }; | ||
29 | GreenNode { | ||
30 | kind, | ||
31 | data: GreenNodeData::Branch(branch), | ||
32 | } | ||
33 | } | ||
34 | |||
35 | pub(crate) fn push_trivia(&mut self, kind: SyntaxKind, text: TokenText) { | ||
36 | let branch = match &mut self.data { | ||
37 | GreenNodeData::Branch(branch) => branch, | ||
38 | _ => panic!() | ||
39 | }; | ||
40 | branch.text_len += TextUnit::of_str(&text); | ||
41 | let leading = &mut branch.leading_trivia; | ||
42 | branch.children.last_mut().map(|(_, t)| t).unwrap_or(leading) | ||
43 | .push(Arc::new(GreenTrivia { kind, text })); | ||
44 | } | ||
45 | |||
46 | pub(crate) fn push_child(&mut self, node: Arc<GreenNode>) { | ||
47 | let branch = match &mut self.data { | ||
48 | GreenNodeData::Branch(branch) => branch, | ||
49 | _ => panic!() | ||
50 | }; | ||
51 | branch.text_len += node.text_len(); | ||
52 | branch.children.push((node, Trivias::default())); | ||
53 | } | ||
54 | |||
55 | pub(crate) fn kind(&self) -> SyntaxKind { | ||
56 | self.kind | ||
57 | } | ||
58 | |||
59 | pub(crate) fn text_len(&self) -> TextUnit { | ||
60 | match &self.data { | ||
61 | GreenNodeData::Leaf(l) => l.text_len(), | ||
62 | GreenNodeData::Branch(b) => b.text_len(), | ||
63 | } | ||
64 | } | ||
65 | |||
66 | pub(crate) fn text(&self) -> String { | ||
67 | let mut buff = String::new(); | ||
68 | go(self, &mut buff); | ||
69 | return buff; | ||
70 | fn go(node: &GreenNode, buff: &mut String) { | ||
71 | match &node.data { | ||
72 | GreenNodeData::Leaf(l) => buff.push_str(&l.text), | ||
73 | GreenNodeData::Branch(branch) => { | ||
74 | add_trivia(&branch.leading_trivia, buff); | ||
75 | branch.children.iter().for_each(|(child, trivias)| { | ||
76 | go(child, buff); | ||
77 | add_trivia(trivias, buff); | ||
78 | }) | ||
79 | } | ||
80 | } | ||
81 | } | ||
82 | |||
83 | fn add_trivia(trivias: &Trivias, buff: &mut String) { | ||
84 | trivias.iter().for_each(|t| buff.push_str(&t.text)) | ||
85 | } | ||
86 | } | ||
87 | |||
88 | pub(crate) fn n_children(&self) -> usize { | ||
89 | match &self.data { | ||
90 | GreenNodeData::Leaf(_) => 0, | ||
91 | GreenNodeData::Branch(branch) => branch.children.len(), | ||
92 | } | ||
93 | } | ||
94 | |||
95 | pub(crate) fn nth_child(&self, idx: usize) -> &Arc<GreenNode> { | ||
96 | match &self.data { | ||
97 | GreenNodeData::Leaf(_) => panic!("leaf nodes have no children"), | ||
98 | GreenNodeData::Branch(branch) => &branch.children[idx].0, | ||
99 | } | ||
100 | } | ||
101 | |||
102 | pub(crate) fn nth_trivias(&self, idx: usize) -> &Trivias { | ||
103 | match &self.data { | ||
104 | GreenNodeData::Leaf(_) => panic!("leaf nodes have no children"), | ||
105 | GreenNodeData::Branch(branch) => if idx == 0 { | ||
106 | &branch.leading_trivia | ||
107 | } else { | ||
108 | &branch.children[idx - 1].1 | ||
109 | }, | ||
110 | } | ||
111 | } | ||
112 | |||
113 | pub(crate) fn is_leaf(&self) -> bool { | ||
114 | match self.data { | ||
115 | GreenNodeData::Leaf(_) => true, | ||
116 | GreenNodeData::Branch(_) => false | ||
117 | } | ||
118 | } | ||
119 | |||
120 | pub(crate) fn leaf_text(&self) -> &str { | ||
121 | match &self.data { | ||
122 | GreenNodeData::Leaf(l) => l.text.as_str(), | ||
123 | GreenNodeData::Branch(_) => panic!("not a leaf") | ||
124 | } | ||
125 | } | ||
126 | } | ||
127 | |||
128 | #[derive(Debug)] | ||
129 | enum GreenNodeData { | ||
130 | Leaf(GreenLeaf), | ||
131 | Branch(GreenBranch), | ||
132 | } | ||
133 | |||
134 | #[derive(Debug)] | ||
135 | struct GreenLeaf { | ||
136 | text: TokenText | ||
137 | } | ||
138 | |||
139 | #[derive(Debug)] | ||
140 | struct GreenBranch { | ||
141 | text_len: TextUnit, | ||
142 | leading_trivia: Trivias, | ||
143 | children: Vec<(Arc<GreenNode>, Trivias)>, | ||
144 | } | ||
145 | |||
146 | #[derive(Debug)] | ||
147 | pub(crate) struct GreenTrivia { | ||
148 | pub(crate) kind: SyntaxKind, | ||
149 | pub(crate) text: TokenText, | ||
150 | } | ||
151 | |||
152 | type Trivias = Vec<Arc<GreenTrivia>>; | ||
153 | |||
154 | |||
155 | pub(crate) trait TextLen { | ||
156 | fn text_len(&self) -> TextUnit; | ||
157 | } | ||
158 | |||
159 | impl TextLen for GreenTrivia { | ||
160 | fn text_len(&self) -> TextUnit { | ||
161 | TextUnit::of_str(&self.text) | ||
162 | } | ||
163 | } | ||
164 | |||
165 | impl<T: TextLen> TextLen for Arc<T> { | ||
166 | fn text_len(&self) -> TextUnit { | ||
167 | let this: &T = self; | ||
168 | this.text_len() | ||
169 | } | ||
170 | } | ||
171 | |||
172 | impl TextLen for GreenNode { | ||
173 | fn text_len(&self) -> TextUnit { | ||
174 | self.text_len() | ||
175 | } | ||
176 | } | ||
177 | |||
178 | impl TextLen for GreenLeaf { | ||
179 | fn text_len(&self) -> TextUnit { | ||
180 | TextUnit::of_str(&self.text) | ||
181 | } | ||
182 | } | ||
183 | |||
184 | impl TextLen for GreenBranch { | ||
185 | fn text_len(&self) -> TextUnit { | ||
186 | self.text_len | ||
187 | } | ||
188 | } | ||
189 | |||
190 | impl<T: TextLen> TextLen for [T] { | ||
191 | fn text_len(&self) -> TextUnit { | ||
192 | self.iter().map(TextLen::text_len).sum() | ||
193 | } | ||
194 | } | ||