aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_parser/src/grammar
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_parser/src/grammar')
-rw-r--r--crates/ra_parser/src/grammar/expressions.rs245
-rw-r--r--crates/ra_parser/src/grammar/expressions/atom.rs25
-rw-r--r--crates/ra_parser/src/grammar/items.rs2
-rw-r--r--crates/ra_parser/src/grammar/items/use_item.rs24
-rw-r--r--crates/ra_parser/src/grammar/params.rs9
-rw-r--r--crates/ra_parser/src/grammar/paths.rs9
-rw-r--r--crates/ra_parser/src/grammar/patterns.rs33
-rw-r--r--crates/ra_parser/src/grammar/type_args.rs25
8 files changed, 193 insertions, 179 deletions
diff --git a/crates/ra_parser/src/grammar/expressions.rs b/crates/ra_parser/src/grammar/expressions.rs
index 30036eb46..1dd9a586c 100644
--- a/crates/ra_parser/src/grammar/expressions.rs
+++ b/crates/ra_parser/src/grammar/expressions.rs
@@ -14,20 +14,17 @@ const EXPR_FIRST: TokenSet = LHS_FIRST;
14 14
15pub(super) fn expr(p: &mut Parser) -> BlockLike { 15pub(super) fn expr(p: &mut Parser) -> BlockLike {
16 let r = Restrictions { forbid_structs: false, prefer_stmt: false }; 16 let r = Restrictions { forbid_structs: false, prefer_stmt: false };
17 let mut dollar_lvl = 0; 17 expr_bp(p, r, 1).1
18 expr_bp(p, r, 1, &mut dollar_lvl).1
19} 18}
20 19
21pub(super) fn expr_stmt(p: &mut Parser) -> (Option<CompletedMarker>, BlockLike) { 20pub(super) fn expr_stmt(p: &mut Parser) -> (Option<CompletedMarker>, BlockLike) {
22 let r = Restrictions { forbid_structs: false, prefer_stmt: true }; 21 let r = Restrictions { forbid_structs: false, prefer_stmt: true };
23 let mut dollar_lvl = 0; 22 expr_bp(p, r, 1)
24 expr_bp(p, r, 1, &mut dollar_lvl)
25} 23}
26 24
27fn expr_no_struct(p: &mut Parser) { 25fn expr_no_struct(p: &mut Parser) {
28 let r = Restrictions { forbid_structs: true, prefer_stmt: false }; 26 let r = Restrictions { forbid_structs: true, prefer_stmt: false };
29 let mut dollar_lvl = 0; 27 expr_bp(p, r, 1);
30 expr_bp(p, r, 1, &mut dollar_lvl);
31} 28}
32 29
33// test block 30// test block
@@ -212,72 +209,53 @@ struct Restrictions {
212 prefer_stmt: bool, 209 prefer_stmt: bool,
213} 210}
214 211
215enum Op { 212/// Binding powers of operators for a Pratt parser.
216 Simple, 213///
217 Composite(SyntaxKind, u8), 214/// See https://www.oilshell.org/blog/2016/11/03.html
218} 215#[rustfmt::skip]
219 216fn current_op(p: &Parser) -> (u8, SyntaxKind) {
220fn current_op(p: &Parser) -> (u8, Op) { 217 const NOT_AN_OP: (u8, SyntaxKind) = (0, T![@]);
221 if let Some(t) = p.current3() { 218 match p.current() {
222 match t { 219 T![|] if p.at(T![||]) => (3, T![||]),
223 (T![<], T![<], T![=]) => return (1, Op::Composite(T![<<=], 3)), 220 T![|] if p.at(T![|=]) => (1, T![|=]),
224 (T![>], T![>], T![=]) => return (1, Op::Composite(T![>>=], 3)), 221 T![|] => (6, T![|]),
225 _ => (), 222 T![>] if p.at(T![>>=]) => (1, T![>>=]),
226 } 223 T![>] if p.at(T![>>]) => (9, T![>>]),
227 } 224 T![>] if p.at(T![>=]) => (5, T![>=]),
228 225 T![>] => (5, T![>]),
229 if let Some(t) = p.current2() { 226 T![=] if p.at(T![=>]) => NOT_AN_OP,
230 match t { 227 T![=] if p.at(T![==]) => (5, T![==]),
231 (T![+], T![=]) => return (1, Op::Composite(T![+=], 2)), 228 T![=] => (1, T![=]),
232 (T![-], T![=]) => return (1, Op::Composite(T![-=], 2)), 229 T![<] if p.at(T![<=]) => (5, T![<=]),
233 (T![*], T![=]) => return (1, Op::Composite(T![*=], 2)), 230 T![<] if p.at(T![<<=]) => (1, T![<<=]),
234 (T![%], T![=]) => return (1, Op::Composite(T![%=], 2)), 231 T![<] if p.at(T![<<]) => (9, T![<<]),
235 (T![/], T![=]) => return (1, Op::Composite(T![/=], 2)), 232 T![<] => (5, T![<]),
236 (T![|], T![=]) => return (1, Op::Composite(T![|=], 2)), 233 T![+] if p.at(T![+=]) => (1, T![+=]),
237 (T![&], T![=]) => return (1, Op::Composite(T![&=], 2)), 234 T![+] => (10, T![+]),
238 (T![^], T![=]) => return (1, Op::Composite(T![^=], 2)), 235 T![^] if p.at(T![^=]) => (1, T![^=]),
239 (T![|], T![|]) => return (3, Op::Composite(T![||], 2)), 236 T![^] => (7, T![^]),
240 (T![&], T![&]) => return (4, Op::Composite(T![&&], 2)), 237 T![%] if p.at(T![%=]) => (1, T![%=]),
241 (T![<], T![=]) => return (5, Op::Composite(T![<=], 2)), 238 T![%] => (11, T![%]),
242 (T![>], T![=]) => return (5, Op::Composite(T![>=], 2)), 239 T![&] if p.at(T![&=]) => (1, T![&=]),
243 (T![<], T![<]) => return (9, Op::Composite(T![<<], 2)), 240 T![&] if p.at(T![&&]) => (4, T![&&]),
244 (T![>], T![>]) => return (9, Op::Composite(T![>>], 2)), 241 T![&] => (8, T![&]),
245 _ => (), 242 T![/] if p.at(T![/=]) => (1, T![/=]),
246 } 243 T![/] => (11, T![/]),
244 T![*] if p.at(T![*=]) => (1, T![*=]),
245 T![*] => (11, T![*]),
246 T![.] if p.at(T![..=]) => (2, T![..=]),
247 T![.] if p.at(T![..]) => (2, T![..]),
248 T![!] if p.at(T![!=]) => (5, T![!=]),
249 T![-] if p.at(T![-=]) => (1, T![-=]),
250 T![-] => (10, T![-]),
251
252 _ => NOT_AN_OP
247 } 253 }
248
249 let bp = match p.current() {
250 T![=] => 1,
251 T![..] | T![..=] => 2,
252 T![==] | T![!=] | T![<] | T![>] => 5,
253 T![|] => 6,
254 T![^] => 7,
255 T![&] => 8,
256 T![-] | T![+] => 10,
257 T![*] | T![/] | T![%] => 11,
258 _ => 0,
259 };
260 (bp, Op::Simple)
261} 254}
262 255
263// Parses expression with binding power of at least bp. 256// Parses expression with binding power of at least bp.
264fn expr_bp( 257fn expr_bp(p: &mut Parser, r: Restrictions, bp: u8) -> (Option<CompletedMarker>, BlockLike) {
265 p: &mut Parser, 258 let mut lhs = match lhs(p, r) {
266 r: Restrictions,
267 mut bp: u8,
268 dollar_lvl: &mut usize,
269) -> (Option<CompletedMarker>, BlockLike) {
270 // `newly_dollar_open` is a flag indicated that dollar is just closed after lhs, e.g.
271 // `$1$ + a`
272 // We use this flag to skip handling it.
273 let mut newly_dollar_open = if p.at_l_dollar() {
274 *dollar_lvl += p.eat_l_dollars();
275 true
276 } else {
277 false
278 };
279
280 let mut lhs = match lhs(p, r, dollar_lvl) {
281 Some((lhs, blocklike)) => { 259 Some((lhs, blocklike)) => {
282 // test stmt_bin_expr_ambiguity 260 // test stmt_bin_expr_ambiguity
283 // fn foo() { 261 // fn foo() {
@@ -293,42 +271,23 @@ fn expr_bp(
293 }; 271 };
294 272
295 loop { 273 loop {
296 if *dollar_lvl > 0 && p.at_r_dollar() {
297 *dollar_lvl -= p.eat_r_dollars(*dollar_lvl);
298 if !newly_dollar_open {
299 // We "pump" bp for make it highest priority
300 bp = 255;
301 }
302 newly_dollar_open = false;
303 }
304
305 let is_range = p.at(T![..]) || p.at(T![..=]); 274 let is_range = p.at(T![..]) || p.at(T![..=]);
306 let (op_bp, op) = current_op(p); 275 let (op_bp, op) = current_op(p);
307 if op_bp < bp { 276 if op_bp < bp {
308 break; 277 break;
309 } 278 }
310 let m = lhs.precede(p); 279 let m = lhs.precede(p);
311 match op { 280 p.bump(op);
312 Op::Simple => p.bump_any(),
313 Op::Composite(kind, n) => {
314 p.bump_compound(kind, n);
315 }
316 }
317 281
318 expr_bp(p, r, op_bp + 1, dollar_lvl); 282 expr_bp(p, r, op_bp + 1);
319 lhs = m.complete(p, if is_range { RANGE_EXPR } else { BIN_EXPR }); 283 lhs = m.complete(p, if is_range { RANGE_EXPR } else { BIN_EXPR });
320 } 284 }
321 (Some(lhs), BlockLike::NotBlock) 285 (Some(lhs), BlockLike::NotBlock)
322} 286}
323 287
324const LHS_FIRST: TokenSet = 288const LHS_FIRST: TokenSet = atom::ATOM_EXPR_FIRST.union(token_set![AMP, STAR, EXCL, DOT, MINUS]);
325 atom::ATOM_EXPR_FIRST.union(token_set![AMP, STAR, EXCL, DOTDOT, DOTDOTEQ, MINUS]);
326 289
327fn lhs( 290fn lhs(p: &mut Parser, r: Restrictions) -> Option<(CompletedMarker, BlockLike)> {
328 p: &mut Parser,
329 r: Restrictions,
330 dollar_lvl: &mut usize,
331) -> Option<(CompletedMarker, BlockLike)> {
332 let m; 291 let m;
333 let kind = match p.current() { 292 let kind = match p.current() {
334 // test ref_expr 293 // test ref_expr
@@ -353,17 +312,20 @@ fn lhs(
353 p.bump_any(); 312 p.bump_any();
354 PREFIX_EXPR 313 PREFIX_EXPR
355 } 314 }
356 // test full_range_expr
357 // fn foo() { xs[..]; }
358 T![..] | T![..=] => {
359 m = p.start();
360 p.bump_any();
361 if p.at_ts(EXPR_FIRST) {
362 expr_bp(p, r, 2, dollar_lvl);
363 }
364 return Some((m.complete(p, RANGE_EXPR), BlockLike::NotBlock));
365 }
366 _ => { 315 _ => {
316 // test full_range_expr
317 // fn foo() { xs[..]; }
318 for &op in [T![..=], T![..]].iter() {
319 if p.at(op) {
320 m = p.start();
321 p.bump(op);
322 if p.at_ts(EXPR_FIRST) {
323 expr_bp(p, r, 2);
324 }
325 return Some((m.complete(p, RANGE_EXPR), BlockLike::NotBlock));
326 }
327 }
328
367 // test expression_after_block 329 // test expression_after_block
368 // fn foo() { 330 // fn foo() {
369 // let mut p = F{x: 5}; 331 // let mut p = F{x: 5};
@@ -374,7 +336,7 @@ fn lhs(
374 return Some(postfix_expr(p, lhs, blocklike, !(r.prefer_stmt && blocklike.is_block()))); 336 return Some(postfix_expr(p, lhs, blocklike, !(r.prefer_stmt && blocklike.is_block())));
375 } 337 }
376 }; 338 };
377 expr_bp(p, r, 255, dollar_lvl); 339 expr_bp(p, r, 255);
378 Some((m.complete(p, kind), BlockLike::NotBlock)) 340 Some((m.complete(p, kind), BlockLike::NotBlock))
379} 341}
380 342
@@ -399,29 +361,13 @@ fn postfix_expr(
399 // } 361 // }
400 T!['('] if allow_calls => call_expr(p, lhs), 362 T!['('] if allow_calls => call_expr(p, lhs),
401 T!['['] if allow_calls => index_expr(p, lhs), 363 T!['['] if allow_calls => index_expr(p, lhs),
402 T![.] if p.nth(1) == IDENT && (p.nth(2) == T!['('] || p.nth(2) == T![::]) => { 364 T![.] => match postfix_dot_expr(p, lhs) {
403 method_call_expr(p, lhs) 365 Ok(it) => it,
404 } 366 Err(it) => {
405 T![.] if p.nth(1) == AWAIT_KW => { 367 lhs = it;
406 // test await_expr 368 break;
407 // fn foo() { 369 }
408 // x.await; 370 },
409 // x.0.await;
410 // x.0().await?.hello();
411 // }
412 let m = lhs.precede(p);
413 p.bump_any();
414 p.bump_any();
415 m.complete(p, AWAIT_EXPR)
416 }
417 T![.] => field_expr(p, lhs),
418 // test postfix_range
419 // fn foo() { let x = 1..; }
420 T![..] | T![..=] if !EXPR_FIRST.contains(p.nth(1)) => {
421 let m = lhs.precede(p);
422 p.bump_any();
423 m.complete(p, RANGE_EXPR)
424 }
425 T![?] => try_expr(p, lhs), 371 T![?] => try_expr(p, lhs),
426 T![as] => cast_expr(p, lhs), 372 T![as] => cast_expr(p, lhs),
427 _ => break, 373 _ => break,
@@ -429,7 +375,46 @@ fn postfix_expr(
429 allow_calls = true; 375 allow_calls = true;
430 block_like = BlockLike::NotBlock; 376 block_like = BlockLike::NotBlock;
431 } 377 }
432 (lhs, block_like) 378 return (lhs, block_like);
379
380 fn postfix_dot_expr(
381 p: &mut Parser,
382 lhs: CompletedMarker,
383 ) -> Result<CompletedMarker, CompletedMarker> {
384 assert!(p.at(T![.]));
385 if p.nth(1) == IDENT && (p.nth(2) == T!['('] || p.nth_at(2, T![::])) {
386 return Ok(method_call_expr(p, lhs));
387 }
388
389 // test await_expr
390 // fn foo() {
391 // x.await;
392 // x.0.await;
393 // x.0().await?.hello();
394 // }
395 if p.nth(1) == T![await] {
396 let m = lhs.precede(p);
397 p.bump(T![.]);
398 p.bump(T![await]);
399 return Ok(m.complete(p, AWAIT_EXPR));
400 }
401
402 // test postfix_range
403 // fn foo() { let x = 1..; }
404 for &(op, la) in [(T![..=], 3), (T![..], 2)].iter() {
405 if p.at(op) {
406 return if EXPR_FIRST.contains(p.nth(la)) {
407 Err(lhs)
408 } else {
409 let m = lhs.precede(p);
410 p.bump(op);
411 Ok(m.complete(p, RANGE_EXPR))
412 };
413 }
414 }
415
416 Ok(field_expr(p, lhs))
417 }
433} 418}
434 419
435// test call_expr 420// test call_expr
@@ -465,7 +450,7 @@ fn index_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
465// y.bar::<T>(1, 2,); 450// y.bar::<T>(1, 2,);
466// } 451// }
467fn method_call_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker { 452fn method_call_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
468 assert!(p.at(T![.]) && p.nth(1) == IDENT && (p.nth(2) == T!['('] || p.nth(2) == T![::])); 453 assert!(p.at(T![.]) && p.nth(1) == IDENT && (p.nth(2) == T!['('] || p.nth_at(2, T![::])));
469 let m = lhs.precede(p); 454 let m = lhs.precede(p);
470 p.bump_any(); 455 p.bump_any();
471 name_ref(p); 456 name_ref(p);
@@ -567,7 +552,7 @@ fn path_expr(p: &mut Parser, r: Restrictions) -> (CompletedMarker, BlockLike) {
567 record_field_list(p); 552 record_field_list(p);
568 (m.complete(p, RECORD_LIT), BlockLike::NotBlock) 553 (m.complete(p, RECORD_LIT), BlockLike::NotBlock)
569 } 554 }
570 T![!] => { 555 T![!] if !p.at(T![!=]) => {
571 let block_like = items::macro_call_after_excl(p); 556 let block_like = items::macro_call_after_excl(p);
572 (m.complete(p, MACRO_CALL), block_like) 557 (m.complete(p, MACRO_CALL), block_like)
573 } 558 }
@@ -601,8 +586,8 @@ pub(crate) fn record_field_list(p: &mut Parser) {
601 } 586 }
602 m.complete(p, RECORD_FIELD); 587 m.complete(p, RECORD_FIELD);
603 } 588 }
604 T![..] => { 589 T![.] if p.at(T![..]) => {
605 p.bump_any(); 590 p.bump(T![..]);
606 expr(p); 591 expr(p);
607 } 592 }
608 T!['{'] => error_block(p, "expected a field"), 593 T!['{'] => error_block(p, "expected a field"),
diff --git a/crates/ra_parser/src/grammar/expressions/atom.rs b/crates/ra_parser/src/grammar/expressions/atom.rs
index cea79cf6f..6e295fbf9 100644
--- a/crates/ra_parser/src/grammar/expressions/atom.rs
+++ b/crates/ra_parser/src/grammar/expressions/atom.rs
@@ -69,6 +69,7 @@ pub(super) fn atom_expr(p: &mut Parser, r: Restrictions) -> Option<(CompletedMar
69 let done = match p.current() { 69 let done = match p.current() {
70 T!['('] => tuple_expr(p), 70 T!['('] => tuple_expr(p),
71 T!['['] => array_expr(p), 71 T!['['] => array_expr(p),
72 L_DOLLAR => meta_var_expr(p),
72 T![|] => lambda_expr(p), 73 T![|] => lambda_expr(p),
73 T![move] if la == T![|] => lambda_expr(p), 74 T![move] if la == T![|] => lambda_expr(p),
74 T![async] if la == T![|] || (la == T![move] && p.nth(2) == T![|]) => lambda_expr(p), 75 T![async] if la == T![|] || (la == T![move] && p.nth(2) == T![|]) => lambda_expr(p),
@@ -554,3 +555,27 @@ fn box_expr(p: &mut Parser, m: Option<Marker>) -> CompletedMarker {
554 } 555 }
555 m.complete(p, BOX_EXPR) 556 m.complete(p, BOX_EXPR)
556} 557}
558
559/// Expression from `$var` macro expansion, wrapped in dollars
560fn meta_var_expr(p: &mut Parser) -> CompletedMarker {
561 assert!(p.at(L_DOLLAR));
562 let m = p.start();
563 p.bump(L_DOLLAR);
564 let (completed, _is_block) =
565 expr_bp(p, Restrictions { forbid_structs: false, prefer_stmt: false }, 1);
566
567 match (completed, p.current()) {
568 (Some(it), R_DOLLAR) => {
569 p.bump(R_DOLLAR);
570 m.abandon(p);
571 it
572 }
573 _ => {
574 while !p.at(R_DOLLAR) {
575 p.bump_any()
576 }
577 p.bump(R_DOLLAR);
578 m.complete(p, ERROR)
579 }
580 }
581}
diff --git a/crates/ra_parser/src/grammar/items.rs b/crates/ra_parser/src/grammar/items.rs
index f27cc85ff..eff9d67e4 100644
--- a/crates/ra_parser/src/grammar/items.rs
+++ b/crates/ra_parser/src/grammar/items.rs
@@ -422,7 +422,7 @@ pub(crate) fn token_tree(p: &mut Parser) {
422 return; 422 return;
423 } 423 }
424 T![')'] | T![']'] => p.err_and_bump("unmatched brace"), 424 T![')'] | T![']'] => p.err_and_bump("unmatched brace"),
425 _ => p.bump_raw(), 425 _ => p.bump_any(),
426 } 426 }
427 } 427 }
428 p.expect(closing_paren_kind); 428 p.expect(closing_paren_kind);
diff --git a/crates/ra_parser/src/grammar/items/use_item.rs b/crates/ra_parser/src/grammar/items/use_item.rs
index 7a1693a34..f28f522b8 100644
--- a/crates/ra_parser/src/grammar/items/use_item.rs
+++ b/crates/ra_parser/src/grammar/items/use_item.rs
@@ -13,9 +13,8 @@ pub(super) fn use_item(p: &mut Parser, m: Marker) {
13/// so handles both `some::path::{inner::path}` and `inner::path` in 13/// so handles both `some::path::{inner::path}` and `inner::path` in
14/// `use some::path::{inner::path};` 14/// `use some::path::{inner::path};`
15fn use_tree(p: &mut Parser) { 15fn use_tree(p: &mut Parser) {
16 let la = p.nth(1);
17 let m = p.start(); 16 let m = p.start();
18 match (p.current(), la) { 17 match p.current() {
19 // Finish the use_tree for cases of e.g. 18 // Finish the use_tree for cases of e.g.
20 // `use some::path::{self, *};` or `use *;` 19 // `use some::path::{self, *};` or `use *;`
21 // This does not handle cases such as `use some::path::*` 20 // This does not handle cases such as `use some::path::*`
@@ -28,15 +27,15 @@ fn use_tree(p: &mut Parser) {
28 // use ::*; 27 // use ::*;
29 // use some::path::{*}; 28 // use some::path::{*};
30 // use some::path::{::*}; 29 // use some::path::{::*};
31 (T![*], _) => p.bump_any(), 30 T![*] => p.bump(T![*]),
32 (T![::], T![*]) => { 31 T![:] if p.at(T![::]) && p.nth(2) == T![*] => {
33 // Parse `use ::*;`, which imports all from the crate root in Rust 2015 32 // Parse `use ::*;`, which imports all from the crate root in Rust 2015
34 // This is invalid inside a use_tree_list, (e.g. `use some::path::{::*}`) 33 // This is invalid inside a use_tree_list, (e.g. `use some::path::{::*}`)
35 // but still parses and errors later: ('crate root in paths can only be used in start position') 34 // but still parses and errors later: ('crate root in paths can only be used in start position')
36 // FIXME: Add this error (if not out of scope) 35 // FIXME: Add this error (if not out of scope)
37 // In Rust 2018, it is always invalid (see above) 36 // In Rust 2018, it is always invalid (see above)
38 p.bump_any(); 37 p.bump(T![::]);
39 p.bump_any(); 38 p.bump(T![*]);
40 } 39 }
41 // Open a use tree list 40 // Open a use tree list
42 // Handles cases such as `use {some::path};` or `{inner::path}` in 41 // Handles cases such as `use {some::path};` or `{inner::path}` in
@@ -47,10 +46,11 @@ fn use_tree(p: &mut Parser) {
47 // use {path::from::root}; // Rust 2015 46 // use {path::from::root}; // Rust 2015
48 // use ::{some::arbritrary::path}; // Rust 2015 47 // use ::{some::arbritrary::path}; // Rust 2015
49 // use ::{{{crate::export}}}; // Nonsensical but perfectly legal nestnig 48 // use ::{{{crate::export}}}; // Nonsensical but perfectly legal nestnig
50 (T!['{'], _) | (T![::], T!['{']) => { 49 T!['{'] => {
51 if p.at(T![::]) { 50 use_tree_list(p);
52 p.bump_any(); 51 }
53 } 52 T![:] if p.at(T![::]) && p.nth(2) == T!['{'] => {
53 p.bump(T![::]);
54 use_tree_list(p); 54 use_tree_list(p);
55 } 55 }
56 // Parse a 'standard' path. 56 // Parse a 'standard' path.
@@ -80,8 +80,8 @@ fn use_tree(p: &mut Parser) {
80 // use Trait as _; 80 // use Trait as _;
81 opt_alias(p); 81 opt_alias(p);
82 } 82 }
83 T![::] => { 83 T![:] if p.at(T![::]) => {
84 p.bump_any(); 84 p.bump(T![::]);
85 match p.current() { 85 match p.current() {
86 T![*] => { 86 T![*] => {
87 p.bump_any(); 87 p.bump_any();
diff --git a/crates/ra_parser/src/grammar/params.rs b/crates/ra_parser/src/grammar/params.rs
index 56e457325..5893b22fd 100644
--- a/crates/ra_parser/src/grammar/params.rs
+++ b/crates/ra_parser/src/grammar/params.rs
@@ -80,7 +80,7 @@ fn value_parameter(p: &mut Parser, flavor: Flavor) {
80 match flavor { 80 match flavor {
81 Flavor::OptionalType | Flavor::Normal => { 81 Flavor::OptionalType | Flavor::Normal => {
82 patterns::pattern(p); 82 patterns::pattern(p);
83 if p.at(T![:]) || flavor.type_required() { 83 if p.at(T![:]) && !p.at(T![::]) || flavor.type_required() {
84 types::ascription(p) 84 types::ascription(p)
85 } 85 }
86 } 86 }
@@ -96,10 +96,11 @@ fn value_parameter(p: &mut Parser, flavor: Flavor) {
96 // trait Foo { 96 // trait Foo {
97 // fn bar(_: u64, mut x: i32); 97 // fn bar(_: u64, mut x: i32);
98 // } 98 // }
99 if (la0 == IDENT || la0 == T![_]) && la1 == T![:] 99 if (la0 == IDENT || la0 == T![_]) && la1 == T![:] && !p.nth_at(1, T![::])
100 || la0 == T![mut] && la1 == IDENT && la2 == T![:] 100 || la0 == T![mut] && la1 == IDENT && la2 == T![:]
101 || la0 == T![&] && la1 == IDENT && la2 == T![:] 101 || la0 == T![&]
102 || la0 == T![&] && la1 == T![mut] && la2 == IDENT && la3 == T![:] 102 && (la1 == IDENT && la2 == T![:] && !p.nth_at(2, T![::])
103 || la1 == T![mut] && la2 == IDENT && la3 == T![:] && !p.nth_at(3, T![::]))
103 { 104 {
104 patterns::pattern(p); 105 patterns::pattern(p);
105 types::ascription(p); 106 types::ascription(p);
diff --git a/crates/ra_parser/src/grammar/paths.rs b/crates/ra_parser/src/grammar/paths.rs
index 345c93f55..24b65128e 100644
--- a/crates/ra_parser/src/grammar/paths.rs
+++ b/crates/ra_parser/src/grammar/paths.rs
@@ -1,7 +1,7 @@
1use super::*; 1use super::*;
2 2
3pub(super) const PATH_FIRST: TokenSet = 3pub(super) const PATH_FIRST: TokenSet =
4 token_set![IDENT, SELF_KW, SUPER_KW, CRATE_KW, COLONCOLON, L_ANGLE]; 4 token_set![IDENT, SELF_KW, SUPER_KW, CRATE_KW, COLON, L_ANGLE];
5 5
6pub(super) fn is_path_start(p: &Parser) -> bool { 6pub(super) fn is_path_start(p: &Parser) -> bool {
7 is_use_path_start(p) || p.at(T![<]) 7 is_use_path_start(p) || p.at(T![<])
@@ -9,7 +9,8 @@ pub(super) fn is_path_start(p: &Parser) -> bool {
9 9
10pub(super) fn is_use_path_start(p: &Parser) -> bool { 10pub(super) fn is_use_path_start(p: &Parser) -> bool {
11 match p.current() { 11 match p.current() {
12 IDENT | T![self] | T![super] | T![crate] | T![::] => true, 12 IDENT | T![self] | T![super] | T![crate] => true,
13 T![:] if p.at(T![::]) => true,
13 _ => false, 14 _ => false,
14 } 15 }
15} 16}
@@ -38,13 +39,13 @@ fn path(p: &mut Parser, mode: Mode) {
38 path_segment(p, mode, true); 39 path_segment(p, mode, true);
39 let mut qual = path.complete(p, PATH); 40 let mut qual = path.complete(p, PATH);
40 loop { 41 loop {
41 let use_tree = match p.nth(1) { 42 let use_tree = match p.nth(2) {
42 T![*] | T!['{'] => true, 43 T![*] | T!['{'] => true,
43 _ => false, 44 _ => false,
44 }; 45 };
45 if p.at(T![::]) && !use_tree { 46 if p.at(T![::]) && !use_tree {
46 let path = qual.precede(p); 47 let path = qual.precede(p);
47 p.bump_any(); 48 p.bump(T![::]);
48 path_segment(p, mode, false); 49 path_segment(p, mode, false);
49 let path = path.complete(p, PATH); 50 let path = path.complete(p, PATH);
50 qual = path; 51 qual = path;
diff --git a/crates/ra_parser/src/grammar/patterns.rs b/crates/ra_parser/src/grammar/patterns.rs
index d2f4296f8..dd1d25b07 100644
--- a/crates/ra_parser/src/grammar/patterns.rs
+++ b/crates/ra_parser/src/grammar/patterns.rs
@@ -34,17 +34,20 @@ pub(super) fn pattern_r(p: &mut Parser, recovery_set: TokenSet) {
34 // 200 .. 301=> (), 34 // 200 .. 301=> (),
35 // } 35 // }
36 // } 36 // }
37 if p.at(T![...]) || p.at(T![..=]) || p.at(T![..]) { 37 for &range_op in [T![...], T![..=], T![..]].iter() {
38 let m = lhs.precede(p); 38 if p.at(range_op) {
39 p.bump_any(); 39 let m = lhs.precede(p);
40 atom_pat(p, recovery_set); 40 p.bump(range_op);
41 m.complete(p, RANGE_PAT); 41 atom_pat(p, recovery_set);
42 m.complete(p, RANGE_PAT);
43 return;
44 }
42 } 45 }
43 // test marco_pat 46 // test marco_pat
44 // fn main() { 47 // fn main() {
45 // let m!(x) = 0; 48 // let m!(x) = 0;
46 // } 49 // }
47 else if lhs.kind() == PATH_PAT && p.at(T![!]) { 50 if lhs.kind() == PATH_PAT && p.at(T![!]) {
48 let m = lhs.precede(p); 51 let m = lhs.precede(p);
49 items::macro_call_after_excl(p); 52 items::macro_call_after_excl(p);
50 m.complete(p, MACRO_CALL); 53 m.complete(p, MACRO_CALL);
@@ -56,14 +59,16 @@ const PAT_RECOVERY_SET: TokenSet =
56 token_set![LET_KW, IF_KW, WHILE_KW, LOOP_KW, MATCH_KW, R_PAREN, COMMA]; 59 token_set![LET_KW, IF_KW, WHILE_KW, LOOP_KW, MATCH_KW, R_PAREN, COMMA];
57 60
58fn atom_pat(p: &mut Parser, recovery_set: TokenSet) -> Option<CompletedMarker> { 61fn atom_pat(p: &mut Parser, recovery_set: TokenSet) -> Option<CompletedMarker> {
59 // Checks the token after an IDENT to see if a pattern is a path (Struct { .. }) or macro
60 // (T![x]).
61 let is_path_or_macro_pat =
62 |la1| la1 == T![::] || la1 == T!['('] || la1 == T!['{'] || la1 == T![!];
63
64 let m = match p.nth(0) { 62 let m = match p.nth(0) {
65 T![box] => box_pat(p), 63 T![box] => box_pat(p),
66 T![ref] | T![mut] | IDENT if !is_path_or_macro_pat(p.nth(1)) => bind_pat(p, true), 64 T![ref] | T![mut] => bind_pat(p, true),
65 IDENT => match p.nth(1) {
66 // Checks the token after an IDENT to see if a pattern is a path (Struct { .. }) or macro
67 // (T![x]).
68 T!['('] | T!['{'] | T![!] => path_pat(p),
69 T![:] if p.nth_at(1, T![::]) => path_pat(p),
70 _ => bind_pat(p, true),
71 },
67 72
68 _ if paths::is_use_path_start(p) => path_pat(p), 73 _ if paths::is_use_path_start(p) => path_pat(p),
69 _ if is_literal_pat_start(p) => literal_pat(p), 74 _ if is_literal_pat_start(p) => literal_pat(p),
@@ -158,7 +163,7 @@ fn record_field_pat_list(p: &mut Parser) {
158 p.bump_any(); 163 p.bump_any();
159 while !p.at(EOF) && !p.at(T!['}']) { 164 while !p.at(EOF) && !p.at(T!['}']) {
160 match p.current() { 165 match p.current() {
161 T![..] => p.bump_any(), 166 T![.] if p.at(T![..]) => p.bump(T![..]),
162 IDENT if p.nth(1) == T![:] => record_field_pat(p), 167 IDENT if p.nth(1) == T![:] => record_field_pat(p),
163 T!['{'] => error_block(p, "expected ident"), 168 T!['{'] => error_block(p, "expected ident"),
164 T![box] => { 169 T![box] => {
@@ -237,7 +242,7 @@ fn slice_pat(p: &mut Parser) -> CompletedMarker {
237fn pat_list(p: &mut Parser, ket: SyntaxKind) { 242fn pat_list(p: &mut Parser, ket: SyntaxKind) {
238 while !p.at(EOF) && !p.at(ket) { 243 while !p.at(EOF) && !p.at(ket) {
239 match p.current() { 244 match p.current() {
240 T![..] => p.bump_any(), 245 T![.] if p.at(T![..]) => p.bump(T![..]),
241 _ => { 246 _ => {
242 if !p.at_ts(PATTERN_FIRST) { 247 if !p.at_ts(PATTERN_FIRST) {
243 p.error("expected a pattern"); 248 p.error("expected a pattern");
diff --git a/crates/ra_parser/src/grammar/type_args.rs b/crates/ra_parser/src/grammar/type_args.rs
index e100af531..edc7d4ff2 100644
--- a/crates/ra_parser/src/grammar/type_args.rs
+++ b/crates/ra_parser/src/grammar/type_args.rs
@@ -2,19 +2,16 @@ use super::*;
2 2
3pub(super) fn opt_type_arg_list(p: &mut Parser, colon_colon_required: bool) { 3pub(super) fn opt_type_arg_list(p: &mut Parser, colon_colon_required: bool) {
4 let m; 4 let m;
5 match (colon_colon_required, p.nth(0), p.nth(1)) { 5 if p.at(T![::]) && p.nth(2) == T![<] {
6 (_, T![::], T![<]) => { 6 m = p.start();
7 m = p.start(); 7 p.bump(T![::]);
8 p.bump_any(); 8 p.bump(T![<]);
9 p.bump_any(); 9 } else if !colon_colon_required && p.at(T![<]) && p.nth(1) != T![=] {
10 } 10 m = p.start();
11 (false, T![<], T![=]) => return, 11 p.bump(T![<]);
12 (false, T![<], _) => { 12 } else {
13 m = p.start(); 13 return;
14 p.bump_any(); 14 }
15 }
16 _ => return,
17 };
18 15
19 while !p.at(EOF) && !p.at(T![>]) { 16 while !p.at(EOF) && !p.at(T![>]) {
20 type_arg(p); 17 type_arg(p);
@@ -37,7 +34,7 @@ fn type_arg(p: &mut Parser) {
37 } 34 }
38 // test associated_type_bounds 35 // test associated_type_bounds
39 // fn print_all<T: Iterator<Item: Display>>(printables: T) {} 36 // fn print_all<T: Iterator<Item: Display>>(printables: T) {}
40 IDENT if p.nth(1) == T![:] => { 37 IDENT if p.nth(1) == T![:] && p.nth(2) != T![:] => {
41 name_ref(p); 38 name_ref(p);
42 type_params::bounds(p); 39 type_params::bounds(p);
43 m.complete(p, ASSOC_TYPE_ARG); 40 m.complete(p, ASSOC_TYPE_ARG);