@@ -6,63 +6,72 @@ use crate::{
66} ;
77use std:: { iter, mem, str} ;
88
9- struct FStringParser {
9+ struct FStringParser < ' a > {
10+ source : iter:: Peekable < str:: Chars < ' a > > ,
1011 str_start : Location ,
1112 str_end : Location ,
1213}
1314
14- impl FStringParser {
15- fn new ( str_start : Location , str_end : Location ) -> Self {
16- Self { str_start, str_end }
15+ impl < ' a > FStringParser < ' a > {
16+ fn new ( source : & ' a str , str_start : Location , str_end : Location ) -> Self {
17+ Self {
18+ source : source. chars ( ) . peekable ( ) ,
19+ str_start,
20+ str_end,
21+ }
22+ }
23+
24+ fn next_char ( & mut self ) -> Option < char > {
25+ self . source . next ( )
26+ }
27+
28+ fn peek ( & mut self ) -> Option < & char > {
29+ self . source . peek ( )
1730 }
1831
1932 #[ inline]
2033 fn expr ( & self , node : ExprKind ) -> Expr {
2134 Expr :: new ( self . str_start , self . str_end , node)
2235 }
2336
24- fn parse_formatted_value < ' a > (
25- & mut self ,
26- mut chars : iter:: Peekable < str:: Chars < ' a > > ,
27- nested : u8 ,
28- ) -> Result < ( Vec < Expr > , iter:: Peekable < str:: Chars < ' a > > ) , FStringErrorType > {
37+ fn parse_formatted_value ( & mut self , nested : u8 ) -> Result < Vec < Expr > , FStringErrorType > {
2938 let mut expression = String :: new ( ) ;
3039 let mut spec = None ;
3140 let mut delims = Vec :: new ( ) ;
3241 let mut conversion = ConversionFlag :: None ;
3342 let mut self_documenting = false ;
3443 let mut trailing_seq = String :: new ( ) ;
3544
36- while let Some ( ch) = chars . next ( ) {
45+ while let Some ( ch) = self . next_char ( ) {
3746 match ch {
3847 // can be integrated better with the remainign code, but as a starting point ok
3948 // in general I would do here a tokenizing of the fstrings to omit this peeking.
40- '!' if chars . peek ( ) == Some ( & '=' ) => {
49+ '!' if self . peek ( ) == Some ( & '=' ) => {
4150 expression. push_str ( "!=" ) ;
42- chars . next ( ) ;
51+ self . next_char ( ) ;
4352 }
4453
45- '=' if chars . peek ( ) == Some ( & '=' ) => {
54+ '=' if self . peek ( ) == Some ( & '=' ) => {
4655 expression. push_str ( "==" ) ;
47- chars . next ( ) ;
56+ self . next_char ( ) ;
4857 }
4958
50- '>' if chars . peek ( ) == Some ( & '=' ) => {
59+ '>' if self . peek ( ) == Some ( & '=' ) => {
5160 expression. push_str ( ">=" ) ;
52- chars . next ( ) ;
61+ self . next_char ( ) ;
5362 }
5463
55- '<' if chars . peek ( ) == Some ( & '=' ) => {
64+ '<' if self . peek ( ) == Some ( & '=' ) => {
5665 expression. push_str ( "<=" ) ;
57- chars . next ( ) ;
66+ self . next_char ( ) ;
5867 }
5968
60- '!' if delims. is_empty ( ) && chars . peek ( ) != Some ( & '=' ) => {
69+ '!' if delims. is_empty ( ) && self . peek ( ) != Some ( & '=' ) => {
6170 if expression. trim ( ) . is_empty ( ) {
6271 return Err ( EmptyExpression ) ;
6372 }
6473
65- conversion = match chars . next ( ) {
74+ conversion = match self . next_char ( ) {
6675 Some ( 's' ) => ConversionFlag :: Str ,
6776 Some ( 'a' ) => ConversionFlag :: Ascii ,
6877 Some ( 'r' ) => ConversionFlag :: Repr ,
@@ -82,7 +91,7 @@ impl FStringParser {
8291 }
8392 } ;
8493
85- if let Some ( & peek) = chars . peek ( ) {
94+ if let Some ( & peek) = self . peek ( ) {
8695 if peek != '}' && peek != ':' {
8796 return Err ( if expression. trim ( ) . is_empty ( ) {
8897 EmptyExpression
@@ -101,17 +110,16 @@ impl FStringParser {
101110
102111 // match a python 3.8 self documenting expression
103112 // format '{' PYTHON_EXPRESSION '=' FORMAT_SPECIFIER? '}'
104- '=' if chars . peek ( ) != Some ( & '=' ) && delims. is_empty ( ) => {
113+ '=' if self . peek ( ) != Some ( & '=' ) && delims. is_empty ( ) => {
105114 self_documenting = true ;
106115 }
107116
108117 ':' if delims. is_empty ( ) => {
109- let ( parsed_spec, remaining_chars ) = self . parse_spec ( chars , nested) ?;
118+ let parsed_spec = self . parse_spec ( nested) ?;
110119
111120 spec = Some ( Box :: new ( self . expr ( ExprKind :: JoinedStr {
112121 values : parsed_spec,
113122 } ) ) ) ;
114- chars = remaining_chars;
115123 }
116124 '(' | '{' | '[' => {
117125 expression. push ( ch) ;
@@ -194,21 +202,21 @@ impl FStringParser {
194202 } ) ,
195203 ]
196204 } ;
197- return Ok ( ( ret, chars ) ) ;
205+ return Ok ( ret) ;
198206 }
199207 '"' | '\'' => {
200208 expression. push ( ch) ;
201- let mut string_ended = false ;
202- for next in & mut chars {
203- expression. push ( next) ;
204- if next == ch {
205- string_ended = true ;
206- break ;
209+ loop {
210+ match self . next_char ( ) {
211+ Some ( c) => {
212+ expression. push ( c) ;
213+ if c == ch {
214+ break ;
215+ }
216+ }
217+ None => return Err ( UnterminatedString ) ,
207218 }
208219 }
209- if !string_ended {
210- return Err ( UnterminatedString ) ;
211- }
212220 }
213221 ' ' if self_documenting => {
214222 trailing_seq. push ( ch) ;
@@ -230,14 +238,10 @@ impl FStringParser {
230238 } )
231239 }
232240
233- fn parse_spec < ' a > (
234- & mut self ,
235- mut chars : iter:: Peekable < str:: Chars < ' a > > ,
236- nested : u8 ,
237- ) -> Result < ( Vec < Expr > , iter:: Peekable < str:: Chars < ' a > > ) , FStringErrorType > {
241+ fn parse_spec ( & mut self , nested : u8 ) -> Result < Vec < Expr > , FStringErrorType > {
238242 let mut spec_constructor = Vec :: new ( ) ;
239243 let mut constant_piece = String :: new ( ) ;
240- while let Some ( & next) = chars . peek ( ) {
244+ while let Some ( & next) = self . peek ( ) {
241245 match next {
242246 '{' => {
243247 if !constant_piece. is_empty ( ) {
@@ -247,9 +251,8 @@ impl FStringParser {
247251 } ) ) ;
248252 constant_piece. clear ( ) ;
249253 }
250- let ( parsed_expr, remaining_chars ) = self . parse ( chars , nested + 1 ) ?;
254+ let parsed_expr = self . parse ( nested + 1 ) ?;
251255 spec_constructor. extend ( parsed_expr) ;
252- chars = remaining_chars;
253256 continue ;
254257 }
255258 '}' => {
@@ -259,7 +262,7 @@ impl FStringParser {
259262 constant_piece. push ( next) ;
260263 }
261264 }
262- chars . next ( ) ;
265+ self . next_char ( ) ;
263266 }
264267 if !constant_piece. is_empty ( ) {
265268 spec_constructor. push ( self . expr ( ExprKind :: Constant {
@@ -268,29 +271,25 @@ impl FStringParser {
268271 } ) ) ;
269272 constant_piece. clear ( ) ;
270273 }
271- Ok ( ( spec_constructor, chars ) )
274+ Ok ( spec_constructor)
272275 }
273276
274- fn parse < ' a > (
275- & mut self ,
276- mut chars : iter:: Peekable < str:: Chars < ' a > > ,
277- nested : u8 ,
278- ) -> Result < ( Vec < Expr > , iter:: Peekable < str:: Chars < ' a > > ) , FStringErrorType > {
277+ fn parse ( & mut self , nested : u8 ) -> Result < Vec < Expr > , FStringErrorType > {
279278 if nested >= 2 {
280279 return Err ( ExpressionNestedTooDeeply ) ;
281280 }
282281
283282 let mut content = String :: new ( ) ;
284283 let mut values = vec ! [ ] ;
285284
286- while let Some ( & ch) = chars . peek ( ) {
285+ while let Some ( & ch) = self . peek ( ) {
287286 match ch {
288287 '{' => {
289- chars . next ( ) ;
288+ self . next_char ( ) ;
290289 if nested == 0 {
291- match chars . peek ( ) {
290+ match self . peek ( ) {
292291 Some ( '{' ) => {
293- chars . next ( ) ;
292+ self . next_char ( ) ;
294293 content. push ( '{' ) ;
295294 continue ;
296295 }
@@ -305,26 +304,24 @@ impl FStringParser {
305304 } ) ) ;
306305 }
307306
308- let ( parsed_values, remaining_chars) =
309- self . parse_formatted_value ( chars, nested) ?;
307+ let parsed_values = self . parse_formatted_value ( nested) ?;
310308 values. extend ( parsed_values) ;
311- chars = remaining_chars;
312309 }
313310 '}' => {
314311 if nested > 0 {
315312 break ;
316313 }
317- chars . next ( ) ;
318- if let Some ( '}' ) = chars . peek ( ) {
319- chars . next ( ) ;
314+ self . next_char ( ) ;
315+ if let Some ( '}' ) = self . peek ( ) {
316+ self . next_char ( ) ;
320317 content. push ( '}' ) ;
321318 } else {
322319 return Err ( SingleRbrace ) ;
323320 }
324321 }
325322 _ => {
326323 content. push ( ch) ;
327- chars . next ( ) ;
324+ self . next_char ( ) ;
328325 }
329326 }
330327 }
@@ -336,7 +333,7 @@ impl FStringParser {
336333 } ) )
337334 }
338335
339- Ok ( ( values, chars ) )
336+ Ok ( values)
340337 }
341338}
342339
@@ -352,9 +349,8 @@ pub fn parse_located_fstring(
352349 start : Location ,
353350 end : Location ,
354351) -> Result < Vec < Expr > , FStringError > {
355- FStringParser :: new ( start, end)
356- . parse ( source. chars ( ) . peekable ( ) , 0 )
357- . map ( |( e, _) | e)
352+ FStringParser :: new ( source, start, end)
353+ . parse ( 0 )
358354 . map_err ( |error| FStringError {
359355 error,
360356 location : start,
@@ -366,9 +362,7 @@ mod tests {
366362 use super :: * ;
367363
368364 fn parse_fstring ( source : & str ) -> Result < Vec < Expr > , FStringErrorType > {
369- FStringParser :: new ( Location :: default ( ) , Location :: default ( ) )
370- . parse ( source. chars ( ) . peekable ( ) , 0 )
371- . map ( |( e, _) | e)
365+ FStringParser :: new ( source, Location :: default ( ) , Location :: default ( ) ) . parse ( 0 )
372366 }
373367
374368 #[ test]
0 commit comments