introduce tree builder

This commit is contained in:
Aleksey Kladov 2019-02-23 16:55:01 +03:00
parent 0c1cb98182
commit f078f7adc8
3 changed files with 61 additions and 20 deletions

View file

@ -36,7 +36,7 @@ pub use crate::{
ast::AstNode,
syntax_error::{SyntaxError, SyntaxErrorKind, Location},
syntax_text::SyntaxText,
syntax_node::{Direction, SyntaxNode, WalkEvent, TreeArc},
syntax_node::{Direction, SyntaxNode, WalkEvent, TreeArc, SyntaxTreeBuilder},
ptr::{SyntaxNodePtr, AstPtr},
parsing::{tokenize, Token},
};

View file

@ -1,13 +1,12 @@
use std::mem;
use ra_parser::{TreeSink, ParseError};
use rowan::GreenNodeBuilder;
use crate::{
SmolStr, SyntaxError, SyntaxErrorKind, TextUnit, TextRange,
SmolStr, SyntaxError, TextUnit, TextRange, SyntaxTreeBuilder,
SyntaxKind::{self, *},
parsing::Token,
syntax_node::{GreenNode, RaTypes},
syntax_node::GreenNode,
};
/// Bridges the parser with our specific syntax tree representation.
@ -19,8 +18,7 @@ pub(crate) struct TextTreeSink<'a> {
text_pos: TextUnit,
token_pos: usize,
state: State,
errors: Vec<SyntaxError>,
inner: GreenNodeBuilder<RaTypes>,
inner: SyntaxTreeBuilder,
}
enum State {
@ -33,7 +31,7 @@ impl<'a> TreeSink for TextTreeSink<'a> {
fn leaf(&mut self, kind: SyntaxKind, n_tokens: u8) {
match mem::replace(&mut self.state, State::Normal) {
State::PendingStart => unreachable!(),
State::PendingFinish => self.inner.finish_internal(),
State::PendingFinish => self.inner.finish_branch(),
State::Normal => (),
}
self.eat_trivias();
@ -48,12 +46,12 @@ impl<'a> TreeSink for TextTreeSink<'a> {
fn start_branch(&mut self, kind: SyntaxKind) {
match mem::replace(&mut self.state, State::Normal) {
State::PendingStart => {
self.inner.start_internal(kind);
self.inner.start_branch(kind);
// No need to attach trivias to previous node: there is no
// previous node.
return;
}
State::PendingFinish => self.inner.finish_internal(),
State::PendingFinish => self.inner.finish_branch(),
State::Normal => (),
}
@ -73,21 +71,20 @@ impl<'a> TreeSink for TextTreeSink<'a> {
n_attached_trivias(kind, leading_trivias)
};
self.eat_n_trivias(n_trivias - n_attached_trivias);
self.inner.start_internal(kind);
self.inner.start_branch(kind);
self.eat_n_trivias(n_attached_trivias);
}
fn finish_branch(&mut self) {
match mem::replace(&mut self.state, State::PendingFinish) {
State::PendingStart => unreachable!(),
State::PendingFinish => self.inner.finish_internal(),
State::PendingFinish => self.inner.finish_branch(),
State::Normal => (),
}
}
fn error(&mut self, error: ParseError) {
let error = SyntaxError::new(SyntaxErrorKind::ParseError(error), self.text_pos);
self.errors.push(error)
self.inner.error(error, self.text_pos)
}
}
@ -99,8 +96,7 @@ impl<'a> TextTreeSink<'a> {
text_pos: 0.into(),
token_pos: 0,
state: State::PendingStart,
errors: Vec::new(),
inner: GreenNodeBuilder::new(),
inner: SyntaxTreeBuilder::default(),
}
}
@ -108,12 +104,12 @@ impl<'a> TextTreeSink<'a> {
match mem::replace(&mut self.state, State::Normal) {
State::PendingFinish => {
self.eat_trivias();
self.inner.finish_internal()
self.inner.finish_branch()
}
State::PendingStart | State::Normal => unreachable!(),
}
(self.inner.finish(), self.errors)
self.inner.finish_raw()
}
fn eat_trivias(&mut self) {

View file

@ -11,11 +11,12 @@ use std::{
borrow::Borrow,
};
use rowan::{Types, TransparentNewType};
use ra_parser::ParseError;
use rowan::{Types, TransparentNewType, GreenNodeBuilder};
use crate::{
SmolStr, SyntaxKind, TextRange, SyntaxText, SourceFile, AstNode,
syntax_error::SyntaxError,
SmolStr, SyntaxKind, TextUnit, TextRange, SyntaxText, SourceFile, AstNode,
syntax_error::{SyntaxError, SyntaxErrorKind},
};
pub use rowan::WalkEvent;
@ -276,3 +277,47 @@ fn has_short_text(kind: SyntaxKind) -> bool {
_ => false,
}
}
pub struct SyntaxTreeBuilder {
errors: Vec<SyntaxError>,
inner: GreenNodeBuilder<RaTypes>,
}
impl Default for SyntaxTreeBuilder {
fn default() -> SyntaxTreeBuilder {
SyntaxTreeBuilder { errors: Vec::new(), inner: GreenNodeBuilder::new() }
}
}
impl SyntaxTreeBuilder {
pub(crate) fn finish_raw(self) -> (GreenNode, Vec<SyntaxError>) {
let green = self.inner.finish();
(green, self.errors)
}
pub fn finish(self) -> TreeArc<SyntaxNode> {
let (green, errors) = self.finish_raw();
let node = SyntaxNode::new(green, errors);
if cfg!(debug_assertions) {
crate::validation::validate_block_structure(&node);
}
node
}
pub fn leaf(&mut self, kind: SyntaxKind, text: SmolStr) {
self.inner.leaf(kind, text)
}
pub fn start_branch(&mut self, kind: SyntaxKind) {
self.inner.start_internal(kind)
}
pub fn finish_branch(&mut self) {
self.inner.finish_internal()
}
pub fn error(&mut self, error: ParseError, text_pos: TextUnit) {
let error = SyntaxError::new(SyntaxErrorKind::ParseError(error), text_pos);
self.errors.push(error)
}
}