@@ -379,7 +379,7 @@ fn postfix_expr(
379379 // }
380380 T ! [ '(' ] if allow_calls => call_expr ( p, lhs) ,
381381 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) {
383383 Ok ( it) => it,
384384 Err ( it) => {
385385 lhs = it;
@@ -393,35 +393,44 @@ fn postfix_expr(
393393 block_like = BlockLike :: NotBlock ;
394394 }
395395 return ( lhs, block_like) ;
396+ }
396397
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 {
401403 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 } ;
405407
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+ }
418411
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 ! [ . ] ) ;
421424 }
425+ p. bump ( T ! [ await ] ) ;
426+ return Ok ( m. complete ( p, AWAIT_EXPR ) ) ;
427+ }
422428
423- Ok ( field_expr ( p, lhs) )
429+ if p. at ( T ! [ ..=] ) || p. at ( T ! [ ..] ) {
430+ return Err ( lhs) ;
424431 }
432+
433+ field_expr :: < FLOAT_RECOVERY > ( p, lhs)
425434}
426435
427436// test call_expr
@@ -455,11 +464,22 @@ fn index_expr(p: &mut Parser<'_>, lhs: CompletedMarker) -> CompletedMarker {
455464// fn foo() {
456465// x.foo();
457466// y.bar::<T>(1, 2,);
467+ // x.0.0.call();
468+ // x.0. call();
458469// }
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+ }
461479 let m = lhs. precede ( p) ;
462- p. bump_any ( ) ;
480+ if !FLOAT_RECOVERY {
481+ p. bump ( T ! [ . ] ) ;
482+ }
463483 name_ref ( p) ;
464484 generic_args:: opt_generic_arg_list ( p, true ) ;
465485 if p. at ( T ! [ '(' ] ) {
@@ -472,21 +492,35 @@ fn method_call_expr(p: &mut Parser<'_>, lhs: CompletedMarker) -> CompletedMarker
472492// fn foo() {
473493// x.foo;
474494// x.0.bar;
495+ // x.0.1;
496+ // x.0. bar;
475497// x.0();
476498// }
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+ }
479506 let m = lhs. precede ( p) ;
480- p. bump ( T ! [ . ] ) ;
507+ if !FLOAT_RECOVERY {
508+ p. bump ( T ! [ . ] ) ;
509+ }
481510 if p. at ( IDENT ) || p. at ( INT_NUMBER ) {
482511 name_ref_or_index ( p) ;
483512 } 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+ } ;
486520 } else {
487521 p. error ( "expected field name or number" ) ;
488522 }
489- m. complete ( p, FIELD_EXPR )
523+ Ok ( m. complete ( p, FIELD_EXPR ) )
490524}
491525
492526// test try_expr
0 commit comments