@@ -91,6 +91,18 @@ impl From<P<Expr>> for LhsExpr {
9191 }
9292}
9393
94+ #[ derive( Debug ) ]
95+ enum DestructuredFloat {
96+ /// 1e2
97+ Single ( Symbol , Span ) ,
98+ /// 1.
99+ TrailingDot ( Symbol , Span , Span ) ,
100+ /// 1.2 | 1.2e3
101+ MiddleDot ( Symbol , Span , Span , Symbol , Span ) ,
102+ /// Invalid
103+ Error ,
104+ }
105+
94106impl < ' a > Parser < ' a > {
95107 /// Parses an expression.
96108 #[ inline]
@@ -1013,13 +1025,8 @@ impl<'a> Parser<'a> {
10131025 // support pushing "future tokens" (would be also helpful to `break_and_eat`), or
10141026 // we should break everything including floats into more basic proc-macro style
10151027 // tokens in the lexer (probably preferable).
1016- fn parse_expr_tuple_field_access_float (
1017- & mut self ,
1018- lo : Span ,
1019- base : P < Expr > ,
1020- float : Symbol ,
1021- suffix : Option < Symbol > ,
1022- ) -> P < Expr > {
1028+ // See also `TokenKind::break_two_token_op` which does similar splitting of `>>` into `>`.
1029+ fn break_up_float ( & mut self , float : Symbol ) -> DestructuredFloat {
10231030 #[ derive( Debug ) ]
10241031 enum FloatComponent {
10251032 IdentLike ( String ) ,
@@ -1056,7 +1063,7 @@ impl<'a> Parser<'a> {
10561063 match & * components {
10571064 // 1e2
10581065 [ IdentLike ( i) ] => {
1059- self . parse_expr_tuple_field_access ( lo , base , Symbol :: intern ( & i) , suffix , None )
1066+ DestructuredFloat :: Single ( Symbol :: intern ( & i) , span )
10601067 }
10611068 // 1.
10621069 [ IdentLike ( i) , Punct ( '.' ) ] => {
@@ -1068,11 +1075,8 @@ impl<'a> Parser<'a> {
10681075 } else {
10691076 ( span, span)
10701077 } ;
1071- assert ! ( suffix. is_none( ) ) ;
10721078 let symbol = Symbol :: intern ( & i) ;
1073- self . token = Token :: new ( token:: Ident ( symbol, false ) , ident_span) ;
1074- let next_token = ( Token :: new ( token:: Dot , dot_span) , self . token_spacing ) ;
1075- self . parse_expr_tuple_field_access ( lo, base, symbol, None , Some ( next_token) )
1079+ DestructuredFloat :: TrailingDot ( symbol, ident_span, dot_span)
10761080 }
10771081 // 1.2 | 1.2e3
10781082 [ IdentLike ( i1) , Punct ( '.' ) , IdentLike ( i2) ] => {
@@ -1088,16 +1092,8 @@ impl<'a> Parser<'a> {
10881092 ( span, span, span)
10891093 } ;
10901094 let symbol1 = Symbol :: intern ( & i1) ;
1091- self . token = Token :: new ( token:: Ident ( symbol1, false ) , ident1_span) ;
1092- // This needs to be `Spacing::Alone` to prevent regressions.
1093- // See issue #76399 and PR #76285 for more details
1094- let next_token1 = ( Token :: new ( token:: Dot , dot_span) , Spacing :: Alone ) ;
1095- let base1 =
1096- self . parse_expr_tuple_field_access ( lo, base, symbol1, None , Some ( next_token1) ) ;
10971095 let symbol2 = Symbol :: intern ( & i2) ;
1098- let next_token2 = Token :: new ( token:: Ident ( symbol2, false ) , ident2_span) ;
1099- self . bump_with ( ( next_token2, self . token_spacing ) ) ; // `.`
1100- self . parse_expr_tuple_field_access ( lo, base1, symbol2, suffix, None )
1096+ DestructuredFloat :: MiddleDot ( symbol1, ident1_span, dot_span, symbol2, ident2_span)
11011097 }
11021098 // 1e+ | 1e- (recovered)
11031099 [ IdentLike ( _) , Punct ( '+' | '-' ) ] |
@@ -1109,12 +1105,47 @@ impl<'a> Parser<'a> {
11091105 [ IdentLike ( _) , Punct ( '.' ) , IdentLike ( _) , Punct ( '+' | '-' ) , IdentLike ( _) ] => {
11101106 // See the FIXME about `TokenCursor` above.
11111107 self . error_unexpected_after_dot ( ) ;
1112- base
1108+ DestructuredFloat :: Error
11131109 }
11141110 _ => panic ! ( "unexpected components in a float token: {:?}" , components) ,
11151111 }
11161112 }
11171113
1114+ fn parse_expr_tuple_field_access_float (
1115+ & mut self ,
1116+ lo : Span ,
1117+ base : P < Expr > ,
1118+ float : Symbol ,
1119+ suffix : Option < Symbol > ,
1120+ ) -> P < Expr > {
1121+ match self . break_up_float ( float) {
1122+ // 1e2
1123+ DestructuredFloat :: Single ( sym, _sp) => {
1124+ self . parse_expr_tuple_field_access ( lo, base, sym, suffix, None )
1125+ }
1126+ // 1.
1127+ DestructuredFloat :: TrailingDot ( sym, ident_span, dot_span) => {
1128+ assert ! ( suffix. is_none( ) ) ;
1129+ self . token = Token :: new ( token:: Ident ( sym, false ) , ident_span) ;
1130+ let next_token = ( Token :: new ( token:: Dot , dot_span) , self . token_spacing ) ;
1131+ self . parse_expr_tuple_field_access ( lo, base, sym, None , Some ( next_token) )
1132+ }
1133+ // 1.2 | 1.2e3
1134+ DestructuredFloat :: MiddleDot ( symbol1, ident1_span, dot_span, symbol2, ident2_span) => {
1135+ self . token = Token :: new ( token:: Ident ( symbol1, false ) , ident1_span) ;
1136+ // This needs to be `Spacing::Alone` to prevent regressions.
1137+ // See issue #76399 and PR #76285 for more details
1138+ let next_token1 = ( Token :: new ( token:: Dot , dot_span) , Spacing :: Alone ) ;
1139+ let base1 =
1140+ self . parse_expr_tuple_field_access ( lo, base, symbol1, None , Some ( next_token1) ) ;
1141+ let next_token2 = Token :: new ( token:: Ident ( symbol2, false ) , ident2_span) ;
1142+ self . bump_with ( ( next_token2, self . token_spacing ) ) ; // `.`
1143+ self . parse_expr_tuple_field_access ( lo, base1, symbol2, suffix, None )
1144+ }
1145+ DestructuredFloat :: Error => base,
1146+ }
1147+ }
1148+
11181149 fn parse_expr_tuple_field_access (
11191150 & mut self ,
11201151 lo : Span ,
0 commit comments