aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2019-02-23 13:55:01 +0000
committerAleksey Kladov <[email protected]>2019-02-23 13:55:01 +0000
commitf078f7adc8ac0ffae07462d736083807c98c0483 (patch)
treee2f6611aaaf1459bb587f47dacaad9f07c4a8110
parent0c1cb981820c55127c3c09d93868814a1df98246 (diff)
introduce tree builder
-rw-r--r--crates/ra_syntax/src/lib.rs2
-rw-r--r--crates/ra_syntax/src/parsing/text_tree_sink.rs28
-rw-r--r--crates/ra_syntax/src/syntax_node.rs51
3 files changed, 61 insertions, 20 deletions
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::{
36 ast::AstNode, 36 ast::AstNode,
37 syntax_error::{SyntaxError, SyntaxErrorKind, Location}, 37 syntax_error::{SyntaxError, SyntaxErrorKind, Location},
38 syntax_text::SyntaxText, 38 syntax_text::SyntaxText,
39 syntax_node::{Direction, SyntaxNode, WalkEvent, TreeArc}, 39 syntax_node::{Direction, SyntaxNode, WalkEvent, TreeArc, SyntaxTreeBuilder},
40 ptr::{SyntaxNodePtr, AstPtr}, 40 ptr::{SyntaxNodePtr, AstPtr},
41 parsing::{tokenize, Token}, 41 parsing::{tokenize, Token},
42}; 42};
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 @@
1use std::mem; 1use std::mem;
2 2
3use ra_parser::{TreeSink, ParseError}; 3use ra_parser::{TreeSink, ParseError};
4use rowan::GreenNodeBuilder;
5 4
6use crate::{ 5use crate::{
7 SmolStr, SyntaxError, SyntaxErrorKind, TextUnit, TextRange, 6 SmolStr, SyntaxError, TextUnit, TextRange, SyntaxTreeBuilder,
8 SyntaxKind::{self, *}, 7 SyntaxKind::{self, *},
9 parsing::Token, 8 parsing::Token,
10 syntax_node::{GreenNode, RaTypes}, 9 syntax_node::GreenNode,
11}; 10};
12 11
13/// Bridges the parser with our specific syntax tree representation. 12/// Bridges the parser with our specific syntax tree representation.
@@ -19,8 +18,7 @@ pub(crate) struct TextTreeSink<'a> {
19 text_pos: TextUnit, 18 text_pos: TextUnit,
20 token_pos: usize, 19 token_pos: usize,
21 state: State, 20 state: State,
22 errors: Vec<SyntaxError>, 21 inner: SyntaxTreeBuilder,
23 inner: GreenNodeBuilder<RaTypes>,
24} 22}
25 23
26enum State { 24enum State {
@@ -33,7 +31,7 @@ impl<'a> TreeSink for TextTreeSink<'a> {
33 fn leaf(&mut self, kind: SyntaxKind, n_tokens: u8) { 31 fn leaf(&mut self, kind: SyntaxKind, n_tokens: u8) {
34 match mem::replace(&mut self.state, State::Normal) { 32 match mem::replace(&mut self.state, State::Normal) {
35 State::PendingStart => unreachable!(), 33 State::PendingStart => unreachable!(),
36 State::PendingFinish => self.inner.finish_internal(), 34 State::PendingFinish => self.inner.finish_branch(),
37 State::Normal => (), 35 State::Normal => (),
38 } 36 }
39 self.eat_trivias(); 37 self.eat_trivias();
@@ -48,12 +46,12 @@ impl<'a> TreeSink for TextTreeSink<'a> {
48 fn start_branch(&mut self, kind: SyntaxKind) { 46 fn start_branch(&mut self, kind: SyntaxKind) {
49 match mem::replace(&mut self.state, State::Normal) { 47 match mem::replace(&mut self.state, State::Normal) {
50 State::PendingStart => { 48 State::PendingStart => {
51 self.inner.start_internal(kind); 49 self.inner.start_branch(kind);
52 // No need to attach trivias to previous node: there is no 50 // No need to attach trivias to previous node: there is no
53 // previous node. 51 // previous node.
54 return; 52 return;
55 } 53 }
56 State::PendingFinish => self.inner.finish_internal(), 54 State::PendingFinish => self.inner.finish_branch(),
57 State::Normal => (), 55 State::Normal => (),
58 } 56 }
59 57
@@ -73,21 +71,20 @@ impl<'a> TreeSink for TextTreeSink<'a> {
73 n_attached_trivias(kind, leading_trivias) 71 n_attached_trivias(kind, leading_trivias)
74 }; 72 };
75 self.eat_n_trivias(n_trivias - n_attached_trivias); 73 self.eat_n_trivias(n_trivias - n_attached_trivias);
76 self.inner.start_internal(kind); 74 self.inner.start_branch(kind);
77 self.eat_n_trivias(n_attached_trivias); 75 self.eat_n_trivias(n_attached_trivias);
78 } 76 }
79 77
80 fn finish_branch(&mut self) { 78 fn finish_branch(&mut self) {
81 match mem::replace(&mut self.state, State::PendingFinish) { 79 match mem::replace(&mut self.state, State::PendingFinish) {
82 State::PendingStart => unreachable!(), 80 State::PendingStart => unreachable!(),
83 State::PendingFinish => self.inner.finish_internal(), 81 State::PendingFinish => self.inner.finish_branch(),
84 State::Normal => (), 82 State::Normal => (),
85 } 83 }
86 } 84 }
87 85
88 fn error(&mut self, error: ParseError) { 86 fn error(&mut self, error: ParseError) {
89 let error = SyntaxError::new(SyntaxErrorKind::ParseError(error), self.text_pos); 87 self.inner.error(error, self.text_pos)
90 self.errors.push(error)
91 } 88 }
92} 89}
93 90
@@ -99,8 +96,7 @@ impl<'a> TextTreeSink<'a> {
99 text_pos: 0.into(), 96 text_pos: 0.into(),
100 token_pos: 0, 97 token_pos: 0,
101 state: State::PendingStart, 98 state: State::PendingStart,
102 errors: Vec::new(), 99 inner: SyntaxTreeBuilder::default(),
103 inner: GreenNodeBuilder::new(),
104 } 100 }
105 } 101 }
106 102
@@ -108,12 +104,12 @@ impl<'a> TextTreeSink<'a> {
108 match mem::replace(&mut self.state, State::Normal) { 104 match mem::replace(&mut self.state, State::Normal) {
109 State::PendingFinish => { 105 State::PendingFinish => {
110 self.eat_trivias(); 106 self.eat_trivias();
111 self.inner.finish_internal() 107 self.inner.finish_branch()
112 } 108 }
113 State::PendingStart | State::Normal => unreachable!(), 109 State::PendingStart | State::Normal => unreachable!(),
114 } 110 }
115 111
116 (self.inner.finish(), self.errors) 112 self.inner.finish_raw()
117 } 113 }
118 114
119 fn eat_trivias(&mut self) { 115 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::{
11 borrow::Borrow, 11 borrow::Borrow,
12}; 12};
13 13
14use rowan::{Types, TransparentNewType}; 14use ra_parser::ParseError;
15use rowan::{Types, TransparentNewType, GreenNodeBuilder};
15 16
16use crate::{ 17use crate::{
17 SmolStr, SyntaxKind, TextRange, SyntaxText, SourceFile, AstNode, 18 SmolStr, SyntaxKind, TextUnit, TextRange, SyntaxText, SourceFile, AstNode,
18 syntax_error::SyntaxError, 19 syntax_error::{SyntaxError, SyntaxErrorKind},
19}; 20};
20 21
21pub use rowan::WalkEvent; 22pub use rowan::WalkEvent;
@@ -276,3 +277,47 @@ fn has_short_text(kind: SyntaxKind) -> bool {
276 _ => false, 277 _ => false,
277 } 278 }
278} 279}
280
281pub struct SyntaxTreeBuilder {
282 errors: Vec<SyntaxError>,
283 inner: GreenNodeBuilder<RaTypes>,
284}
285
286impl Default for SyntaxTreeBuilder {
287 fn default() -> SyntaxTreeBuilder {
288 SyntaxTreeBuilder { errors: Vec::new(), inner: GreenNodeBuilder::new() }
289 }
290}
291
292impl SyntaxTreeBuilder {
293 pub(crate) fn finish_raw(self) -> (GreenNode, Vec<SyntaxError>) {
294 let green = self.inner.finish();
295 (green, self.errors)
296 }
297
298 pub fn finish(self) -> TreeArc<SyntaxNode> {
299 let (green, errors) = self.finish_raw();
300 let node = SyntaxNode::new(green, errors);
301 if cfg!(debug_assertions) {
302 crate::validation::validate_block_structure(&node);
303 }
304 node
305 }
306
307 pub fn leaf(&mut self, kind: SyntaxKind, text: SmolStr) {
308 self.inner.leaf(kind, text)
309 }
310
311 pub fn start_branch(&mut self, kind: SyntaxKind) {
312 self.inner.start_internal(kind)
313 }
314
315 pub fn finish_branch(&mut self) {
316 self.inner.finish_internal()
317 }
318
319 pub fn error(&mut self, error: ParseError, text_pos: TextUnit) {
320 let error = SyntaxError::new(SyntaxErrorKind::ParseError(error), text_pos);
321 self.errors.push(error)
322 }
323}