diff --git a/src/lib.rs b/src/lib.rs index 13872a3d9a..d95e266624 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -7,6 +7,6 @@ mod parser; pub mod syntax_kinds; pub use text::{TextUnit, TextRange}; -pub use tree::{SyntaxKind, Token, FileBuilder, File, Node}; +pub use tree::{SyntaxKind, Token, FileBuilder, Sink, File, Node}; pub use lexer::{next_token, tokenize}; pub use parser::parse; diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 7336c51363..0a136266cc 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -1,4 +1,4 @@ -use {Token, File, FileBuilder}; +use {Token, File, FileBuilder, Sink}; use syntax_kinds::*; diff --git a/src/tree/file_builder.rs b/src/tree/file_builder.rs index 430303ce93..eba850fef0 100644 --- a/src/tree/file_builder.rs +++ b/src/tree/file_builder.rs @@ -1,6 +1,13 @@ use {SyntaxKind, TextUnit, TextRange}; use super::{NodeData, NodeIdx, File}; +pub trait Sink { + fn leaf(&mut self, kind: SyntaxKind, len: TextUnit); + fn start_internal(&mut self, kind: SyntaxKind); + fn finish_internal(&mut self); +} + + pub struct FileBuilder { text: String, nodes: Vec, @@ -8,6 +15,44 @@ pub struct FileBuilder { pos: TextUnit, } +impl Sink for FileBuilder { + fn leaf(&mut self, kind: SyntaxKind, len: TextUnit) { + let leaf = NodeData { + kind, + range: TextRange::from_len(self.pos, len), + parent: None, + first_child: None, + next_sibling: None, + }; + self.pos += len; + let id = self.push_child(leaf); + self.add_len(id); + } + + fn start_internal(&mut self, kind: SyntaxKind) { + let node = NodeData { + kind, + range: TextRange::from_len(self.pos, 0.into()), + parent: None, + first_child: None, + next_sibling: None, + }; + let id = if self.in_progress.is_empty() { + self.new_node(node) + } else { + self.push_child(node) + }; + self.in_progress.push((id, None)) + } + + fn finish_internal(&mut self) { + let (id, _) = self.in_progress.pop().unwrap(); + if !self.in_progress.is_empty() { + self.add_len(id); + } + } +} + impl FileBuilder { pub fn new(text: String) -> FileBuilder { FileBuilder { @@ -27,42 +72,6 @@ impl FileBuilder { } } - pub fn leaf(&mut self, kind: SyntaxKind, len: TextUnit) { - let leaf = NodeData { - kind, - range: TextRange::from_len(self.pos, len), - parent: None, - first_child: None, - next_sibling: None, - }; - self.pos += len; - let id = self.push_child(leaf); - self.add_len(id); - } - - pub fn start_internal(&mut self, kind: SyntaxKind) { - let node = NodeData { - kind, - range: TextRange::from_len(self.pos, 0.into()), - parent: None, - first_child: None, - next_sibling: None, - }; - let id = if self.in_progress.is_empty() { - self.new_node(node) - } else { - self.push_child(node) - }; - self.in_progress.push((id, None)) - } - - pub fn finish_internal(&mut self) { - let (id, _) = self.in_progress.pop().unwrap(); - if !self.in_progress.is_empty() { - self.add_len(id); - } - } - fn new_node(&mut self, data: NodeData) -> NodeIdx { let id = NodeIdx(self.nodes.len() as u32); self.nodes.push(data); diff --git a/src/tree/mod.rs b/src/tree/mod.rs index 6bacb46eff..7a5d429a37 100644 --- a/src/tree/mod.rs +++ b/src/tree/mod.rs @@ -4,7 +4,7 @@ use syntax_kinds::syntax_info; use std::fmt; mod file_builder; -pub use self::file_builder::FileBuilder; +pub use self::file_builder::{FileBuilder, Sink}; #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct SyntaxKind(pub(crate) u32);