diff options
Diffstat (limited to 'crates/ra_syntax')
-rw-r--r-- | crates/ra_syntax/src/lib.rs | 3 | ||||
-rw-r--r-- | crates/ra_syntax/src/parser_impl/event.rs | 210 | ||||
-rw-r--r-- | crates/ra_syntax/src/parser_impl/mod.rs | 25 | ||||
-rw-r--r-- | crates/ra_syntax/src/reparsing.rs | 3 | ||||
-rw-r--r-- | crates/ra_syntax/src/yellow/builder.rs | 32 | ||||
-rw-r--r-- | crates/ra_syntax/tests/data/parser/err/0025_nope.txt | 6 | ||||
-rw-r--r-- | crates/ra_syntax/tests/data/parser/ok/0033_label_break.txt | 6 |
7 files changed, 183 insertions, 102 deletions
diff --git a/crates/ra_syntax/src/lib.rs b/crates/ra_syntax/src/lib.rs index 738664afd..703469629 100644 --- a/crates/ra_syntax/src/lib.rs +++ b/crates/ra_syntax/src/lib.rs | |||
@@ -74,7 +74,8 @@ impl File { | |||
74 | } | 74 | } |
75 | pub fn parse(text: &str) -> File { | 75 | pub fn parse(text: &str) -> File { |
76 | let tokens = tokenize(&text); | 76 | let tokens = tokenize(&text); |
77 | let (green, errors) = parser_impl::parse_with::<yellow::GreenBuilder>( | 77 | let (green, errors) = parser_impl::parse_with( |
78 | yellow::GreenBuilder::new(), | ||
78 | text, &tokens, grammar::root, | 79 | text, &tokens, grammar::root, |
79 | ); | 80 | ); |
80 | File::new(green, errors) | 81 | File::new(green, errors) |
diff --git a/crates/ra_syntax/src/parser_impl/event.rs b/crates/ra_syntax/src/parser_impl/event.rs index 9fd56b996..95e5ce4cc 100644 --- a/crates/ra_syntax/src/parser_impl/event.rs +++ b/crates/ra_syntax/src/parser_impl/event.rs | |||
@@ -9,9 +9,10 @@ | |||
9 | //! this stream to a real tree. | 9 | //! this stream to a real tree. |
10 | use std::mem; | 10 | use std::mem; |
11 | use { | 11 | use { |
12 | TextUnit, TextRange, SmolStr, | ||
12 | lexer::Token, | 13 | lexer::Token, |
13 | parser_impl::Sink, | 14 | parser_impl::Sink, |
14 | SyntaxKind::{self, TOMBSTONE}, | 15 | SyntaxKind::{self, *}, |
15 | }; | 16 | }; |
16 | 17 | ||
17 | 18 | ||
@@ -78,77 +79,162 @@ pub(crate) enum Event { | |||
78 | }, | 79 | }, |
79 | } | 80 | } |
80 | 81 | ||
82 | pub(super) struct EventProcessor<'a, S: Sink> { | ||
83 | sink: S, | ||
84 | text_pos: TextUnit, | ||
85 | text: &'a str, | ||
86 | token_pos: usize, | ||
87 | tokens: &'a [Token], | ||
88 | events: &'a mut [Event], | ||
89 | } | ||
81 | 90 | ||
82 | pub(super) fn process<'a, S: Sink<'a>>(builder: &mut S, tokens: &[Token], mut events: Vec<Event>) { | 91 | impl<'a, S: Sink> EventProcessor<'a, S> { |
83 | fn tombstone() -> Event { | 92 | pub(super) fn new(sink: S, text: &'a str, tokens: &'a[Token], events: &'a mut [Event]) -> EventProcessor<'a, S> { |
84 | Event::Start { kind: TOMBSTONE, forward_parent: None } | 93 | EventProcessor { |
94 | sink, | ||
95 | text_pos: 0.into(), | ||
96 | text, | ||
97 | token_pos: 0, | ||
98 | tokens, | ||
99 | events | ||
100 | } | ||
85 | } | 101 | } |
86 | let eat_ws = |idx: &mut usize, builder: &mut S| { | 102 | |
87 | while let Some(token) = tokens.get(*idx) { | 103 | pub(super) fn process(mut self) -> S { |
88 | if !token.kind.is_trivia() { | 104 | fn tombstone() -> Event { |
89 | break; | 105 | Event::Start { kind: TOMBSTONE, forward_parent: None } |
90 | } | ||
91 | builder.leaf(token.kind, token.len); | ||
92 | *idx += 1 | ||
93 | } | 106 | } |
94 | }; | 107 | let mut forward_parents = Vec::new(); |
95 | 108 | ||
96 | let events: &mut [Event] = &mut events; | 109 | for i in 0..self.events.len() { |
97 | let mut depth = 0; | 110 | match mem::replace(&mut self.events[i], tombstone()) { |
98 | let mut forward_parents = Vec::new(); | 111 | Event::Start { |
99 | let mut next_tok_idx = 0; | 112 | kind: TOMBSTONE, .. |
100 | for i in 0..events.len() { | 113 | } => (), |
101 | match mem::replace(&mut events[i], tombstone()) { | 114 | |
102 | Event::Start { | 115 | Event::Start { kind, forward_parent } => { |
103 | kind: TOMBSTONE, .. | 116 | forward_parents.push(kind); |
104 | } => (), | 117 | let mut idx = i; |
105 | 118 | let mut fp = forward_parent; | |
106 | Event::Start { kind, forward_parent } => { | 119 | while let Some(fwd) = fp { |
107 | forward_parents.push(kind); | 120 | idx += fwd as usize; |
108 | let mut idx = i; | 121 | fp = match mem::replace(&mut self.events[idx], tombstone()) { |
109 | let mut fp = forward_parent; | 122 | Event::Start { |
110 | while let Some(fwd) = fp { | 123 | kind, |
111 | idx += fwd as usize; | 124 | forward_parent, |
112 | fp = match mem::replace(&mut events[idx], tombstone()) { | 125 | } => { |
113 | Event::Start { | 126 | forward_parents.push(kind); |
114 | kind, | 127 | forward_parent |
115 | forward_parent, | 128 | }, |
116 | } => { | 129 | _ => unreachable!(), |
117 | forward_parents.push(kind); | 130 | }; |
118 | forward_parent | 131 | } |
119 | }, | 132 | for kind in forward_parents.drain(..).rev() { |
120 | _ => unreachable!(), | 133 | self.start(kind); |
121 | }; | ||
122 | } | ||
123 | for kind in forward_parents.drain(..).rev() { | ||
124 | if depth > 0 { | ||
125 | eat_ws(&mut next_tok_idx, builder); | ||
126 | } | 134 | } |
127 | depth += 1; | ||
128 | builder.start_internal(kind); | ||
129 | } | 135 | } |
130 | } | 136 | Event::Finish => { |
131 | Event::Finish => { | 137 | let last = i == self.events.len() - 1; |
132 | depth -= 1; | 138 | self.finish(last); |
133 | if depth == 0 { | 139 | }, |
134 | eat_ws(&mut next_tok_idx, builder); | 140 | Event::Token { kind, n_raw_tokens } => { |
141 | self.eat_ws(); | ||
142 | let n_raw_tokens = n_raw_tokens as usize; | ||
143 | let len = self.tokens[self.token_pos..self.token_pos + n_raw_tokens] | ||
144 | .iter() | ||
145 | .map(|it| it.len) | ||
146 | .sum::<TextUnit>(); | ||
147 | self.leaf(kind, len, n_raw_tokens); | ||
135 | } | 148 | } |
149 | Event::Error { msg } => self.sink.error(msg, self.text_pos), | ||
150 | } | ||
151 | } | ||
152 | self.sink | ||
153 | } | ||
154 | |||
155 | fn start(&mut self, kind: SyntaxKind) { | ||
156 | if kind == ROOT { | ||
157 | self.sink.start_internal(kind); | ||
158 | return; | ||
159 | } | ||
160 | let n_trivias = self.tokens[self.token_pos..] | ||
161 | .iter() | ||
162 | .take_while(|it| it.kind.is_trivia()) | ||
163 | .count(); | ||
164 | let leading_trivias = &self.tokens[self.token_pos..self.token_pos + n_trivias]; | ||
165 | let mut trivia_end = self.text_pos + leading_trivias | ||
166 | .iter() | ||
167 | .map(|it| it.len) | ||
168 | .sum::<TextUnit>(); | ||
169 | |||
170 | let n_attached_trivias = { | ||
171 | let leading_trivias = leading_trivias.iter().rev() | ||
172 | .map(|it| { | ||
173 | let next_end = trivia_end - it.len; | ||
174 | let range = TextRange::from_to(next_end, trivia_end); | ||
175 | trivia_end = next_end; | ||
176 | (it.kind, &self.text[range]) | ||
177 | }); | ||
178 | n_attached_trivias(kind, leading_trivias) | ||
179 | }; | ||
180 | self.eat_n_trivias(n_trivias - n_attached_trivias); | ||
181 | self.sink.start_internal(kind); | ||
182 | self.eat_n_trivias(n_attached_trivias); | ||
183 | } | ||
136 | 184 | ||
137 | builder.finish_internal(); | 185 | fn finish(&mut self, last: bool) { |
186 | if last { | ||
187 | self.eat_ws() | ||
188 | } | ||
189 | self.sink.finish_internal(); | ||
190 | } | ||
191 | |||
192 | fn eat_ws(&mut self) { | ||
193 | while let Some(&token) = self.tokens.get(self.token_pos) { | ||
194 | if !token.kind.is_trivia() { | ||
195 | break; | ||
138 | } | 196 | } |
139 | Event::Token { | 197 | self.leaf(token.kind, token.len, 1); |
140 | kind, | 198 | } |
141 | mut n_raw_tokens, | 199 | } |
142 | } => { | 200 | |
143 | eat_ws(&mut next_tok_idx, builder); | 201 | fn eat_n_trivias(&mut self, n: usize) { |
144 | let mut len = 0.into(); | 202 | for _ in 0..n { |
145 | for _ in 0..n_raw_tokens { | 203 | let token = self.tokens[self.token_pos]; |
146 | len += tokens[next_tok_idx].len; | 204 | assert!(token.kind.is_trivia()); |
147 | next_tok_idx += 1; | 205 | self.leaf(token.kind, token.len, 1); |
206 | } | ||
207 | } | ||
208 | |||
209 | fn leaf(&mut self, kind: SyntaxKind, len: TextUnit, n_tokens: usize) { | ||
210 | let range = TextRange::offset_len(self.text_pos, len); | ||
211 | let text: SmolStr = self.text[range].into(); | ||
212 | self.text_pos += len; | ||
213 | self.token_pos += n_tokens; | ||
214 | self.sink.leaf(kind, text); | ||
215 | } | ||
216 | } | ||
217 | |||
218 | fn n_attached_trivias<'a>(kind: SyntaxKind, trivias: impl Iterator<Item=(SyntaxKind, &'a str)>) -> usize { | ||
219 | match kind { | ||
220 | STRUCT_DEF | ENUM_DEF | FN_DEF | TRAIT_DEF | MODULE => { | ||
221 | let mut res = 0; | ||
222 | for (i, (kind, text)) in trivias.enumerate() { | ||
223 | match kind { | ||
224 | WHITESPACE => { | ||
225 | if text.contains("\n\n") { | ||
226 | break; | ||
227 | } | ||
228 | } | ||
229 | COMMENT => { | ||
230 | res = i + 1; | ||
231 | } | ||
232 | _ => (), | ||
148 | } | 233 | } |
149 | builder.leaf(kind, len); | ||
150 | } | 234 | } |
151 | Event::Error { msg } => builder.error(msg), | 235 | res |
152 | } | 236 | } |
237 | _ => 0, | ||
153 | } | 238 | } |
239 | |||
154 | } | 240 | } |
diff --git a/crates/ra_syntax/src/parser_impl/mod.rs b/crates/ra_syntax/src/parser_impl/mod.rs index b343b404f..8d74cef0e 100644 --- a/crates/ra_syntax/src/parser_impl/mod.rs +++ b/crates/ra_syntax/src/parser_impl/mod.rs | |||
@@ -4,45 +4,44 @@ mod input; | |||
4 | use std::cell::Cell; | 4 | use std::cell::Cell; |
5 | 5 | ||
6 | use { | 6 | use { |
7 | TextUnit, SmolStr, | ||
7 | lexer::Token, | 8 | lexer::Token, |
8 | parser_api::Parser, | 9 | parser_api::Parser, |
9 | parser_impl::{ | 10 | parser_impl::{ |
10 | event::{process, Event}, | 11 | event::{EventProcessor, Event}, |
11 | input::{InputPosition, ParserInput}, | 12 | input::{InputPosition, ParserInput}, |
12 | }, | 13 | }, |
13 | TextUnit, | ||
14 | }; | 14 | }; |
15 | 15 | ||
16 | use SyntaxKind::{self, EOF, TOMBSTONE}; | 16 | use SyntaxKind::{self, EOF, TOMBSTONE}; |
17 | 17 | ||
18 | pub(crate) trait Sink<'a> { | 18 | pub(crate) trait Sink { |
19 | type Tree; | 19 | type Tree; |
20 | 20 | ||
21 | fn new(text: &'a str) -> Self; | 21 | fn leaf(&mut self, kind: SyntaxKind, text: SmolStr); |
22 | |||
23 | fn leaf(&mut self, kind: SyntaxKind, len: TextUnit); | ||
24 | fn start_internal(&mut self, kind: SyntaxKind); | 22 | fn start_internal(&mut self, kind: SyntaxKind); |
25 | fn finish_internal(&mut self); | 23 | fn finish_internal(&mut self); |
26 | fn error(&mut self, err: String); | 24 | fn error(&mut self, message: String, offset: TextUnit); |
27 | fn finish(self) -> Self::Tree; | 25 | fn finish(self) -> Self::Tree; |
28 | } | 26 | } |
29 | 27 | ||
30 | /// Parse a sequence of tokens into the representative node tree | 28 | /// Parse a sequence of tokens into the representative node tree |
31 | pub(crate) fn parse_with<'a, S: Sink<'a>>( | 29 | pub(crate) fn parse_with<S: Sink>( |
32 | text: &'a str, | 30 | sink: S, |
31 | text: &str, | ||
33 | tokens: &[Token], | 32 | tokens: &[Token], |
34 | parser: fn(&mut Parser), | 33 | parser: fn(&mut Parser), |
35 | ) -> S::Tree { | 34 | ) -> S::Tree { |
36 | let events = { | 35 | let mut events = { |
37 | let input = input::ParserInput::new(text, tokens); | 36 | let input = input::ParserInput::new(text, tokens); |
38 | let parser_impl = ParserImpl::new(&input); | 37 | let parser_impl = ParserImpl::new(&input); |
39 | let mut parser_api = Parser(parser_impl); | 38 | let mut parser_api = Parser(parser_impl); |
40 | parser(&mut parser_api); | 39 | parser(&mut parser_api); |
41 | parser_api.0.into_events() | 40 | parser_api.0.into_events() |
42 | }; | 41 | }; |
43 | let mut sink = S::new(text); | 42 | EventProcessor::new(sink, text, tokens, &mut events) |
44 | process(&mut sink, tokens, events); | 43 | .process() |
45 | sink.finish() | 44 | .finish() |
46 | } | 45 | } |
47 | 46 | ||
48 | /// Implementation details of `Parser`, extracted | 47 | /// Implementation details of `Parser`, extracted |
diff --git a/crates/ra_syntax/src/reparsing.rs b/crates/ra_syntax/src/reparsing.rs index dcafd2c40..d8b6a6a10 100644 --- a/crates/ra_syntax/src/reparsing.rs +++ b/crates/ra_syntax/src/reparsing.rs | |||
@@ -84,7 +84,8 @@ fn reparse_block<'node>( | |||
84 | return None; | 84 | return None; |
85 | } | 85 | } |
86 | let (green, new_errors) = | 86 | let (green, new_errors) = |
87 | parser_impl::parse_with::<yellow::GreenBuilder>( | 87 | parser_impl::parse_with( |
88 | yellow::GreenBuilder::new(), | ||
88 | &text, &tokens, reparser, | 89 | &text, &tokens, reparser, |
89 | ); | 90 | ); |
90 | Some((node, green, new_errors)) | 91 | Some((node, green, new_errors)) |
diff --git a/crates/ra_syntax/src/yellow/builder.rs b/crates/ra_syntax/src/yellow/builder.rs index 35dbaec05..c307b2bd0 100644 --- a/crates/ra_syntax/src/yellow/builder.rs +++ b/crates/ra_syntax/src/yellow/builder.rs | |||
@@ -1,33 +1,29 @@ | |||
1 | use rowan::GreenNodeBuilder; | 1 | use rowan::GreenNodeBuilder; |
2 | use { | 2 | use { |
3 | TextUnit, SmolStr, | ||
3 | parser_impl::Sink, | 4 | parser_impl::Sink, |
4 | yellow::{GreenNode, SyntaxError, RaTypes}, | 5 | yellow::{GreenNode, SyntaxError, RaTypes}, |
5 | SyntaxKind, TextRange, TextUnit, | 6 | SyntaxKind, |
6 | }; | 7 | }; |
7 | 8 | ||
8 | pub(crate) struct GreenBuilder<'a> { | 9 | pub(crate) struct GreenBuilder { |
9 | text: &'a str, | ||
10 | pos: TextUnit, | ||
11 | errors: Vec<SyntaxError>, | 10 | errors: Vec<SyntaxError>, |
12 | inner: GreenNodeBuilder<RaTypes>, | 11 | inner: GreenNodeBuilder<RaTypes>, |
13 | } | 12 | } |
14 | 13 | ||
15 | impl<'a> Sink<'a> for GreenBuilder<'a> { | 14 | impl GreenBuilder { |
16 | type Tree = (GreenNode, Vec<SyntaxError>); | 15 | pub(crate) fn new() -> GreenBuilder { |
17 | |||
18 | fn new(text: &'a str) -> Self { | ||
19 | GreenBuilder { | 16 | GreenBuilder { |
20 | text, | ||
21 | pos: 0.into(), | ||
22 | errors: Vec::new(), | 17 | errors: Vec::new(), |
23 | inner: GreenNodeBuilder::new(), | 18 | inner: GreenNodeBuilder::new(), |
24 | } | 19 | } |
25 | } | 20 | } |
21 | } | ||
22 | |||
23 | impl Sink for GreenBuilder { | ||
24 | type Tree = (GreenNode, Vec<SyntaxError>); | ||
26 | 25 | ||
27 | fn leaf(&mut self, kind: SyntaxKind, len: TextUnit) { | 26 | fn leaf(&mut self, kind: SyntaxKind, text: SmolStr) { |
28 | let range = TextRange::offset_len(self.pos, len); | ||
29 | self.pos += len; | ||
30 | let text = self.text[range].into(); | ||
31 | self.inner.leaf(kind, text); | 27 | self.inner.leaf(kind, text); |
32 | } | 28 | } |
33 | 29 | ||
@@ -39,11 +35,9 @@ impl<'a> Sink<'a> for GreenBuilder<'a> { | |||
39 | self.inner.finish_internal(); | 35 | self.inner.finish_internal(); |
40 | } | 36 | } |
41 | 37 | ||
42 | fn error(&mut self, message: String) { | 38 | fn error(&mut self, message: String, offset: TextUnit) { |
43 | self.errors.push(SyntaxError { | 39 | let error = SyntaxError { msg: message, offset }; |
44 | msg: message, | 40 | self.errors.push(error) |
45 | offset: self.pos, | ||
46 | }) | ||
47 | } | 41 | } |
48 | 42 | ||
49 | fn finish(self) -> (GreenNode, Vec<SyntaxError>) { | 43 | fn finish(self) -> (GreenNode, Vec<SyntaxError>) { |
diff --git a/crates/ra_syntax/tests/data/parser/err/0025_nope.txt b/crates/ra_syntax/tests/data/parser/err/0025_nope.txt index c30b8585f..6879c8d0a 100644 --- a/crates/ra_syntax/tests/data/parser/err/0025_nope.txt +++ b/crates/ra_syntax/tests/data/parser/err/0025_nope.txt | |||
@@ -137,9 +137,9 @@ ROOT@[0; 575) | |||
137 | BLOCK@[306; 459) | 137 | BLOCK@[306; 459) |
138 | L_CURLY@[306; 307) | 138 | L_CURLY@[306; 307) |
139 | WHITESPACE@[307; 316) | 139 | WHITESPACE@[307; 316) |
140 | COMMENT@[316; 329) | 140 | ENUM_DEF@[316; 453) |
141 | WHITESPACE@[329; 338) | 141 | COMMENT@[316; 329) |
142 | ENUM_DEF@[338; 453) | 142 | WHITESPACE@[329; 338) |
143 | ENUM_KW@[338; 342) | 143 | ENUM_KW@[338; 342) |
144 | WHITESPACE@[342; 343) | 144 | WHITESPACE@[342; 343) |
145 | NAME@[343; 348) | 145 | NAME@[343; 348) |
diff --git a/crates/ra_syntax/tests/data/parser/ok/0033_label_break.txt b/crates/ra_syntax/tests/data/parser/ok/0033_label_break.txt index 6abb9234c..201eca644 100644 --- a/crates/ra_syntax/tests/data/parser/ok/0033_label_break.txt +++ b/crates/ra_syntax/tests/data/parser/ok/0033_label_break.txt | |||
@@ -1,7 +1,7 @@ | |||
1 | ROOT@[0; 506) | 1 | ROOT@[0; 506) |
2 | COMMENT@[0; 33) | 2 | FN_DEF@[0; 505) |
3 | WHITESPACE@[33; 34) | 3 | COMMENT@[0; 33) |
4 | FN_DEF@[34; 505) | 4 | WHITESPACE@[33; 34) |
5 | FN_KW@[34; 36) | 5 | FN_KW@[34; 36) |
6 | WHITESPACE@[36; 37) | 6 | WHITESPACE@[36; 37) |
7 | NAME@[37; 41) | 7 | NAME@[37; 41) |