aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_parser/src/parser.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_parser/src/parser.rs')
-rw-r--r--crates/ra_parser/src/parser.rs328
1 files changed, 105 insertions, 223 deletions
diff --git a/crates/ra_parser/src/parser.rs b/crates/ra_parser/src/parser.rs
index d8567e84b..a2ac363fb 100644
--- a/crates/ra_parser/src/parser.rs
+++ b/crates/ra_parser/src/parser.rs
@@ -5,8 +5,8 @@ use drop_bomb::DropBomb;
5use crate::{ 5use crate::{
6 event::Event, 6 event::Event,
7 ParseError, 7 ParseError,
8 SyntaxKind::{self, EOF, ERROR, TOMBSTONE}, 8 SyntaxKind::{self, EOF, ERROR, L_DOLLAR, R_DOLLAR, TOMBSTONE},
9 Token, TokenSet, TokenSource, T, 9 TokenSet, TokenSource, T,
10}; 10};
11 11
12/// `Parser` struct provides the low-level API for 12/// `Parser` struct provides the low-level API for
@@ -40,38 +40,6 @@ impl<'t> Parser<'t> {
40 self.nth(0) 40 self.nth(0)
41 } 41 }
42 42
43 /// Returns the kinds of the current two tokens, if they are not separated
44 /// by trivia.
45 ///
46 /// Useful for parsing things like `>>`.
47 pub(crate) fn current2(&self) -> Option<(SyntaxKind, SyntaxKind)> {
48 let c1 = self.nth(0);
49 let c2 = self.nth(1);
50
51 if self.token_source.current().is_jointed_to_next {
52 Some((c1, c2))
53 } else {
54 None
55 }
56 }
57
58 /// Returns the kinds of the current three tokens, if they are not separated
59 /// by trivia.
60 ///
61 /// Useful for parsing things like `=>>`.
62 pub(crate) fn current3(&self) -> Option<(SyntaxKind, SyntaxKind, SyntaxKind)> {
63 let c1 = self.nth(0);
64 let c2 = self.nth(1);
65 let c3 = self.nth(2);
66 if self.token_source.current().is_jointed_to_next
67 && self.token_source.lookahead_nth(1).is_jointed_to_next
68 {
69 Some((c1, c2, c3))
70 } else {
71 None
72 }
73 }
74
75 /// Lookahead operation: returns the kind of the next nth 43 /// Lookahead operation: returns the kind of the next nth
76 /// token. 44 /// token.
77 pub(crate) fn nth(&self, n: usize) -> SyntaxKind { 45 pub(crate) fn nth(&self, n: usize) -> SyntaxKind {
@@ -81,33 +49,93 @@ impl<'t> Parser<'t> {
81 assert!(steps <= 10_000_000, "the parser seems stuck"); 49 assert!(steps <= 10_000_000, "the parser seems stuck");
82 self.steps.set(steps + 1); 50 self.steps.set(steps + 1);
83 51
84 // It is beecause the Dollar will appear between nth 52 self.token_source.lookahead_nth(n).kind
85 // Following code skips through it
86 let mut non_dollars_count = 0;
87 let mut i = 0;
88
89 loop {
90 let token = self.token_source.lookahead_nth(i);
91 let mut kind = token.kind;
92 if let Some((composited, step)) = self.is_composite(token, i) {
93 kind = composited;
94 i += step;
95 } else {
96 i += 1;
97 }
98
99 match kind {
100 EOF => return EOF,
101 SyntaxKind::L_DOLLAR | SyntaxKind::R_DOLLAR => {}
102 _ if non_dollars_count == n => return kind,
103 _ => non_dollars_count += 1,
104 }
105 }
106 } 53 }
107 54
108 /// Checks if the current token is `kind`. 55 /// Checks if the current token is `kind`.
109 pub(crate) fn at(&self, kind: SyntaxKind) -> bool { 56 pub(crate) fn at(&self, kind: SyntaxKind) -> bool {
110 self.current() == kind 57 self.nth_at(0, kind)
58 }
59
60 pub(crate) fn nth_at(&self, n: usize, kind: SyntaxKind) -> bool {
61 match kind {
62 T![-=] => self.at_composite2(n, T![-], T![=]),
63 T![->] => self.at_composite2(n, T![-], T![>]),
64 T![::] => self.at_composite2(n, T![:], T![:]),
65 T![!=] => self.at_composite2(n, T![!], T![=]),
66 T![..] => self.at_composite2(n, T![.], T![.]),
67 T![*=] => self.at_composite2(n, T![*], T![=]),
68 T![/=] => self.at_composite2(n, T![/], T![=]),
69 T![&&] => self.at_composite2(n, T![&], T![&]),
70 T![&=] => self.at_composite2(n, T![&], T![=]),
71 T![%=] => self.at_composite2(n, T![%], T![=]),
72 T![^=] => self.at_composite2(n, T![^], T![=]),
73 T![+=] => self.at_composite2(n, T![+], T![=]),
74 T![<<] => self.at_composite2(n, T![<], T![<]),
75 T![<=] => self.at_composite2(n, T![<], T![=]),
76 T![==] => self.at_composite2(n, T![=], T![=]),
77 T![=>] => self.at_composite2(n, T![=], T![>]),
78 T![>=] => self.at_composite2(n, T![>], T![=]),
79 T![>>] => self.at_composite2(n, T![>], T![>]),
80 T![|=] => self.at_composite2(n, T![|], T![=]),
81 T![||] => self.at_composite2(n, T![|], T![|]),
82
83 T![...] => self.at_composite3(n, T![.], T![.], T![.]),
84 T![..=] => self.at_composite3(n, T![.], T![.], T![=]),
85 T![<<=] => self.at_composite3(n, T![<], T![<], T![=]),
86 T![>>=] => self.at_composite3(n, T![>], T![>], T![=]),
87
88 _ => self.token_source.lookahead_nth(n).kind == kind,
89 }
90 }
91
92 /// Consume the next token if `kind` matches.
93 pub(crate) fn eat(&mut self, kind: SyntaxKind) -> bool {
94 if !self.at(kind) {
95 return false;
96 }
97 let n_raw_tokens = match kind {
98 T![-=]
99 | T![->]
100 | T![::]
101 | T![!=]
102 | T![..]
103 | T![*=]
104 | T![/=]
105 | T![&&]
106 | T![&=]
107 | T![%=]
108 | T![^=]
109 | T![+=]
110 | T![<<]
111 | T![<=]
112 | T![==]
113 | T![=>]
114 | T![>=]
115 | T![>>]
116 | T![|=]
117 | T![||] => 2,
118
119 T![...] | T![..=] | T![<<=] | T![>>=] => 3,
120 _ => 1,
121 };
122 self.do_bump(kind, n_raw_tokens);
123 true
124 }
125
126 fn at_composite2(&self, n: usize, k1: SyntaxKind, k2: SyntaxKind) -> bool {
127 let t1 = self.token_source.lookahead_nth(n + 0);
128 let t2 = self.token_source.lookahead_nth(n + 1);
129 t1.kind == k1 && t1.is_jointed_to_next && t2.kind == k2
130 }
131
132 fn at_composite3(&self, n: usize, k1: SyntaxKind, k2: SyntaxKind, k3: SyntaxKind) -> bool {
133 let t1 = self.token_source.lookahead_nth(n + 0);
134 let t2 = self.token_source.lookahead_nth(n + 1);
135 let t3 = self.token_source.lookahead_nth(n + 2);
136 (t1.kind == k1 && t1.is_jointed_to_next)
137 && (t2.kind == k2 && t2.is_jointed_to_next)
138 && t3.kind == k3
111 } 139 }
112 140
113 /// Checks if the current token is in `kinds`. 141 /// Checks if the current token is in `kinds`.
@@ -129,22 +157,9 @@ impl<'t> Parser<'t> {
129 Marker::new(pos) 157 Marker::new(pos)
130 } 158 }
131 159
132 /// Advances the parser by one token unconditionally 160 /// Consume the next token if `kind` matches.
133 /// Mainly use in `token_tree` parsing 161 pub(crate) fn bump(&mut self, kind: SyntaxKind) {
134 pub(crate) fn bump_raw(&mut self) { 162 assert!(self.eat(kind));
135 let mut kind = self.token_source.current().kind;
136
137 // Skip dollars, do_bump will eat these later
138 let mut i = 0;
139 while kind == SyntaxKind::L_DOLLAR || kind == SyntaxKind::R_DOLLAR {
140 kind = self.token_source.lookahead_nth(i).kind;
141 i += 1;
142 }
143
144 if kind == EOF {
145 return;
146 }
147 self.do_bump(kind, 1);
148 } 163 }
149 164
150 /// Advances the parser by one token with composite puncts handled 165 /// Advances the parser by one token with composite puncts handled
@@ -153,27 +168,7 @@ impl<'t> Parser<'t> {
153 if kind == EOF { 168 if kind == EOF {
154 return; 169 return;
155 } 170 }
156 171 self.do_bump(kind, 1)
157 use SyntaxKind::*;
158
159 // Handle parser composites
160 match kind {
161 T![...] | T![..=] => {
162 self.bump_compound(kind, 3);
163 }
164 T![..] | T![::] | T![==] | T![=>] | T![!=] | T![->] => {
165 self.bump_compound(kind, 2);
166 }
167 _ => {
168 self.do_bump(kind, 1);
169 }
170 }
171 }
172
173 /// Advances the parser by one token, asserting that it is exactly the expected token
174 pub(crate) fn bump(&mut self, expected: SyntaxKind) {
175 debug_assert!(self.nth(0) == expected);
176 self.bump_any()
177 } 172 }
178 173
179 /// Advances the parser by one token, remapping its kind. 174 /// Advances the parser by one token, remapping its kind.
@@ -190,13 +185,6 @@ impl<'t> Parser<'t> {
190 self.do_bump(kind, 1); 185 self.do_bump(kind, 1);
191 } 186 }
192 187
193 /// Advances the parser by `n` tokens, remapping its kind.
194 /// This is useful to create compound tokens from parts. For
195 /// example, an `<<` token is two consecutive remapped `<` tokens
196 pub(crate) fn bump_compound(&mut self, kind: SyntaxKind, n: u8) {
197 self.do_bump(kind, n);
198 }
199
200 /// Emit error with the `message` 188 /// Emit error with the `message`
201 /// FIXME: this should be much more fancy and support 189 /// FIXME: this should be much more fancy and support
202 /// structured errors with spans and notes, like rustc 190 /// structured errors with spans and notes, like rustc
@@ -206,15 +194,6 @@ impl<'t> Parser<'t> {
206 self.push_event(Event::Error { msg }) 194 self.push_event(Event::Error { msg })
207 } 195 }
208 196
209 /// Consume the next token if `kind` matches.
210 pub(crate) fn eat(&mut self, kind: SyntaxKind) -> bool {
211 if !self.at(kind) {
212 return false;
213 }
214 self.bump_any();
215 true
216 }
217
218 /// Consume the next token if it is `kind` or emit an error 197 /// Consume the next token if it is `kind` or emit an error
219 /// otherwise. 198 /// otherwise.
220 pub(crate) fn expect(&mut self, kind: SyntaxKind) -> bool { 199 pub(crate) fn expect(&mut self, kind: SyntaxKind) -> bool {
@@ -232,19 +211,26 @@ impl<'t> Parser<'t> {
232 211
233 /// Create an error node and consume the next token. 212 /// Create an error node and consume the next token.
234 pub(crate) fn err_recover(&mut self, message: &str, recovery: TokenSet) { 213 pub(crate) fn err_recover(&mut self, message: &str, recovery: TokenSet) {
235 if self.at(T!['{']) || self.at(T!['}']) || self.at_ts(recovery) { 214 match self.current() {
236 self.error(message); 215 T!['{'] | T!['}'] | L_DOLLAR | R_DOLLAR => {
237 } else { 216 self.error(message);
238 let m = self.start(); 217 return;
218 }
219 _ => (),
220 }
221
222 if self.at_ts(recovery) {
239 self.error(message); 223 self.error(message);
240 self.bump_any(); 224 return;
241 m.complete(self, ERROR); 225 }
242 }; 226
227 let m = self.start();
228 self.error(message);
229 self.bump_any();
230 m.complete(self, ERROR);
243 } 231 }
244 232
245 fn do_bump(&mut self, kind: SyntaxKind, n_raw_tokens: u8) { 233 fn do_bump(&mut self, kind: SyntaxKind, n_raw_tokens: u8) {
246 self.eat_dollars();
247
248 for _ in 0..n_raw_tokens { 234 for _ in 0..n_raw_tokens {
249 self.token_source.bump(); 235 self.token_source.bump();
250 } 236 }
@@ -255,110 +241,6 @@ impl<'t> Parser<'t> {
255 fn push_event(&mut self, event: Event) { 241 fn push_event(&mut self, event: Event) {
256 self.events.push(event) 242 self.events.push(event)
257 } 243 }
258
259 /// helper function for check if it is composite.
260 fn is_composite(&self, first: Token, n: usize) -> Option<(SyntaxKind, usize)> {
261 // We assume the dollars will not occuried between
262 // mult-byte tokens
263
264 let jn1 = first.is_jointed_to_next;
265 if !jn1 && first.kind != T![-] {
266 return None;
267 }
268
269 let second = self.token_source.lookahead_nth(n + 1);
270 if first.kind == T![-] && second.kind == T![>] {
271 return Some((T![->], 2));
272 }
273 if !jn1 {
274 return None;
275 }
276
277 match (first.kind, second.kind) {
278 (T![:], T![:]) => return Some((T![::], 2)),
279 (T![=], T![=]) => return Some((T![==], 2)),
280 (T![=], T![>]) => return Some((T![=>], 2)),
281 (T![!], T![=]) => return Some((T![!=], 2)),
282 _ => {}
283 }
284
285 if first.kind != T![.] || second.kind != T![.] {
286 return None;
287 }
288
289 let third = self.token_source.lookahead_nth(n + 2);
290
291 let jn2 = second.is_jointed_to_next;
292 let la3 = third.kind;
293
294 if jn2 && la3 == T![.] {
295 return Some((T![...], 3));
296 }
297 if la3 == T![=] {
298 return Some((T![..=], 3));
299 }
300 return Some((T![..], 2));
301 }
302
303 fn eat_dollars(&mut self) {
304 loop {
305 match self.token_source.current().kind {
306 k @ SyntaxKind::L_DOLLAR | k @ SyntaxKind::R_DOLLAR => {
307 self.token_source.bump();
308 self.push_event(Event::Token { kind: k, n_raw_tokens: 1 });
309 }
310 _ => {
311 return;
312 }
313 }
314 }
315 }
316
317 pub(crate) fn eat_l_dollars(&mut self) -> usize {
318 let mut ate_count = 0;
319 loop {
320 match self.token_source.current().kind {
321 k @ SyntaxKind::L_DOLLAR => {
322 self.token_source.bump();
323 self.push_event(Event::Token { kind: k, n_raw_tokens: 1 });
324 ate_count += 1;
325 }
326 _ => {
327 return ate_count;
328 }
329 }
330 }
331 }
332
333 pub(crate) fn eat_r_dollars(&mut self, max_count: usize) -> usize {
334 let mut ate_count = 0;
335 loop {
336 match self.token_source.current().kind {
337 k @ SyntaxKind::R_DOLLAR => {
338 self.token_source.bump();
339 self.push_event(Event::Token { kind: k, n_raw_tokens: 1 });
340 ate_count += 1;
341
342 if max_count >= ate_count {
343 return ate_count;
344 }
345 }
346 _ => {
347 return ate_count;
348 }
349 }
350 }
351 }
352
353 pub(crate) fn at_l_dollar(&self) -> bool {
354 let kind = self.token_source.current().kind;
355 (kind == SyntaxKind::L_DOLLAR)
356 }
357
358 pub(crate) fn at_r_dollar(&self) -> bool {
359 let kind = self.token_source.current().kind;
360 (kind == SyntaxKind::R_DOLLAR)
361 }
362} 244}
363 245
364/// See `Parser::start`. 246/// See `Parser::start`.