diff options
Diffstat (limited to 'crates/ra_parser')
-rw-r--r-- | crates/ra_parser/Cargo.toml | 3 | ||||
-rw-r--r-- | crates/ra_parser/src/grammar/expressions.rs | 51 |
2 files changed, 24 insertions, 30 deletions
diff --git a/crates/ra_parser/Cargo.toml b/crates/ra_parser/Cargo.toml index b110e2bc6..0da581fd5 100644 --- a/crates/ra_parser/Cargo.toml +++ b/crates/ra_parser/Cargo.toml | |||
@@ -5,5 +5,8 @@ version = "0.1.0" | |||
5 | authors = ["rust-analyzer developers"] | 5 | authors = ["rust-analyzer developers"] |
6 | publish = false | 6 | publish = false |
7 | 7 | ||
8 | [lib] | ||
9 | doctest = false | ||
10 | |||
8 | [dependencies] | 11 | [dependencies] |
9 | drop_bomb = "0.1.4" | 12 | drop_bomb = "0.1.4" |
diff --git a/crates/ra_parser/src/grammar/expressions.rs b/crates/ra_parser/src/grammar/expressions.rs index 45f2e3de4..81d4f75f9 100644 --- a/crates/ra_parser/src/grammar/expressions.rs +++ b/crates/ra_parser/src/grammar/expressions.rs | |||
@@ -290,6 +290,22 @@ fn expr_bp(p: &mut Parser, r: Restrictions, bp: u8) -> (Option<CompletedMarker>, | |||
290 | let m = lhs.precede(p); | 290 | let m = lhs.precede(p); |
291 | p.bump(op); | 291 | p.bump(op); |
292 | 292 | ||
293 | if is_range { | ||
294 | // test postfix_range | ||
295 | // fn foo() { | ||
296 | // let x = 1..; | ||
297 | // match 1.. { _ => () }; | ||
298 | // match a.b()..S { _ => () }; | ||
299 | // } | ||
300 | let has_trailing_expression = | ||
301 | p.at_ts(EXPR_FIRST) && !(r.forbid_structs && p.at(T!['{'])); | ||
302 | if !has_trailing_expression { | ||
303 | // no RHS | ||
304 | lhs = m.complete(p, RANGE_EXPR); | ||
305 | break; | ||
306 | } | ||
307 | } | ||
308 | |||
293 | expr_bp(p, r, op_bp + 1); | 309 | expr_bp(p, r, op_bp + 1); |
294 | lhs = m.complete(p, if is_range { RANGE_EXPR } else { BIN_EXPR }); | 310 | lhs = m.complete(p, if is_range { RANGE_EXPR } else { BIN_EXPR }); |
295 | } | 311 | } |
@@ -330,7 +346,7 @@ fn lhs(p: &mut Parser, r: Restrictions) -> Option<(CompletedMarker, BlockLike)> | |||
330 | if p.at(op) { | 346 | if p.at(op) { |
331 | m = p.start(); | 347 | m = p.start(); |
332 | p.bump(op); | 348 | p.bump(op); |
333 | if p.at_ts(EXPR_FIRST) { | 349 | if p.at_ts(EXPR_FIRST) && !(r.forbid_structs && p.at(T!['{'])) { |
334 | expr_bp(p, r, 2); | 350 | expr_bp(p, r, 2); |
335 | } | 351 | } |
336 | return Some((m.complete(p, RANGE_EXPR), BlockLike::NotBlock)); | 352 | return Some((m.complete(p, RANGE_EXPR), BlockLike::NotBlock)); |
@@ -344,13 +360,7 @@ fn lhs(p: &mut Parser, r: Restrictions) -> Option<(CompletedMarker, BlockLike)> | |||
344 | // } | 360 | // } |
345 | // | 361 | // |
346 | let (lhs, blocklike) = atom::atom_expr(p, r)?; | 362 | let (lhs, blocklike) = atom::atom_expr(p, r)?; |
347 | return Some(postfix_expr( | 363 | return Some(postfix_expr(p, lhs, blocklike, !(r.prefer_stmt && blocklike.is_block()))); |
348 | p, | ||
349 | lhs, | ||
350 | blocklike, | ||
351 | !(r.prefer_stmt && blocklike.is_block()), | ||
352 | r.forbid_structs, | ||
353 | )); | ||
354 | } | 364 | } |
355 | }; | 365 | }; |
356 | // parse the interior of the unary expression | 366 | // parse the interior of the unary expression |
@@ -366,7 +376,6 @@ fn postfix_expr( | |||
366 | // `while true {break}; ();` | 376 | // `while true {break}; ();` |
367 | mut block_like: BlockLike, | 377 | mut block_like: BlockLike, |
368 | mut allow_calls: bool, | 378 | mut allow_calls: bool, |
369 | forbid_structs: bool, | ||
370 | ) -> (CompletedMarker, BlockLike) { | 379 | ) -> (CompletedMarker, BlockLike) { |
371 | loop { | 380 | loop { |
372 | lhs = match p.current() { | 381 | lhs = match p.current() { |
@@ -380,7 +389,7 @@ fn postfix_expr( | |||
380 | // } | 389 | // } |
381 | T!['('] if allow_calls => call_expr(p, lhs), | 390 | T!['('] if allow_calls => call_expr(p, lhs), |
382 | T!['['] if allow_calls => index_expr(p, lhs), | 391 | T!['['] if allow_calls => index_expr(p, lhs), |
383 | T![.] => match postfix_dot_expr(p, lhs, forbid_structs) { | 392 | T![.] => match postfix_dot_expr(p, lhs) { |
384 | Ok(it) => it, | 393 | Ok(it) => it, |
385 | Err(it) => { | 394 | Err(it) => { |
386 | lhs = it; | 395 | lhs = it; |
@@ -398,7 +407,6 @@ fn postfix_expr( | |||
398 | fn postfix_dot_expr( | 407 | fn postfix_dot_expr( |
399 | p: &mut Parser, | 408 | p: &mut Parser, |
400 | lhs: CompletedMarker, | 409 | lhs: CompletedMarker, |
401 | forbid_structs: bool, | ||
402 | ) -> Result<CompletedMarker, CompletedMarker> { | 410 | ) -> Result<CompletedMarker, CompletedMarker> { |
403 | assert!(p.at(T![.])); | 411 | assert!(p.at(T![.])); |
404 | if p.nth(1) == IDENT && (p.nth(2) == T!['('] || p.nth_at(2, T![::])) { | 412 | if p.nth(1) == IDENT && (p.nth(2) == T!['('] || p.nth_at(2, T![::])) { |
@@ -418,25 +426,8 @@ fn postfix_expr( | |||
418 | return Ok(m.complete(p, AWAIT_EXPR)); | 426 | return Ok(m.complete(p, AWAIT_EXPR)); |
419 | } | 427 | } |
420 | 428 | ||
421 | // test postfix_range | 429 | if p.at(T![..=]) || p.at(T![..]) { |
422 | // fn foo() { | 430 | return Err(lhs); |
423 | // let x = 1..; | ||
424 | // match 1.. { _ => () }; | ||
425 | // match a.b()..S { _ => () }; | ||
426 | // } | ||
427 | for &(op, la) in &[(T![..=], 3), (T![..], 2)] { | ||
428 | if p.at(op) { | ||
429 | let next_token = p.nth(la); | ||
430 | let has_trailing_expression = | ||
431 | !(forbid_structs && next_token == T!['{']) && EXPR_FIRST.contains(next_token); | ||
432 | return if has_trailing_expression { | ||
433 | Err(lhs) | ||
434 | } else { | ||
435 | let m = lhs.precede(p); | ||
436 | p.bump(op); | ||
437 | Ok(m.complete(p, RANGE_EXPR)) | ||
438 | }; | ||
439 | } | ||
440 | } | 431 | } |
441 | 432 | ||
442 | Ok(field_expr(p, lhs)) | 433 | Ok(field_expr(p, lhs)) |