@@ -4,6 +4,7 @@ use crate::{
4
4
error:: { FStringError , FStringErrorType , ParseError } ,
5
5
parser:: parse_expression,
6
6
} ;
7
+ use itertools:: Itertools ;
7
8
use std:: { iter, mem, str} ;
8
9
9
10
struct FStringParser < ' a > {
@@ -105,19 +106,16 @@ impl<'a> FStringParser<'a> {
105
106
nested -= 1 ;
106
107
if nested == 0 {
107
108
formatted_value_piece. push ( next) ;
108
- spec_constructor. push (
109
- self . expr ( ExprKind :: FormattedValue {
110
- value : Box :: new (
111
- FStringParser :: new (
112
- & formatted_value_piece,
113
- Location :: default ( ) ,
114
- & self . recurse_lvl + 1 ,
115
- )
116
- . parse ( ) ?,
117
- ) ,
118
- conversion : ConversionFlag :: None as _ ,
119
- format_spec : None ,
120
- } ) ,
109
+ let values = FStringParser :: new (
110
+ & formatted_value_piece,
111
+ Location :: default ( ) ,
112
+ & self . recurse_lvl + 1 ,
113
+ )
114
+ . parse ( ) ?;
115
+ spec_constructor. push ( values
116
+ . into_iter ( )
117
+ . exactly_one ( )
118
+ . expect ( "Expected formatted value to produce exactly one expression." )
121
119
) ;
122
120
formatted_value_piece. clear ( ) ;
123
121
} else {
@@ -129,11 +127,13 @@ impl<'a> FStringParser<'a> {
129
127
}
130
128
'{' => {
131
129
nested += 1 ;
132
- spec_constructor. push ( self . expr ( ExprKind :: Constant {
133
- value : constant_piece. to_owned ( ) . into ( ) ,
134
- kind : None ,
135
- } ) ) ;
136
- constant_piece. clear ( ) ;
130
+ if !constant_piece. is_empty ( ) {
131
+ spec_constructor. push ( self . expr ( ExprKind :: Constant {
132
+ value : constant_piece. to_owned ( ) . into ( ) ,
133
+ kind : None ,
134
+ } ) ) ;
135
+ constant_piece. clear ( ) ;
136
+ }
137
137
formatted_value_piece. push ( next) ;
138
138
formatted_value_piece. push ( ' ' ) ;
139
139
}
@@ -144,11 +144,13 @@ impl<'a> FStringParser<'a> {
144
144
}
145
145
self . chars . next ( ) ;
146
146
}
147
- spec_constructor. push ( self . expr ( ExprKind :: Constant {
148
- value : constant_piece. to_owned ( ) . into ( ) ,
149
- kind : None ,
150
- } ) ) ;
151
- constant_piece. clear ( ) ;
147
+ if !constant_piece. is_empty ( ) {
148
+ spec_constructor. push ( self . expr ( ExprKind :: Constant {
149
+ value : constant_piece. to_owned ( ) . into ( ) ,
150
+ kind : None ,
151
+ } ) ) ;
152
+ constant_piece. clear ( ) ;
153
+ }
152
154
if nested > 0 {
153
155
return Err ( UnclosedLbrace ) ;
154
156
}
@@ -241,7 +243,7 @@ impl<'a> FStringParser<'a> {
241
243
Err ( UnclosedLbrace )
242
244
}
243
245
244
- fn parse ( mut self ) -> Result < Expr , FStringErrorType > {
246
+ fn parse ( mut self ) -> Result < Vec < Expr > , FStringErrorType > {
245
247
if self . recurse_lvl >= 2 {
246
248
return Err ( ExpressionNestedTooDeeply ) ;
247
249
}
@@ -287,7 +289,7 @@ impl<'a> FStringParser<'a> {
287
289
} ) )
288
290
}
289
291
290
- Ok ( self . expr ( ExprKind :: JoinedStr { values } ) )
292
+ Ok ( values)
291
293
}
292
294
}
293
295
@@ -298,7 +300,7 @@ fn parse_fstring_expr(source: &str) -> Result<Expr, ParseError> {
298
300
299
301
/// Parse an fstring from a string, located at a certain position in the sourcecode.
300
302
/// In case of errors, we will get the location and the error returned.
301
- pub fn parse_located_fstring ( source : & str , location : Location ) -> Result < Expr , FStringError > {
303
+ pub fn parse_located_fstring ( source : & str , location : Location ) -> Result < Vec < Expr > , FStringError > {
302
304
FStringParser :: new ( source, location, 0 )
303
305
. parse ( )
304
306
. map_err ( |error| FStringError { error, location } )
@@ -308,7 +310,7 @@ pub fn parse_located_fstring(source: &str, location: Location) -> Result<Expr, F
308
310
mod tests {
309
311
use super :: * ;
310
312
311
- fn parse_fstring ( source : & str ) -> Result < Expr , FStringErrorType > {
313
+ fn parse_fstring ( source : & str ) -> Result < Vec < Expr > , FStringErrorType > {
312
314
FStringParser :: new ( source, Location :: default ( ) , 0 ) . parse ( )
313
315
}
314
316
0 commit comments