@@ -5006,10 +5006,16 @@ fstring_parse(const char **str, const char *end, int raw, int recurse_lvl,
5006
5006
closing brace doesn't match an opening paren, for example. It
5007
5007
doesn't need to error on all invalid expressions, just correctly
5008
5008
find the end of all valid ones. Any errors inside the expression
5009
- will be caught when we parse it later. */
5009
+ will be caught when we parse it later.
5010
+
5011
+ *expression is set to the expression. For an '=' "debug" expression,
5012
+ *expr_text is set to the debug text (the original text of the expression,
5013
+ *including the '=' and any whitespace around it, as a string object). If
5014
+ *not a debug expression, *expr_text set to NULL. */
5010
5015
static int
5011
5016
fstring_find_expr (const char * * str , const char * end , int raw , int recurse_lvl ,
5012
- expr_ty * expression , struct compiling * c , const node * n )
5017
+ PyObject * * expr_text , expr_ty * expression ,
5018
+ struct compiling * c , const node * n )
5013
5019
{
5014
5020
/* Return -1 on error, else 0. */
5015
5021
@@ -5020,9 +5026,6 @@ fstring_find_expr(const char **str, const char *end, int raw, int recurse_lvl,
5020
5026
int conversion = -1 ; /* The conversion char. Use default if not
5021
5027
specified, or !r if using = and no format
5022
5028
spec. */
5023
- int equal_flag = 0 ; /* Are we using the = feature? */
5024
- PyObject * expr_text = NULL ; /* The text of the expression, used for =. */
5025
- const char * expr_text_end ;
5026
5029
5027
5030
/* 0 if we're not in a string, else the quote char we're trying to
5028
5031
match (single or double quote). */
@@ -5198,15 +5201,21 @@ fstring_find_expr(const char **str, const char *end, int raw, int recurse_lvl,
5198
5201
expr_text. */
5199
5202
if (* * str == '=' ) {
5200
5203
* str += 1 ;
5201
- equal_flag = 1 ;
5202
5204
5203
5205
/* Skip over ASCII whitespace. No need to test for end of string
5204
5206
here, since we know there's at least a trailing quote somewhere
5205
5207
ahead. */
5206
5208
while (Py_ISSPACE (* * str )) {
5207
5209
* str += 1 ;
5208
5210
}
5209
- expr_text_end = * str ;
5211
+
5212
+ /* Set *expr_text to the text of the expression. */
5213
+ * expr_text = PyUnicode_FromStringAndSize (expr_start , * str - expr_start );
5214
+ if (!* expr_text ) {
5215
+ goto error ;
5216
+ }
5217
+ } else {
5218
+ * expr_text = NULL ;
5210
5219
}
5211
5220
5212
5221
/* Check for a conversion char, if present. */
@@ -5227,17 +5236,6 @@ fstring_find_expr(const char **str, const char *end, int raw, int recurse_lvl,
5227
5236
}
5228
5237
5229
5238
}
5230
- if (equal_flag ) {
5231
- Py_ssize_t len = expr_text_end - expr_start ;
5232
- expr_text = PyUnicode_FromStringAndSize (expr_start , len );
5233
- if (!expr_text ) {
5234
- goto error ;
5235
- }
5236
- if (PyArena_AddPyObject (c -> c_arena , expr_text ) < 0 ) {
5237
- Py_DECREF (expr_text );
5238
- goto error ;
5239
- }
5240
- }
5241
5239
5242
5240
/* Check for the format spec, if present. */
5243
5241
if (* str >= end )
@@ -5261,16 +5259,16 @@ fstring_find_expr(const char **str, const char *end, int raw, int recurse_lvl,
5261
5259
assert (* * str == '}' );
5262
5260
* str += 1 ;
5263
5261
5264
- /* If we're in = mode, and have no format spec and no explict conversion,
5265
- set the conversion to 'r'. */
5266
- if (equal_flag && format_spec == NULL && conversion == -1 ) {
5262
+ /* If we're in = mode (detected by non-NULL expr_text), and have no format
5263
+ spec and no explict conversion, set the conversion to 'r'. */
5264
+ if (* expr_text && format_spec == NULL && conversion == -1 ) {
5267
5265
conversion = 'r' ;
5268
5266
}
5269
5267
5270
5268
/* And now create the FormattedValue node that represents this
5271
5269
entire expression with the conversion and format spec. */
5272
5270
* expression = FormattedValue (simple_expression , conversion ,
5273
- format_spec , expr_text , LINENO (n ),
5271
+ format_spec , LINENO (n ),
5274
5272
n -> n_col_offset , n -> n_end_lineno ,
5275
5273
n -> n_end_col_offset , c -> c_arena );
5276
5274
if (!* expression )
@@ -5313,7 +5311,7 @@ fstring_find_expr(const char **str, const char *end, int raw, int recurse_lvl,
5313
5311
static int
5314
5312
fstring_find_literal_and_expr (const char * * str , const char * end , int raw ,
5315
5313
int recurse_lvl , PyObject * * literal ,
5316
- expr_ty * expression ,
5314
+ PyObject * * expr_text , expr_ty * expression ,
5317
5315
struct compiling * c , const node * n )
5318
5316
{
5319
5317
int result ;
@@ -5341,7 +5339,8 @@ fstring_find_literal_and_expr(const char **str, const char *end, int raw,
5341
5339
/* We must now be the start of an expression, on a '{'. */
5342
5340
assert (* * str == '{' );
5343
5341
5344
- if (fstring_find_expr (str , end , raw , recurse_lvl , expression , c , n ) < 0 )
5342
+ if (fstring_find_expr (str , end , raw , recurse_lvl , expr_text ,
5343
+ expression , c , n ) < 0 )
5345
5344
goto error ;
5346
5345
5347
5346
return 0 ;
@@ -5604,39 +5603,42 @@ FstringParser_ConcatFstring(FstringParser *state, const char **str,
5604
5603
5605
5604
/* Parse the f-string. */
5606
5605
while (1 ) {
5607
- PyObject * literal = NULL ;
5606
+ PyObject * literal [ 2 ] = { NULL , NULL } ;
5608
5607
expr_ty expression = NULL ;
5609
5608
5610
5609
/* If there's a zero length literal in front of the
5611
5610
expression, literal will be NULL. If we're at the end of
5612
5611
the f-string, expression will be NULL (unless result == 1,
5613
5612
see below). */
5614
5613
int result = fstring_find_literal_and_expr (str , end , raw , recurse_lvl ,
5615
- & literal , & expression ,
5616
- c , n );
5614
+ & literal [ 0 ] , & literal [ 1 ] ,
5615
+ & expression , c , n );
5617
5616
if (result < 0 )
5618
5617
return -1 ;
5619
5618
5620
- /* Add the literal, if any. */
5621
- if (!literal ) {
5622
- /* Do nothing. Just leave last_str alone (and possibly
5623
- NULL). */
5624
- } else if (!state -> last_str ) {
5625
- /* Note that the literal can be zero length, if the
5626
- input string is "\\\n" or "\\\r", among others. */
5627
- state -> last_str = literal ;
5628
- literal = NULL ;
5629
- } else {
5630
- /* We have a literal, concatenate it. */
5631
- assert (PyUnicode_GET_LENGTH (literal ) != 0 );
5632
- if (FstringParser_ConcatAndDel (state , literal ) < 0 )
5633
- return -1 ;
5634
- literal = NULL ;
5619
+ /* Add the literals, if any. */
5620
+ for (int i = 0 ; i < 2 ; i ++ ) {
5621
+ if (!literal [i ]) {
5622
+ /* Do nothing. Just leave last_str alone (and possibly
5623
+ NULL). */
5624
+ } else if (!state -> last_str ) {
5625
+ /* Note that the literal can be zero length, if the
5626
+ input string is "\\\n" or "\\\r", among others. */
5627
+ state -> last_str = literal [i ];
5628
+ literal [i ] = NULL ;
5629
+ } else {
5630
+ /* We have a literal, concatenate it. */
5631
+ assert (PyUnicode_GET_LENGTH (literal [i ]) != 0 );
5632
+ if (FstringParser_ConcatAndDel (state , literal [i ]) < 0 )
5633
+ return -1 ;
5634
+ literal [i ] = NULL ;
5635
+ }
5635
5636
}
5636
5637
5637
- /* We've dealt with the literal now. It can't be leaked on further
5638
+ /* We've dealt with the literals now. They can't be leaked on further
5638
5639
errors. */
5639
- assert (literal == NULL );
5640
+ assert (literal [0 ] == NULL );
5641
+ assert (literal [1 ] == NULL );
5640
5642
5641
5643
/* See if we should just loop around to get the next literal
5642
5644
and expression, while ignoring the expression this
0 commit comments