@@ -11,13 +11,15 @@ use self::FStringErrorType::*;
11
11
struct FStringParser < ' a > {
12
12
chars : iter:: Peekable < str:: Chars < ' a > > ,
13
13
str_location : Location ,
14
+ recurse_lvl : u8 ,
14
15
}
15
16
16
17
impl < ' a > FStringParser < ' a > {
17
- fn new ( source : & ' a str , str_location : Location ) -> Self {
18
+ fn new ( source : & ' a str , str_location : Location , recurse_lvl : u8 ) -> Self {
18
19
Self {
19
20
chars : source. chars ( ) . peekable ( ) ,
20
21
str_location,
22
+ recurse_lvl,
21
23
}
22
24
}
23
25
@@ -95,25 +97,35 @@ impl<'a> FStringParser<'a> {
95
97
let mut spec_constructor = Vec :: new ( ) ;
96
98
let mut constant_piece = String :: new ( ) ;
97
99
let mut formatted_value_piece = String :: new ( ) ;
100
+ let mut spec_delims = Vec :: new ( ) ;
98
101
while let Some ( & next) = self . chars . peek ( ) {
99
102
match next {
100
- '{' if in_nested => return Err ( ExpressionNestedTooDeeply ) ,
103
+ '{' if in_nested => {
104
+ spec_delims. push ( next) ;
105
+ formatted_value_piece. push ( next) ;
106
+ }
101
107
'}' if in_nested => {
102
- in_nested = false ;
103
- spec_constructor. push (
104
- self . expr ( ExprKind :: FormattedValue {
105
- value : Box :: new (
106
- FStringParser :: new (
107
- & format ! ( "{{{}}}" , formatted_value_piece) ,
108
- Location :: default ( ) ,
109
- )
110
- . parse ( ) ?,
111
- ) ,
112
- conversion : None ,
113
- format_spec : None ,
114
- } ) ,
115
- ) ;
116
- formatted_value_piece. clear ( ) ;
108
+ if spec_delims. is_empty ( ) {
109
+ in_nested = false ;
110
+ spec_constructor. push (
111
+ self . expr ( ExprKind :: FormattedValue {
112
+ value : Box :: new (
113
+ FStringParser :: new (
114
+ & format ! ( "{{{}}}" , formatted_value_piece) ,
115
+ Location :: default ( ) ,
116
+ & self . recurse_lvl + 1 ,
117
+ )
118
+ . parse ( ) ?,
119
+ ) ,
120
+ conversion : None ,
121
+ format_spec : None ,
122
+ } ) ,
123
+ ) ;
124
+ formatted_value_piece. clear ( ) ;
125
+ } else {
126
+ spec_delims. pop ( ) ;
127
+ formatted_value_piece. push ( next) ;
128
+ }
117
129
}
118
130
_ if in_nested => {
119
131
formatted_value_piece. push ( next) ;
@@ -223,6 +235,10 @@ impl<'a> FStringParser<'a> {
223
235
}
224
236
225
237
fn parse ( mut self ) -> Result < Expr , FStringErrorType > {
238
+ if self . recurse_lvl >= 2 {
239
+ return Err ( ExpressionNestedTooDeeply ) ;
240
+ }
241
+
226
242
let mut content = String :: new ( ) ;
227
243
let mut values = vec ! [ ] ;
228
244
@@ -276,7 +292,7 @@ fn parse_fstring_expr(source: &str) -> Result<Expr, ParseError> {
276
292
/// Parse an fstring from a string, located at a certain position in the sourcecode.
277
293
/// In case of errors, we will get the location and the error returned.
278
294
pub fn parse_located_fstring ( source : & str , location : Location ) -> Result < Expr , FStringError > {
279
- FStringParser :: new ( source, location)
295
+ FStringParser :: new ( source, location, 0 )
280
296
. parse ( )
281
297
. map_err ( |error| FStringError { error, location } )
282
298
}
@@ -286,7 +302,7 @@ mod tests {
286
302
use super :: * ;
287
303
288
304
fn parse_fstring ( source : & str ) -> Result < Expr , FStringErrorType > {
289
- FStringParser :: new ( source, Location :: default ( ) ) . parse ( )
305
+ FStringParser :: new ( source, Location :: default ( ) , 0 ) . parse ( )
290
306
}
291
307
292
308
#[ test]
@@ -354,7 +370,7 @@ mod tests {
354
370
assert_eq ! ( parse_fstring( "{5!}" ) , Err ( InvalidConversionFlag ) ) ;
355
371
assert_eq ! ( parse_fstring( "{5!x}" ) , Err ( InvalidConversionFlag ) ) ;
356
372
357
- assert_eq ! ( parse_fstring( "{a:{a:{b}}" ) , Err ( ExpressionNestedTooDeeply ) ) ;
373
+ assert_eq ! ( parse_fstring( "{a:{a:{b}}} " ) , Err ( ExpressionNestedTooDeeply ) ) ;
358
374
359
375
assert_eq ! ( parse_fstring( "{a:b}}" ) , Err ( UnopenedRbrace ) ) ;
360
376
assert_eq ! ( parse_fstring( "}" ) , Err ( UnopenedRbrace ) ) ;
0 commit comments