@@ -961,8 +961,6 @@ _PyPegen_check_fstring_conversion(Parser *p, Token* conv_token, expr_ty conv)
961961 return result_token_with_metadata (p , conv , conv_token -> metadata );
962962}
963963
964- static asdl_expr_seq *
965- unpack_top_level_joined_strs (Parser * p , asdl_expr_seq * raw_expressions );
966964ResultTokenWithMetadata *
967965_PyPegen_setup_full_format_spec (Parser * p , Token * colon , asdl_expr_seq * spec , int lineno , int col_offset ,
968966 int end_lineno , int end_col_offset , PyArena * arena )
@@ -1271,69 +1269,64 @@ _PyPegen_decode_fstring_part(Parser* p, int is_raw, expr_ty constant, Token* tok
12711269 p -> arena );
12721270}
12731271
1274- static asdl_expr_seq *
1275- unpack_top_level_joined_strs (Parser * p , asdl_expr_seq * raw_expressions )
1276- {
1272+ expr_ty
1273+ _PyPegen_joined_str (Parser * p , Token * a , asdl_expr_seq * expr , Token * b ) {
1274+
12771275 /* The parser might put multiple f-string values into an individual
12781276 * JoinedStr node at the top level due to stuff like f-string debugging
12791277 * expressions. This function flattens those and promotes them to the
12801278 * upper level. Only simplifies AST, but the compiler already takes care
12811279 * of the regular output, so this is not necessary if you are not going
12821280 * to expose the output AST to Python level. */
12831281
1284- Py_ssize_t i , req_size , raw_size ;
1285-
1286- req_size = raw_size = asdl_seq_LEN (raw_expressions );
1287- expr_ty expr ;
1288- for (i = 0 ; i < raw_size ; i ++ ) {
1289- expr = asdl_seq_GET (raw_expressions , i );
1290- if (expr -> kind == JoinedStr_kind ) {
1291- req_size += asdl_seq_LEN (expr -> v .JoinedStr .values ) - 1 ;
1292- }
1293- }
1294-
1295- asdl_expr_seq * expressions = _Py_asdl_expr_seq_new (req_size , p -> arena );
1296- if (expressions == NULL ) {
1297- return NULL ;
1298- }
1299-
1300- Py_ssize_t raw_index , req_index = 0 ;
1301- for (raw_index = 0 ; raw_index < raw_size ; raw_index ++ ) {
1302- expr = asdl_seq_GET (raw_expressions , raw_index );
1303- if (expr -> kind == JoinedStr_kind ) {
1304- asdl_expr_seq * values = expr -> v .JoinedStr .values ;
1305- for (Py_ssize_t n = 0 ; n < asdl_seq_LEN (values ); n ++ ) {
1306- asdl_seq_SET (expressions , req_index , asdl_seq_GET (values , n ));
1307- req_index ++ ;
1308- }
1309- } else {
1310- asdl_seq_SET (expressions , req_index , expr );
1311- req_index ++ ;
1282+ Py_ssize_t n_items = asdl_seq_LEN (expr );
1283+ Py_ssize_t total_items = n_items ;
1284+ for (Py_ssize_t i = 0 ; i < n_items ; i ++ ) {
1285+ expr_ty item = asdl_seq_GET (expr , i );
1286+ if (item -> kind == JoinedStr_kind ) {
1287+ total_items += asdl_seq_LEN (item -> v .JoinedStr .values ) - 1 ;
13121288 }
13131289 }
1314- return expressions ;
1315- }
1316-
1317- expr_ty
1318- _PyPegen_joined_str (Parser * p , Token * a , asdl_expr_seq * raw_expressions , Token * b ) {
1319-
1320- asdl_expr_seq * expr = unpack_top_level_joined_strs (p , raw_expressions );
1321- Py_ssize_t n_items = asdl_seq_LEN (expr );
13221290
13231291 const char * quote_str = PyBytes_AsString (a -> bytes );
13241292 if (quote_str == NULL ) {
13251293 return NULL ;
13261294 }
13271295 int is_raw = strpbrk (quote_str , "rR" ) != NULL ;
13281296
1329- asdl_expr_seq * seq = _Py_asdl_expr_seq_new (n_items , p -> arena );
1297+ asdl_expr_seq * seq = _Py_asdl_expr_seq_new (total_items , p -> arena );
13301298 if (seq == NULL ) {
13311299 return NULL ;
13321300 }
13331301
13341302 Py_ssize_t index = 0 ;
13351303 for (Py_ssize_t i = 0 ; i < n_items ; i ++ ) {
13361304 expr_ty item = asdl_seq_GET (expr , i );
1305+
1306+ // This should correspond to a JoinedStr node of two elements
1307+ // created _PyPegen_formatted_value. This situation can only be the result of
1308+ // a f-string debug expression where the first element is a constant with the text and the second
1309+ // a formatted value with the expression.
1310+ if (item -> kind == JoinedStr_kind ) {
1311+ asdl_expr_seq * values = item -> v .JoinedStr .values ;
1312+ if (asdl_seq_LEN (values ) != 2 ) {
1313+ PyErr_Format (PyExc_SystemError ,
1314+ "unexpected JoinedStr node without debug data in f-string at line %d" ,
1315+ item -> lineno );
1316+ return NULL ;
1317+ }
1318+
1319+ expr_ty first = asdl_seq_GET (values , 0 );
1320+ assert (first -> kind == Constant_kind );
1321+ asdl_seq_SET (seq , index ++ , first );
1322+
1323+ expr_ty second = asdl_seq_GET (values , 1 );
1324+ assert (second -> kind == FormattedValue_kind );
1325+ asdl_seq_SET (seq , index ++ , second );
1326+
1327+ continue ;
1328+ }
1329+
13371330 if (item -> kind == Constant_kind ) {
13381331 item = _PyPegen_decode_fstring_part (p , is_raw , item , b );
13391332 if (item == NULL ) {
@@ -1352,7 +1345,7 @@ _PyPegen_joined_str(Parser *p, Token* a, asdl_expr_seq* raw_expressions, Token*b
13521345 }
13531346
13541347 asdl_expr_seq * resized_exprs ;
1355- if (index != n_items ) {
1348+ if (index != total_items ) {
13561349 resized_exprs = _Py_asdl_expr_seq_new (index , p -> arena );
13571350 if (resized_exprs == NULL ) {
13581351 return NULL ;
0 commit comments