@@ -18,6 +18,8 @@ pub enum FStringError {
18
18
UnopenedRbrace ,
19
19
InvalidExpression ,
20
20
InvalidConversionFlag ,
21
+ EmptyExpression ,
22
+ MismatchedDelimiter ,
21
23
}
22
24
23
25
impl From < FStringError > for LalrpopError < Location , Tok , LexicalError > {
@@ -42,12 +44,12 @@ impl<'a> FStringParser<'a> {
42
44
fn parse_formatted_value ( & mut self ) -> Result < StringGroup , FStringError > {
43
45
let mut expression = String :: new ( ) ;
44
46
let mut spec = String :: new ( ) ;
45
- let mut depth = 0 ;
47
+ let mut delims = Vec :: new ( ) ;
46
48
let mut conversion = None ;
47
49
48
50
while let Some ( ch) = self . chars . next ( ) {
49
51
match ch {
50
- '!' if depth == 0 => {
52
+ '!' if delims . is_empty ( ) => {
51
53
conversion = Some ( match self . chars . next ( ) {
52
54
Some ( 's' ) => ConversionFlag :: Str ,
53
55
Some ( 'a' ) => ConversionFlag :: Ascii ,
@@ -60,7 +62,7 @@ impl<'a> FStringParser<'a> {
60
62
}
61
63
} )
62
64
}
63
- ':' if depth == 0 => {
65
+ ':' if delims . is_empty ( ) => {
64
66
while let Some ( & next) = self . chars . peek ( ) {
65
67
if next != '}' {
66
68
spec. push ( next) ;
@@ -70,31 +72,47 @@ impl<'a> FStringParser<'a> {
70
72
}
71
73
}
72
74
}
73
- '{ ' => {
74
- if let Some ( '{' ) = self . chars . peek ( ) {
75
- expression . push_str ( "{{" ) ;
76
- self . chars . next ( ) ;
77
- } else {
78
- expression . push ( '{' ) ;
79
- depth += 1 ;
75
+ '(' | '{' | '[ ' => {
76
+ expression . push ( ch ) ;
77
+ delims . push ( ch ) ;
78
+ }
79
+ ')' => {
80
+ if delims . pop ( ) != Some ( '(' ) {
81
+ return Err ( MismatchedDelimiter ) ;
80
82
}
83
+ expression. push ( ch) ;
84
+ }
85
+ ']' => {
86
+ if delims. pop ( ) != Some ( '[' ) {
87
+ return Err ( MismatchedDelimiter ) ;
88
+ }
89
+ expression. push ( ch) ;
90
+ }
91
+ '}' if !delims. is_empty ( ) => {
92
+ if delims. pop ( ) != Some ( '{' ) {
93
+ return Err ( MismatchedDelimiter ) ;
94
+ }
95
+ expression. push ( ch) ;
81
96
}
82
97
'}' => {
83
- if let Some ( '}' ) = self . chars . peek ( ) {
84
- expression. push_str ( "}}" ) ;
85
- self . chars . next ( ) ;
86
- } else if depth > 0 {
87
- expression. push ( '}' ) ;
88
- depth -= 1 ;
89
- } else {
90
- return Ok ( FormattedValue {
91
- value : Box :: new (
92
- parse_expression ( expression. trim ( ) )
93
- . map_err ( |_| InvalidExpression ) ?,
94
- ) ,
95
- conversion,
96
- spec,
97
- } ) ;
98
+ if expression. is_empty ( ) {
99
+ return Err ( EmptyExpression ) ;
100
+ }
101
+ return Ok ( FormattedValue {
102
+ value : Box :: new (
103
+ parse_expression ( expression. trim ( ) ) . map_err ( |_| InvalidExpression ) ?,
104
+ ) ,
105
+ conversion,
106
+ spec,
107
+ } ) ;
108
+ }
109
+ '"' | '\'' => {
110
+ expression. push ( ch) ;
111
+ while let Some ( next) = self . chars . next ( ) {
112
+ expression. push ( next) ;
113
+ if next == ch {
114
+ break ;
115
+ }
98
116
}
99
117
}
100
118
_ => {
0 commit comments