rust/src/tree/file_builder.rs

232 lines
6.2 KiB
Rust
Raw Normal View History

2018-01-28 08:18:17 +00:00
//! This module provides a way to construct a `File`.
//! It is intended to be completely decoupled from the
//! parser, so as to allow to evolve the tree representation
//! and the parser algorithm independently.
//!
//! The `Sink` trait is the bridge between the parser and the
//! tree builder: the parser produces a stream of events like
//! `start node`, `finish node`, and `FileBuilder` converts
//! this stream to a real tree.
2018-07-29 10:51:55 +00:00
use std::sync::Arc;
use {
SyntaxKind, TextRange, TextUnit,
yellow::GreenNode
};
2018-01-27 23:31:23 +00:00
use super::{File, NodeData, NodeIdx, SyntaxErrorData};
2018-07-29 10:51:55 +00:00
use SError;
2017-12-31 17:30:21 +00:00
2018-01-28 08:18:17 +00:00
pub(crate) trait Sink {
2017-12-31 21:13:56 +00:00
fn leaf(&mut self, kind: SyntaxKind, len: TextUnit);
fn start_internal(&mut self, kind: SyntaxKind);
fn finish_internal(&mut self);
2018-02-09 19:44:50 +00:00
fn error(&mut self, err: ErrorMsg);
2017-12-31 21:13:56 +00:00
}
#[derive(Debug)]
2018-01-28 08:18:17 +00:00
pub(crate) struct FileBuilder {
2017-12-31 17:30:21 +00:00
text: String,
nodes: Vec<NodeData>,
2018-01-07 07:10:35 +00:00
errors: Vec<SyntaxErrorData>,
2018-02-09 19:44:50 +00:00
in_progress: Vec<(NodeIdx, Option<NodeIdx>)>,
// (parent, last_child)
2017-12-31 17:30:21 +00:00
pos: TextUnit,
}
2017-12-31 21:13:56 +00:00
impl Sink for FileBuilder {
fn leaf(&mut self, kind: SyntaxKind, len: TextUnit) {
2017-12-31 17:30:21 +00:00
let leaf = NodeData {
kind,
2018-07-28 10:07:10 +00:00
range: TextRange::offset_len(self.pos, len),
2017-12-31 17:30:21 +00:00
parent: None,
first_child: None,
next_sibling: None,
};
self.pos += len;
let id = self.push_child(leaf);
self.add_len(id);
}
2017-12-31 21:13:56 +00:00
fn start_internal(&mut self, kind: SyntaxKind) {
2017-12-31 17:30:21 +00:00
let node = NodeData {
kind,
2018-07-28 10:07:10 +00:00
range: TextRange::offset_len(self.pos, 0.into()),
2017-12-31 17:30:21 +00:00
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))
}
2017-12-31 21:13:56 +00:00
fn finish_internal(&mut self) {
2018-01-27 23:31:23 +00:00
let (id, _) = self.in_progress
.pop()
.expect("trying to complete a node, but there are no in-progress nodes");
2017-12-31 17:30:21 +00:00
if !self.in_progress.is_empty() {
self.add_len(id);
}
}
2018-01-07 07:55:43 +00:00
2018-02-09 19:44:50 +00:00
fn error(&mut self, err: ErrorMsg) {
let &(node, after_child) = self.in_progress.last().unwrap();
self.errors.push(SyntaxErrorData {
node,
message: err.msg,
2018-02-09 19:44:50 +00:00
after_child,
})
2018-01-07 07:55:43 +00:00
}
2017-12-31 21:13:56 +00:00
}
impl FileBuilder {
pub fn new(text: String) -> FileBuilder {
FileBuilder {
text,
nodes: Vec::new(),
2018-01-07 07:10:35 +00:00
errors: Vec::new(),
2017-12-31 21:13:56 +00:00
in_progress: Vec::new(),
2018-07-28 10:07:10 +00:00
pos: 0.into(),
2017-12-31 21:13:56 +00:00
}
}
pub fn finish(self) -> File {
2018-01-01 19:13:04 +00:00
assert!(
self.in_progress.is_empty(),
2018-01-07 11:56:08 +00:00
"some nodes in FileBuilder are unfinished: {:?}",
2018-01-27 23:31:23 +00:00
self.in_progress
.iter()
.map(|&(idx, _)| self.nodes[idx].kind)
2018-01-07 11:56:08 +00:00
.collect::<Vec<_>>()
2018-01-01 19:13:04 +00:00
);
2018-01-20 20:25:34 +00:00
assert_eq!(
2018-01-27 23:31:23 +00:00
self.pos,
(self.text.len() as u32).into(),
2018-01-01 19:13:04 +00:00
"nodes in FileBuilder do not cover the whole file"
);
2017-12-31 21:13:56 +00:00
File {
text: self.text,
nodes: self.nodes,
2018-01-07 07:10:35 +00:00
errors: self.errors,
2017-12-31 21:13:56 +00:00
}
}
2017-12-31 17:30:21 +00:00
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);
2018-01-01 19:13:04 +00:00
{
let (parent, sibling) = *self.in_progress.last().unwrap();
let slot = if let Some(idx) = sibling {
&mut self.nodes[idx].next_sibling
} else {
&mut self.nodes[parent].first_child
};
fill(slot, id);
2017-12-31 17:30:21 +00:00
}
2018-01-01 19:13:04 +00:00
self.in_progress.last_mut().unwrap().1 = Some(id);
2017-12-31 17:30:21 +00:00
id
}
fn add_len(&mut self, child: NodeIdx) {
let range = self.nodes[child].range;
2017-12-31 17:30:21 +00: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 17:30:21 +00: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())
2018-01-07 07:55:43 +00:00
}
2018-02-09 19:44:50 +00:00
#[derive(Default)]
pub(crate) struct ErrorMsg {
pub(crate) msg: String,
2018-01-07 07:55:43 +00:00
}
2018-07-29 10:51:55 +00:00
pub(crate) struct GreenBuilder {
text: String,
stack: Vec<GreenNode>,
pos: TextUnit,
root: Option<GreenNode>,
errors: Vec<SError>,
}
impl GreenBuilder {
pub(crate) fn new(text: String) -> GreenBuilder {
GreenBuilder {
text,
stack: Vec::new(),
pos: 0.into(),
root: None,
errors: Vec::new(),
}
}
pub(crate) fn finish(self) -> (GreenNode, Vec<SError>) {
(self.root.unwrap(), self.errors)
}
}
impl Sink for GreenBuilder {
fn leaf(&mut self, kind: SyntaxKind, len: TextUnit) {
let range = TextRange::offset_len(self.pos, len);
self.pos += len;
let text = self.text[range].to_owned();
let parent = self.stack.last_mut().unwrap();
if kind.is_trivia() {
parent.push_trivia(kind, text);
} else {
let node = GreenNode::new_leaf(kind, text);
parent.push_child(Arc::new(node));
}
}
fn start_internal(&mut self, kind: SyntaxKind) {
self.stack.push(GreenNode::new_branch(kind))
}
fn finish_internal(&mut self) {
let node = self.stack.pop().unwrap();
if let Some(parent) = self.stack.last_mut() {
parent.push_child(Arc::new(node))
} else {
self.root = Some(node);
}
}
fn error(&mut self, err: ErrorMsg) {
self.errors.push(SError { message: err.msg, offset: self.pos })
}
}
impl SyntaxKind {
fn is_trivia(self) -> bool {
match self {
SyntaxKind::WHITESPACE | SyntaxKind::DOC_COMMENT | SyntaxKind::COMMENT => true,
_ => false
}
}
}