rust/src/tree/file_builder.rs

111 lines
2.9 KiB
Rust
Raw Normal View History

2017-12-31 18:30:21 +01:00
use {SyntaxKind, TextUnit, TextRange};
use super::{NodeData, NodeIdx, File};
pub struct FileBuilder {
text: String,
nodes: Vec<NodeData>,
in_progress: Vec<(NodeIdx, Option<NodeIdx>)>, // (parent, last_child)
pos: TextUnit,
}
impl FileBuilder {
pub fn new(text: String) -> FileBuilder {
FileBuilder {
text,
nodes: Vec::new(),
in_progress: Vec::new(),
pos: TextUnit::new(0),
}
}
pub fn finish(self) -> File {
assert!(self.in_progress.is_empty());
assert!(self.pos == (self.text.len() as u32).into());
File {
text: self.text,
nodes: self.nodes,
}
}
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);
id
}
fn push_child(&mut self, mut child: NodeData) -> NodeIdx {
child.parent = Some(self.current_id());
let id = self.new_node(child);
if let Some(sibling) = self.current_sibling() {
fill(&mut sibling.next_sibling, id);
return id
}
fill(&mut self.current_parent().first_child, id);
id
}
fn add_len(&mut self, child: NodeIdx) {
let range = self.nodes[child].range;
2017-12-31 18:30:21 +01:00
grow(&mut self.current_parent().range, range);
}
fn current_id(&self) -> NodeIdx {
self.in_progress.last().unwrap().0
}
fn current_parent(&mut self) -> &mut NodeData {
let idx = self.current_id();
&mut self.nodes[idx]
2017-12-31 18:30:21 +01:00
}
fn current_sibling(&mut self) -> Option<&mut NodeData> {
let idx = self.in_progress.last().unwrap().1?;
Some(&mut self.nodes[idx])
2017-12-31 18:30:21 +01:00
}
}
fn fill<T>(slot: &mut Option<T>, value: T) {
assert!(slot.is_none());
*slot = Some(value);
}
fn grow(left: &mut TextRange, right: TextRange) {
assert_eq!(left.end(), right.start());
*left = TextRange::from_to(left.start(), right.end())
}