@@ -379,7 +379,7 @@ fn postfix_expr(
379
379
// }
380
380
T ! [ '(' ] if allow_calls => call_expr ( p, lhs) ,
381
381
T ! [ '[' ] if allow_calls => index_expr ( p, lhs) ,
382
- T ! [ . ] => match postfix_dot_expr ( p, lhs) {
382
+ T ! [ . ] => match postfix_dot_expr :: < false > ( p, lhs) {
383
383
Ok ( it) => it,
384
384
Err ( it) => {
385
385
lhs = it;
@@ -393,35 +393,44 @@ fn postfix_expr(
393
393
block_like = BlockLike :: NotBlock ;
394
394
}
395
395
return ( lhs, block_like) ;
396
+ }
396
397
397
- fn postfix_dot_expr (
398
- p : & mut Parser < ' _ > ,
399
- lhs : CompletedMarker ,
400
- ) -> Result < CompletedMarker , CompletedMarker > {
398
+ fn postfix_dot_expr < const FLOAT_RECOVERY : bool > (
399
+ p : & mut Parser < ' _ > ,
400
+ lhs : CompletedMarker ,
401
+ ) -> Result < CompletedMarker , CompletedMarker > {
402
+ if !FLOAT_RECOVERY {
401
403
assert ! ( p. at( T ![ . ] ) ) ;
402
- if p . nth ( 1 ) == IDENT && ( p . nth ( 2 ) == T ! [ '(' ] || p . nth_at ( 2 , T ! [ :: ] ) ) {
403
- return Ok ( method_call_expr ( p , lhs ) ) ;
404
- }
404
+ }
405
+ let nth1 = if FLOAT_RECOVERY { 0 } else { 1 } ;
406
+ let nth2 = if FLOAT_RECOVERY { 1 } else { 2 } ;
405
407
406
- // test await_expr
407
- // fn foo() {
408
- // x.await;
409
- // x.0.await;
410
- // x.0().await?.hello();
411
- // }
412
- if p. nth ( 1 ) == T ! [ await ] {
413
- let m = lhs. precede ( p) ;
414
- p. bump ( T ! [ . ] ) ;
415
- p. bump ( T ! [ await ] ) ;
416
- return Ok ( m. complete ( p, AWAIT_EXPR ) ) ;
417
- }
408
+ if p. nth ( nth1) == IDENT && ( p. nth ( nth2) == T ! [ '(' ] || p. nth_at ( nth2, T ! [ :: ] ) ) {
409
+ return Ok ( method_call_expr :: < FLOAT_RECOVERY > ( p, lhs) ) ;
410
+ }
418
411
419
- if p. at ( T ! [ ..=] ) || p. at ( T ! [ ..] ) {
420
- return Err ( lhs) ;
412
+ // test await_expr
413
+ // fn foo() {
414
+ // x.await;
415
+ // x.0.await;
416
+ // x.0().await?.hello();
417
+ // x.0.0.await;
418
+ // x.0. await;
419
+ // }
420
+ if p. nth ( nth1) == T ! [ await ] {
421
+ let m = lhs. precede ( p) ;
422
+ if !FLOAT_RECOVERY {
423
+ p. bump ( T ! [ . ] ) ;
421
424
}
425
+ p. bump ( T ! [ await ] ) ;
426
+ return Ok ( m. complete ( p, AWAIT_EXPR ) ) ;
427
+ }
422
428
423
- Ok ( field_expr ( p, lhs) )
429
+ if p. at ( T ! [ ..=] ) || p. at ( T ! [ ..] ) {
430
+ return Err ( lhs) ;
424
431
}
432
+
433
+ field_expr :: < FLOAT_RECOVERY > ( p, lhs)
425
434
}
426
435
427
436
// test call_expr
@@ -455,11 +464,22 @@ fn index_expr(p: &mut Parser<'_>, lhs: CompletedMarker) -> CompletedMarker {
455
464
// fn foo() {
456
465
// x.foo();
457
466
// y.bar::<T>(1, 2,);
467
+ // x.0.0.call();
468
+ // x.0. call();
458
469
// }
459
- fn method_call_expr ( p : & mut Parser < ' _ > , lhs : CompletedMarker ) -> CompletedMarker {
460
- assert ! ( p. at( T ![ . ] ) && p. nth( 1 ) == IDENT && ( p. nth( 2 ) == T ![ '(' ] || p. nth_at( 2 , T ![ :: ] ) ) ) ;
470
+ fn method_call_expr < const FLOAT_RECOVERY : bool > (
471
+ p : & mut Parser < ' _ > ,
472
+ lhs : CompletedMarker ,
473
+ ) -> CompletedMarker {
474
+ if FLOAT_RECOVERY {
475
+ assert ! ( p. nth( 0 ) == IDENT && ( p. nth( 1 ) == T ![ '(' ] || p. nth_at( 1 , T ![ :: ] ) ) ) ;
476
+ } else {
477
+ assert ! ( p. at( T ![ . ] ) && p. nth( 1 ) == IDENT && ( p. nth( 2 ) == T ![ '(' ] || p. nth_at( 2 , T ![ :: ] ) ) ) ;
478
+ }
461
479
let m = lhs. precede ( p) ;
462
- p. bump_any ( ) ;
480
+ if !FLOAT_RECOVERY {
481
+ p. bump ( T ! [ . ] ) ;
482
+ }
463
483
name_ref ( p) ;
464
484
generic_args:: opt_generic_arg_list ( p, true ) ;
465
485
if p. at ( T ! [ '(' ] ) {
@@ -472,21 +492,35 @@ fn method_call_expr(p: &mut Parser<'_>, lhs: CompletedMarker) -> CompletedMarker
472
492
// fn foo() {
473
493
// x.foo;
474
494
// x.0.bar;
495
+ // x.0.1;
496
+ // x.0. bar;
475
497
// x.0();
476
498
// }
477
- fn field_expr ( p : & mut Parser < ' _ > , lhs : CompletedMarker ) -> CompletedMarker {
478
- assert ! ( p. at( T ![ . ] ) ) ;
499
+ fn field_expr < const FLOAT_RECOVERY : bool > (
500
+ p : & mut Parser < ' _ > ,
501
+ lhs : CompletedMarker ,
502
+ ) -> Result < CompletedMarker , CompletedMarker > {
503
+ if !FLOAT_RECOVERY {
504
+ assert ! ( p. at( T ![ . ] ) ) ;
505
+ }
479
506
let m = lhs. precede ( p) ;
480
- p. bump ( T ! [ . ] ) ;
507
+ if !FLOAT_RECOVERY {
508
+ p. bump ( T ! [ . ] ) ;
509
+ }
481
510
if p. at ( IDENT ) || p. at ( INT_NUMBER ) {
482
511
name_ref_or_index ( p) ;
483
512
} else if p. at ( FLOAT_NUMBER ) {
484
- // FIXME: How to recover and instead parse INT + T![.]?
485
- p. bump_any ( ) ;
513
+ return match p. split_float ( m) {
514
+ ( true , m) => {
515
+ let lhs = m. complete ( p, FIELD_EXPR ) ;
516
+ postfix_dot_expr :: < true > ( p, lhs)
517
+ }
518
+ ( false , m) => Ok ( m. complete ( p, FIELD_EXPR ) ) ,
519
+ } ;
486
520
} else {
487
521
p. error ( "expected field name or number" ) ;
488
522
}
489
- m. complete ( p, FIELD_EXPR )
523
+ Ok ( m. complete ( p, FIELD_EXPR ) )
490
524
}
491
525
492
526
// test try_expr
0 commit comments