From f078f7adc8ac0ffae07462d736083807c98c0483 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 23 Feb 2019 16:55:01 +0300 Subject: introduce tree builder --- crates/ra_syntax/src/lib.rs | 2 +- crates/ra_syntax/src/parsing/text_tree_sink.rs | 28 ++++++-------- crates/ra_syntax/src/syntax_node.rs | 51 ++++++++++++++++++++++++-- 3 files changed, 61 insertions(+), 20 deletions(-) (limited to 'crates') diff --git a/crates/ra_syntax/src/lib.rs b/crates/ra_syntax/src/lib.rs index e7d402446..7334d53ef 100644 --- a/crates/ra_syntax/src/lib.rs +++ b/crates/ra_syntax/src/lib.rs @@ -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}, }; diff --git a/crates/ra_syntax/src/parsing/text_tree_sink.rs b/crates/ra_syntax/src/parsing/text_tree_sink.rs index 8c1d78deb..961a91d41 100644 --- a/crates/ra_syntax/src/parsing/text_tree_sink.rs +++ b/crates/ra_syntax/src/parsing/text_tree_sink.rs @@ -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, - inner: GreenNodeBuilder, + 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) { diff --git a/crates/ra_syntax/src/syntax_node.rs b/crates/ra_syntax/src/syntax_node.rs index 4d54ae614..e5b4cdb11 100644 --- a/crates/ra_syntax/src/syntax_node.rs +++ b/crates/ra_syntax/src/syntax_node.rs @@ -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, + inner: GreenNodeBuilder, +} + +impl Default for SyntaxTreeBuilder { + fn default() -> SyntaxTreeBuilder { + SyntaxTreeBuilder { errors: Vec::new(), inner: GreenNodeBuilder::new() } + } +} + +impl SyntaxTreeBuilder { + pub(crate) fn finish_raw(self) -> (GreenNode, Vec) { + let green = self.inner.finish(); + (green, self.errors) + } + + pub fn finish(self) -> TreeArc { + 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) + } +} -- cgit v1.2.3