aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_parser
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_parser')
-rw-r--r--crates/ra_parser/src/grammar/items.rs2
-rw-r--r--crates/ra_parser/src/parser.rs64
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) {