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, ast::AstNode,
syntax_error::{SyntaxError, SyntaxErrorKind, Location}, syntax_error::{SyntaxError, SyntaxErrorKind, Location},
syntax_text::SyntaxText, syntax_text::SyntaxText,
syntax_node::{Direction, SyntaxNode, WalkEvent, TreeArc}, syntax_node::{Direction, SyntaxNode, WalkEvent, TreeArc, SyntaxTreeBuilder},
ptr::{SyntaxNodePtr, AstPtr}, ptr::{SyntaxNodePtr, AstPtr},
parsing::{tokenize, Token}, parsing::{tokenize, Token},
}; };

View File

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

View File

@@ -11,11 +11,12 @@ use std::{
borrow::Borrow, borrow::Borrow,
}; };
use rowan::{Types, TransparentNewType}; use ra_parser::ParseError;
use rowan::{Types, TransparentNewType, GreenNodeBuilder};
use crate::{ use crate::{
SmolStr, SyntaxKind, TextRange, SyntaxText, SourceFile, AstNode, SmolStr, SyntaxKind, TextUnit, TextRange, SyntaxText, SourceFile, AstNode,
syntax_error::SyntaxError, syntax_error::{SyntaxError, SyntaxErrorKind},
}; };
pub use rowan::WalkEvent; pub use rowan::WalkEvent;
@@ -276,3 +277,47 @@ fn has_short_text(kind: SyntaxKind) -> bool {
_ => false, _ => 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)
}
}