aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_syntax/src/parsing/builder.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_syntax/src/parsing/builder.rs')
-rw-r--r--crates/ra_syntax/src/parsing/builder.rs55
1 files changed, 44 insertions, 11 deletions
diff --git a/crates/ra_syntax/src/parsing/builder.rs b/crates/ra_syntax/src/parsing/builder.rs
index 0775b0900..cfe3139b8 100644
--- a/crates/ra_syntax/src/parsing/builder.rs
+++ b/crates/ra_syntax/src/parsing/builder.rs
@@ -1,4 +1,7 @@
1use std::mem;
2
1use ra_parser::{TreeSink, ParseError}; 3use ra_parser::{TreeSink, ParseError};
4use rowan::GreenNodeBuilder;
2 5
3use crate::{ 6use crate::{
4 SmolStr, SyntaxError, SyntaxErrorKind, TextUnit, TextRange, 7 SmolStr, SyntaxError, SyntaxErrorKind, TextUnit, TextRange,
@@ -7,19 +10,32 @@ use crate::{
7 syntax_node::{GreenNode, RaTypes}, 10 syntax_node::{GreenNode, RaTypes},
8}; 11};
9 12
10use rowan::GreenNodeBuilder; 13/// Bridges the parser with our specific syntax tree representation.
11 14///
15/// `TreeBuilder` also handles attachment of trivia (whitespace) to nodes.
12pub(crate) struct TreeBuilder<'a> { 16pub(crate) struct TreeBuilder<'a> {
13 text: &'a str, 17 text: &'a str,
14 tokens: &'a [Token], 18 tokens: &'a [Token],
15 text_pos: TextUnit, 19 text_pos: TextUnit,
16 token_pos: usize, 20 token_pos: usize,
21 state: State,
17 errors: Vec<SyntaxError>, 22 errors: Vec<SyntaxError>,
18 inner: GreenNodeBuilder<RaTypes>, 23 inner: GreenNodeBuilder<RaTypes>,
19} 24}
20 25
26enum State {
27 PendingStart,
28 Normal,
29 PendingFinish,
30}
31
21impl<'a> TreeSink for TreeBuilder<'a> { 32impl<'a> TreeSink for TreeBuilder<'a> {
22 fn leaf(&mut self, kind: SyntaxKind, n_tokens: u8) { 33 fn leaf(&mut self, kind: SyntaxKind, n_tokens: u8) {
34 match mem::replace(&mut self.state, State::Normal) {
35 State::PendingStart => unreachable!(),
36 State::PendingFinish => self.inner.finish_internal(),
37 State::Normal => (),
38 }
23 self.eat_trivias(); 39 self.eat_trivias();
24 let n_tokens = n_tokens as usize; 40 let n_tokens = n_tokens as usize;
25 let len = self.tokens[self.token_pos..self.token_pos + n_tokens] 41 let len = self.tokens[self.token_pos..self.token_pos + n_tokens]
@@ -29,11 +45,18 @@ impl<'a> TreeSink for TreeBuilder<'a> {
29 self.do_leaf(kind, len, n_tokens); 45 self.do_leaf(kind, len, n_tokens);
30 } 46 }
31 47
32 fn start_branch(&mut self, kind: SyntaxKind, root: bool) { 48 fn start_branch(&mut self, kind: SyntaxKind) {
33 if root { 49 match mem::replace(&mut self.state, State::Normal) {
34 self.inner.start_internal(kind); 50 State::PendingStart => {
35 return; 51 self.inner.start_internal(kind);
52 // No need to attach trivias to previous node: there is no
53 // previous node.
54 return;
55 }
56 State::PendingFinish => self.inner.finish_internal(),
57 State::Normal => (),
36 } 58 }
59
37 let n_trivias = 60 let n_trivias =
38 self.tokens[self.token_pos..].iter().take_while(|it| it.kind.is_trivia()).count(); 61 self.tokens[self.token_pos..].iter().take_while(|it| it.kind.is_trivia()).count();
39 let leading_trivias = &self.tokens[self.token_pos..self.token_pos + n_trivias]; 62 let leading_trivias = &self.tokens[self.token_pos..self.token_pos + n_trivias];
@@ -54,11 +77,12 @@ impl<'a> TreeSink for TreeBuilder<'a> {
54 self.eat_n_trivias(n_attached_trivias); 77 self.eat_n_trivias(n_attached_trivias);
55 } 78 }
56 79
57 fn finish_branch(&mut self, root: bool) { 80 fn finish_branch(&mut self) {
58 if root { 81 match mem::replace(&mut self.state, State::PendingFinish) {
59 self.eat_trivias() 82 State::PendingStart => unreachable!(),
83 State::PendingFinish => self.inner.finish_internal(),
84 State::Normal => (),
60 } 85 }
61 self.inner.finish_internal();
62 } 86 }
63 87
64 fn error(&mut self, error: ParseError) { 88 fn error(&mut self, error: ParseError) {
@@ -74,12 +98,21 @@ impl<'a> TreeBuilder<'a> {
74 tokens, 98 tokens,
75 text_pos: 0.into(), 99 text_pos: 0.into(),
76 token_pos: 0, 100 token_pos: 0,
101 state: State::PendingStart,
77 errors: Vec::new(), 102 errors: Vec::new(),
78 inner: GreenNodeBuilder::new(), 103 inner: GreenNodeBuilder::new(),
79 } 104 }
80 } 105 }
81 106
82 pub(super) fn finish(self) -> (GreenNode, Vec<SyntaxError>) { 107 pub(super) fn finish(mut self) -> (GreenNode, Vec<SyntaxError>) {
108 match mem::replace(&mut self.state, State::Normal) {
109 State::PendingFinish => {
110 self.eat_trivias();
111 self.inner.finish_internal()
112 }
113 State::PendingStart | State::Normal => unreachable!(),
114 }
115
83 (self.inner.finish(), self.errors) 116 (self.inner.finish(), self.errors)
84 } 117 }
85 118