@@ -969,8 +969,6 @@ _PyPegen_check_fstring_conversion(Parser *p, Token* conv_token, expr_ty conv)
969969 return result_token_with_metadata (p , conv , conv_token -> metadata );
970970}
971971
972- static asdl_expr_seq *
973- unpack_top_level_joined_strs (Parser * p , asdl_expr_seq * raw_expressions );
974972ResultTokenWithMetadata *
975973_PyPegen_setup_full_format_spec (Parser * p , Token * colon , asdl_expr_seq * spec , int lineno , int col_offset ,
976974 int end_lineno , int end_col_offset , PyArena * arena )
@@ -1279,69 +1277,64 @@ _PyPegen_decode_fstring_part(Parser* p, int is_raw, expr_ty constant, Token* tok
12791277 p -> arena );
12801278}
12811279
1282- static asdl_expr_seq *
1283- unpack_top_level_joined_strs (Parser * p , asdl_expr_seq * raw_expressions )
1284- {
1280+ expr_ty
1281+ _PyPegen_joined_str (Parser * p , Token * a , asdl_expr_seq * expr , Token * b ) {
1282+
12851283 /* The parser might put multiple f-string values into an individual
12861284 * JoinedStr node at the top level due to stuff like f-string debugging
12871285 * expressions. This function flattens those and promotes them to the
12881286 * upper level. Only simplifies AST, but the compiler already takes care
12891287 * of the regular output, so this is not necessary if you are not going
12901288 * to expose the output AST to Python level. */
12911289
1292- Py_ssize_t i , req_size , raw_size ;
1293-
1294- req_size = raw_size = asdl_seq_LEN (raw_expressions );
1295- expr_ty expr ;
1296- for (i = 0 ; i < raw_size ; i ++ ) {
1297- expr = asdl_seq_GET (raw_expressions , i );
1298- if (expr -> kind == JoinedStr_kind ) {
1299- req_size += asdl_seq_LEN (expr -> v .JoinedStr .values ) - 1 ;
1300- }
1301- }
1302-
1303- asdl_expr_seq * expressions = _Py_asdl_expr_seq_new (req_size , p -> arena );
1304- if (expressions == NULL ) {
1305- return NULL ;
1306- }
1307-
1308- Py_ssize_t raw_index , req_index = 0 ;
1309- for (raw_index = 0 ; raw_index < raw_size ; raw_index ++ ) {
1310- expr = asdl_seq_GET (raw_expressions , raw_index );
1311- if (expr -> kind == JoinedStr_kind ) {
1312- asdl_expr_seq * values = expr -> v .JoinedStr .values ;
1313- for (Py_ssize_t n = 0 ; n < asdl_seq_LEN (values ); n ++ ) {
1314- asdl_seq_SET (expressions , req_index , asdl_seq_GET (values , n ));
1315- req_index ++ ;
1316- }
1317- } else {
1318- asdl_seq_SET (expressions , req_index , expr );
1319- req_index ++ ;
1290+ Py_ssize_t n_items = asdl_seq_LEN (expr );
1291+ Py_ssize_t total_items = n_items ;
1292+ for (Py_ssize_t i = 0 ; i < n_items ; i ++ ) {
1293+ expr_ty item = asdl_seq_GET (expr , i );
1294+ if (item -> kind == JoinedStr_kind ) {
1295+ total_items += asdl_seq_LEN (item -> v .JoinedStr .values ) - 1 ;
13201296 }
13211297 }
1322- return expressions ;
1323- }
1324-
1325- expr_ty
1326- _PyPegen_joined_str (Parser * p , Token * a , asdl_expr_seq * raw_expressions , Token * b ) {
1327-
1328- asdl_expr_seq * expr = unpack_top_level_joined_strs (p , raw_expressions );
1329- Py_ssize_t n_items = asdl_seq_LEN (expr );
13301298
13311299 const char * quote_str = PyBytes_AsString (a -> bytes );
13321300 if (quote_str == NULL ) {
13331301 return NULL ;
13341302 }
13351303 int is_raw = strpbrk (quote_str , "rR" ) != NULL ;
13361304
1337- asdl_expr_seq * seq = _Py_asdl_expr_seq_new (n_items , p -> arena );
1305+ asdl_expr_seq * seq = _Py_asdl_expr_seq_new (total_items , p -> arena );
13381306 if (seq == NULL ) {
13391307 return NULL ;
13401308 }
13411309
13421310 Py_ssize_t index = 0 ;
13431311 for (Py_ssize_t i = 0 ; i < n_items ; i ++ ) {
13441312 expr_ty item = asdl_seq_GET (expr , i );
1313+
1314+ // This should correspond to a JoinedStr node of two elements
1315+ // created _PyPegen_formatted_value. This situation can only be the result of
1316+ // a f-string debug expression where the first element is a constant with the text and the second
1317+ // a formatted value with the expression.
1318+ if (item -> kind == JoinedStr_kind ) {
1319+ asdl_expr_seq * values = item -> v .JoinedStr .values ;
1320+ if (asdl_seq_LEN (values ) != 2 ) {
1321+ PyErr_Format (PyExc_SystemError ,
1322+ "unexpected JoinedStr node without debug data in f-string at line %d" ,
1323+ item -> lineno );
1324+ return NULL ;
1325+ }
1326+
1327+ expr_ty first = asdl_seq_GET (values , 0 );
1328+ assert (first -> kind == Constant_kind );
1329+ asdl_seq_SET (seq , index ++ , first );
1330+
1331+ expr_ty second = asdl_seq_GET (values , 1 );
1332+ assert (second -> kind == FormattedValue_kind );
1333+ asdl_seq_SET (seq , index ++ , second );
1334+
1335+ continue ;
1336+ }
1337+
13451338 if (item -> kind == Constant_kind ) {
13461339 item = _PyPegen_decode_fstring_part (p , is_raw , item , b );
13471340 if (item == NULL ) {
@@ -1360,7 +1353,7 @@ _PyPegen_joined_str(Parser *p, Token* a, asdl_expr_seq* raw_expressions, Token*b
13601353 }
13611354
13621355 asdl_expr_seq * resized_exprs ;
1363- if (index != n_items ) {
1356+ if (index != total_items ) {
13641357 resized_exprs = _Py_asdl_expr_seq_new (index , p -> arena );
13651358 if (resized_exprs == NULL ) {
13661359 return NULL ;
0 commit comments