aboutsummaryrefslogtreecommitdiff
path: root/src/tree
diff options
context:
space:
mode:
Diffstat (limited to 'src/tree')
-rw-r--r--src/tree/file_builder.rs72
-rw-r--r--src/tree/mod.rs2
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.
10use {SyntaxKind, TextRange, TextUnit}; 10use std::sync::Arc;
11use {
12 SyntaxKind, TextRange, TextUnit,
13 yellow::GreenNode
14};
11use super::{File, NodeData, NodeIdx, SyntaxErrorData}; 15use super::{File, NodeData, NodeIdx, SyntaxErrorData};
16use SError;
12 17
13pub(crate) trait Sink { 18pub(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) {
159pub(crate) struct ErrorMsg { 164pub(crate) struct ErrorMsg {
160 pub(crate) msg: String, 165 pub(crate) msg: String,
161} 166}
167
168pub(crate) struct GreenBuilder {
169 text: String,
170 stack: Vec<GreenNode>,
171 pos: TextUnit,
172 root: Option<GreenNode>,
173 errors: Vec<SError>,
174}
175
176impl 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
192impl 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}
223impl 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
3use ::{TextRange, TextUnit}; 3use ::{TextRange, TextUnit};
4use std::{fmt, cmp}; 4use std::{fmt, cmp};
5pub(crate) use self::file_builder::{ErrorMsg, FileBuilder, Sink}; 5pub(crate) use self::file_builder::{ErrorMsg, FileBuilder, Sink, GreenBuilder};
6 6
7pub use syntax_kinds::SyntaxKind; 7pub use syntax_kinds::SyntaxKind;
8 8