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/tree | |
parent | 8d9961b75377a7bd2656b5aa1451710de8c86f60 (diff) |
Introduce red-green syntax tree
Diffstat (limited to 'src/tree')
-rw-r--r-- | src/tree/file_builder.rs | 72 | ||||
-rw-r--r-- | src/tree/mod.rs | 2 |
2 files changed, 72 insertions, 2 deletions
diff --git a/src/tree/file_builder.rs b/src/tree/file_builder.rs index 712602168..4983006cd 100644 --- a/src/tree/file_builder.rs +++ b/src/tree/file_builder.rs | |||
@@ -7,8 +7,13 @@ | |||
7 | //! tree builder: the parser produces a stream of events like | 7 | //! tree builder: the parser produces a stream of events like |
8 | //! `start node`, `finish node`, and `FileBuilder` converts | 8 | //! `start node`, `finish node`, and `FileBuilder` converts |
9 | //! this stream to a real tree. | 9 | //! this stream to a real tree. |
10 | use {SyntaxKind, TextRange, TextUnit}; | 10 | use std::sync::Arc; |
11 | use { | ||
12 | SyntaxKind, TextRange, TextUnit, | ||
13 | yellow::GreenNode | ||
14 | }; | ||
11 | use super::{File, NodeData, NodeIdx, SyntaxErrorData}; | 15 | use super::{File, NodeData, NodeIdx, SyntaxErrorData}; |
16 | use SError; | ||
12 | 17 | ||
13 | pub(crate) trait Sink { | 18 | pub(crate) trait Sink { |
14 | fn leaf(&mut self, kind: SyntaxKind, len: TextUnit); | 19 | fn leaf(&mut self, kind: SyntaxKind, len: TextUnit); |
@@ -159,3 +164,68 @@ fn grow(left: &mut TextRange, right: TextRange) { | |||
159 | pub(crate) struct ErrorMsg { | 164 | pub(crate) struct ErrorMsg { |
160 | pub(crate) msg: String, | 165 | pub(crate) msg: String, |
161 | } | 166 | } |
167 | |||
168 | pub(crate) struct GreenBuilder { | ||
169 | text: String, | ||
170 | stack: Vec<GreenNode>, | ||
171 | pos: TextUnit, | ||
172 | root: Option<GreenNode>, | ||
173 | errors: Vec<SError>, | ||
174 | } | ||
175 | |||
176 | impl GreenBuilder { | ||
177 | pub(crate) fn new(text: String) -> GreenBuilder { | ||
178 | GreenBuilder { | ||
179 | text, | ||
180 | stack: Vec::new(), | ||
181 | pos: 0.into(), | ||
182 | root: None, | ||
183 | errors: Vec::new(), | ||
184 | } | ||
185 | } | ||
186 | |||
187 | pub(crate) fn finish(self) -> (GreenNode, Vec<SError>) { | ||
188 | (self.root.unwrap(), self.errors) | ||
189 | } | ||
190 | } | ||
191 | |||
192 | impl Sink for GreenBuilder { | ||
193 | fn leaf(&mut self, kind: SyntaxKind, len: TextUnit) { | ||
194 | let range = TextRange::offset_len(self.pos, len); | ||
195 | self.pos += len; | ||
196 | let text = self.text[range].to_owned(); | ||
197 | let parent = self.stack.last_mut().unwrap(); | ||
198 | if kind.is_trivia() { | ||
199 | parent.push_trivia(kind, text); | ||
200 | } else { | ||
201 | let node = GreenNode::new_leaf(kind, text); | ||
202 | parent.push_child(Arc::new(node)); | ||
203 | } | ||
204 | } | ||
205 | |||
206 | fn start_internal(&mut self, kind: SyntaxKind) { | ||
207 | self.stack.push(GreenNode::new_branch(kind)) | ||
208 | } | ||
209 | |||
210 | fn finish_internal(&mut self) { | ||
211 | let node = self.stack.pop().unwrap(); | ||
212 | if let Some(parent) = self.stack.last_mut() { | ||
213 | parent.push_child(Arc::new(node)) | ||
214 | } else { | ||
215 | self.root = Some(node); | ||
216 | } | ||
217 | } | ||
218 | |||
219 | fn error(&mut self, err: ErrorMsg) { | ||
220 | self.errors.push(SError { message: err.msg, offset: self.pos }) | ||
221 | } | ||
222 | } | ||
223 | impl SyntaxKind { | ||
224 | fn is_trivia(self) -> bool { | ||
225 | match self { | ||
226 | SyntaxKind::WHITESPACE | SyntaxKind::DOC_COMMENT | SyntaxKind::COMMENT => true, | ||
227 | _ => false | ||
228 | } | ||
229 | } | ||
230 | } | ||
231 | |||
diff --git a/src/tree/mod.rs b/src/tree/mod.rs index f7b16d7b5..7abe17592 100644 --- a/src/tree/mod.rs +++ b/src/tree/mod.rs | |||
@@ -2,7 +2,7 @@ mod file_builder; | |||
2 | 2 | ||
3 | use ::{TextRange, TextUnit}; | 3 | use ::{TextRange, TextUnit}; |
4 | use std::{fmt, cmp}; | 4 | use std::{fmt, cmp}; |
5 | pub(crate) use self::file_builder::{ErrorMsg, FileBuilder, Sink}; | 5 | pub(crate) use self::file_builder::{ErrorMsg, FileBuilder, Sink, GreenBuilder}; |
6 | 6 | ||
7 | pub use syntax_kinds::SyntaxKind; | 7 | pub use syntax_kinds::SyntaxKind; |
8 | 8 | ||