@@ -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 > > ,
1011str_start : Location ,
1112str_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]
2033fn expr ( & self , node : ExprKind ) ->Expr {
2134Expr :: 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 > {
2938let mut expression =String :: new ( ) ;
3039let mut spec =None ;
3140let mut delims =Vec :: new ( ) ;
3241let mut conversion =ConversionFlag :: None ;
3342let mut self_documenting =false ;
3443let mut trailing_seq =String :: new ( ) ;
3544
36- while let Some ( ch) =chars . next ( ) {
45+ while let Some ( ch) =self . next_char ( ) {
3746match 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 ( & '=' ) =>{
6170if expression. trim ( ) . is_empty ( ) {
6271return Err ( EmptyExpression ) ;
6372}
6473
65- conversion =match chars . next ( ) {
74+ conversion =match self . next_char ( ) {
6675Some ( 's' ) =>ConversionFlag :: Str ,
6776Some ( 'a' ) =>ConversionFlag :: Ascii ,
6877Some ( '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 ( ) {
8695if peek !='}' && peek !=':' {
8796return Err ( if expression. trim ( ) . is_empty ( ) {
8897EmptyExpression
@@ -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 {
112121values : 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 nextin & 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 > {
238242let mut spec_constructor =Vec :: new ( ) ;
239243let mut constant_piece =String :: new ( ) ;
240- while let Some ( & next) =chars . peek ( ) {
244+ while let Some ( & next) =self . peek ( ) {
241245match next{
242246'{' =>{
243247if !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;
253256continue ;
254257}
255258'}' =>{
@@ -259,7 +262,7 @@ impl FStringParser {
259262 constant_piece. push ( next) ;
260263}
261264}
262- chars . next ( ) ;
265+ self . next_char ( ) ;
263266}
264267if !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 > {
279278if nested >=2 {
280279return Err ( ExpressionNestedTooDeeply ) ;
281280}
282281
283282let mut content =String :: new ( ) ;
284283let mut values =vec ! [ ] ;
285284
286- while let Some ( & ch) =chars . peek ( ) {
285+ while let Some ( & ch) =self . peek ( ) {
287286match ch{
288287'{' =>{
289- chars . next ( ) ;
288+ self . next_char ( ) ;
290289if nested ==0 {
291- match chars . peek ( ) {
290+ match self . peek ( ) {
292291Some ( '{' ) =>{
293- chars . next ( ) ;
292+ self . next_char ( ) ;
294293 content. push ( '{' ) ;
295294continue ;
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'}' =>{
314311if nested >0 {
315312break ;
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 {
322319return 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(
352349start : Location ,
353350end : 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,
360356location : start,
@@ -366,9 +362,7 @@ mod tests {
366362use super :: * ;
367363
368364fn 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]