@@ -91,6 +91,18 @@ impl From<P<Expr>> for LhsExpr {
91
91
}
92
92
}
93
93
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
+
94
106
impl < ' a > Parser < ' a > {
95
107
/// Parses an expression.
96
108
#[ inline]
@@ -1013,13 +1025,8 @@ impl<'a> Parser<'a> {
1013
1025
// support pushing "future tokens" (would be also helpful to `break_and_eat`), or
1014
1026
// we should break everything including floats into more basic proc-macro style
1015
1027
// 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 {
1023
1030
#[ derive( Debug ) ]
1024
1031
enum FloatComponent {
1025
1032
IdentLike ( String ) ,
@@ -1056,7 +1063,7 @@ impl<'a> Parser<'a> {
1056
1063
match & * components {
1057
1064
// 1e2
1058
1065
[ IdentLike ( i) ] => {
1059
- self . parse_expr_tuple_field_access ( lo , base , Symbol :: intern ( & i) , suffix , None )
1066
+ DestructuredFloat :: Single ( Symbol :: intern ( & i) , span )
1060
1067
}
1061
1068
// 1.
1062
1069
[ IdentLike ( i) , Punct ( '.' ) ] => {
@@ -1068,11 +1075,8 @@ impl<'a> Parser<'a> {
1068
1075
} else {
1069
1076
( span, span)
1070
1077
} ;
1071
- assert ! ( suffix. is_none( ) ) ;
1072
1078
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)
1076
1080
}
1077
1081
// 1.2 | 1.2e3
1078
1082
[ IdentLike ( i1) , Punct ( '.' ) , IdentLike ( i2) ] => {
@@ -1088,16 +1092,8 @@ impl<'a> Parser<'a> {
1088
1092
( span, span, span)
1089
1093
} ;
1090
1094
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) ) ;
1097
1095
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)
1101
1097
}
1102
1098
// 1e+ | 1e- (recovered)
1103
1099
[ IdentLike ( _) , Punct ( '+' | '-' ) ] |
@@ -1109,12 +1105,47 @@ impl<'a> Parser<'a> {
1109
1105
[ IdentLike ( _) , Punct ( '.' ) , IdentLike ( _) , Punct ( '+' | '-' ) , IdentLike ( _) ] => {
1110
1106
// See the FIXME about `TokenCursor` above.
1111
1107
self . error_unexpected_after_dot ( ) ;
1112
- base
1108
+ DestructuredFloat :: Error
1113
1109
}
1114
1110
_ => panic ! ( "unexpected components in a float token: {:?}" , components) ,
1115
1111
}
1116
1112
}
1117
1113
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
+
1118
1149
fn parse_expr_tuple_field_access (
1119
1150
& mut self ,
1120
1151
lo : Span ,
0 commit comments