diff options
Diffstat (limited to 'crates/ra_parser')
-rw-r--r-- | crates/ra_parser/src/grammar/items.rs | 2 | ||||
-rw-r--r-- | crates/ra_parser/src/parser.rs | 64 |
2 files changed, 61 insertions, 5 deletions
diff --git a/crates/ra_parser/src/grammar/items.rs b/crates/ra_parser/src/grammar/items.rs index 318fd69a1..97f8122a9 100644 --- a/crates/ra_parser/src/grammar/items.rs +++ b/crates/ra_parser/src/grammar/items.rs | |||
@@ -383,7 +383,7 @@ pub(crate) fn token_tree(p: &mut Parser) { | |||
383 | return; | 383 | return; |
384 | } | 384 | } |
385 | R_PAREN | R_BRACK => p.err_and_bump("unmatched brace"), | 385 | R_PAREN | R_BRACK => p.err_and_bump("unmatched brace"), |
386 | _ => p.bump(), | 386 | _ => p.bump_raw(), |
387 | } | 387 | } |
388 | } | 388 | } |
389 | p.expect(closing_paren_kind); | 389 | p.expect(closing_paren_kind); |
diff --git a/crates/ra_parser/src/parser.rs b/crates/ra_parser/src/parser.rs index 71f1f8b30..99b976c4f 100644 --- a/crates/ra_parser/src/parser.rs +++ b/crates/ra_parser/src/parser.rs | |||
@@ -85,8 +85,13 @@ impl<'t> Parser<'t> { | |||
85 | let mut i = 0; | 85 | let mut i = 0; |
86 | 86 | ||
87 | loop { | 87 | loop { |
88 | let kind = self.token_source.token_kind(self.token_pos + i); | 88 | let mut kind = self.token_source.token_kind(self.token_pos + i); |
89 | i += 1; | 89 | if let Some((composited, step)) = self.is_composite(kind, i) { |
90 | kind = composited; | ||
91 | i += step; | ||
92 | } else { | ||
93 | i += 1; | ||
94 | } | ||
90 | 95 | ||
91 | match kind { | 96 | match kind { |
92 | EOF => return EOF, | 97 | EOF => return EOF, |
@@ -121,13 +126,37 @@ impl<'t> Parser<'t> { | |||
121 | Marker::new(pos) | 126 | Marker::new(pos) |
122 | } | 127 | } |
123 | 128 | ||
124 | /// Advances the parser by one token unconditionally. | 129 | /// Advances the parser by one token unconditionally |
130 | /// Mainly use in `token_tree` parsing | ||
131 | pub(crate) fn bump_raw(&mut self) { | ||
132 | let kind = self.token_source.token_kind(self.token_pos); | ||
133 | if kind == EOF { | ||
134 | return; | ||
135 | } | ||
136 | self.do_bump(kind, 1); | ||
137 | } | ||
138 | |||
139 | /// Advances the parser by one token with composite puncts handled | ||
125 | pub(crate) fn bump(&mut self) { | 140 | pub(crate) fn bump(&mut self) { |
126 | let kind = self.nth(0); | 141 | let kind = self.nth(0); |
127 | if kind == EOF { | 142 | if kind == EOF { |
128 | return; | 143 | return; |
129 | } | 144 | } |
130 | self.do_bump(kind, 1); | 145 | |
146 | use SyntaxKind::*; | ||
147 | |||
148 | // Handle parser composites | ||
149 | match kind { | ||
150 | DOTDOTDOT | DOTDOTEQ => { | ||
151 | self.bump_compound(kind, 3); | ||
152 | } | ||
153 | DOTDOT | COLONCOLON | EQEQ | FAT_ARROW | NEQ | THIN_ARROW => { | ||
154 | self.bump_compound(kind, 2); | ||
155 | } | ||
156 | _ => { | ||
157 | self.do_bump(kind, 1); | ||
158 | } | ||
159 | } | ||
131 | } | 160 | } |
132 | 161 | ||
133 | /// Advances the parser by one token, remapping its kind. | 162 | /// Advances the parser by one token, remapping its kind. |
@@ -206,6 +235,33 @@ impl<'t> Parser<'t> { | |||
206 | self.events.push(event) | 235 | self.events.push(event) |
207 | } | 236 | } |
208 | 237 | ||
238 | /// helper function for check if it is composite. | ||
239 | fn is_composite(&self, kind: SyntaxKind, n: usize) -> Option<(SyntaxKind, usize)> { | ||
240 | // We assume the dollars will not occuried between | ||
241 | // mult-byte tokens | ||
242 | |||
243 | let jn1 = self.token_source.is_token_joint_to_next(self.token_pos + n); | ||
244 | let la2 = self.token_source.token_kind(self.token_pos + n + 1); | ||
245 | let jn2 = self.token_source.is_token_joint_to_next(self.token_pos + n + 1); | ||
246 | let la3 = self.token_source.token_kind(self.token_pos + n + 2); | ||
247 | |||
248 | use SyntaxKind::*; | ||
249 | |||
250 | match kind { | ||
251 | DOT if jn1 && la2 == DOT && jn2 && la3 == DOT => Some((DOTDOTDOT, 3)), | ||
252 | DOT if jn1 && la2 == DOT && la3 == EQ => Some((DOTDOTEQ, 3)), | ||
253 | DOT if jn1 && la2 == DOT => Some((DOTDOT, 2)), | ||
254 | |||
255 | COLON if jn1 && la2 == COLON => Some((COLONCOLON, 2)), | ||
256 | EQ if jn1 && la2 == EQ => Some((EQEQ, 2)), | ||
257 | EQ if jn1 && la2 == R_ANGLE => Some((FAT_ARROW, 2)), | ||
258 | |||
259 | EXCL if la2 == EQ => Some((NEQ, 2)), | ||
260 | MINUS if la2 == R_ANGLE => Some((THIN_ARROW, 2)), | ||
261 | _ => None, | ||
262 | } | ||
263 | } | ||
264 | |||
209 | fn eat_dollars(&mut self) { | 265 | fn eat_dollars(&mut self) { |
210 | loop { | 266 | loop { |
211 | match self.token_source.token_kind(self.token_pos) { | 267 | match self.token_source.token_kind(self.token_pos) { |