@@ -909,8 +909,6 @@ _PyPegen_check_fstring_conversion(Parser *p, Token *conv_token, expr_ty conv) {
909909 return result_token_with_metadata (p , conv , conv_token -> metadata );
910910}
911911
912- static asdl_expr_seq *
913- unpack_top_level_joined_strs (Parser * p , asdl_expr_seq * raw_expressions );
914912ResultTokenWithMetadata *
915913_PyPegen_setup_full_format_spec (Parser * p , Token * colon , asdl_expr_seq * spec ,
916914 int lineno , int col_offset , int end_lineno ,
@@ -1192,68 +1190,62 @@ static expr_ty _PyPegen_decode_fstring_part(Parser *p, int is_raw,
11921190 p -> arena );
11931191}
11941192
1195- static asdl_expr_seq *
1196- unpack_top_level_joined_strs (Parser * p , asdl_expr_seq * raw_expressions ) {
1193+ expr_ty
1194+ _PyPegen_joined_str (Parser * p , Token * a , asdl_expr_seq * expr , Token * b ) {
1195+
11971196 /* The parser might put multiple f-string values into an individual
11981197 * JoinedStr node at the top level due to stuff like f-string debugging
11991198 * expressions. This function flattens those and promotes them to the
12001199 * upper level. Only simplifies AST, but the compiler already takes care
12011200 * of the regular output, so this is not necessary if you are not going
12021201 * to expose the output AST to Python level. */
12031202
1204- Py_ssize_t i , req_size , raw_size ;
1205-
1206- req_size = raw_size = asdl_seq_LEN (raw_expressions );
1207- expr_ty expr ;
1208- for (i = 0 ; i < raw_size ; i ++ ) {
1209- expr = asdl_seq_GET (raw_expressions , i );
1210- if (expr -> kind == JoinedStr_kind ) {
1211- req_size += asdl_seq_LEN (expr -> v .JoinedStr .values ) - 1 ;
1212- }
1213- }
1214-
1215- asdl_expr_seq * expressions = _Py_asdl_expr_seq_new (req_size , p -> arena );
1216- if (expressions == NULL ) {
1217- return NULL ;
1218- }
1219-
1220- Py_ssize_t raw_index , req_index = 0 ;
1221- for (raw_index = 0 ; raw_index < raw_size ; raw_index ++ ) {
1222- expr = asdl_seq_GET (raw_expressions , raw_index );
1223- if (expr -> kind == JoinedStr_kind ) {
1224- asdl_expr_seq * values = expr -> v .JoinedStr .values ;
1225- for (Py_ssize_t n = 0 ; n < asdl_seq_LEN (values ); n ++ ) {
1226- asdl_seq_SET (expressions , req_index , asdl_seq_GET (values , n ));
1227- req_index ++ ;
1203+ Py_ssize_t n_items = asdl_seq_LEN (expr );
1204+ Py_ssize_t total_items = n_items ;
1205+ for (Py_ssize_t i = 0 ; i < n_items ; i ++ ) {
1206+ expr_ty item = asdl_seq_GET (expr , i );
1207+ if (item -> kind == JoinedStr_kind ) {
1208+ total_items += asdl_seq_LEN (item -> v .JoinedStr .values ) - 1 ;
12281209 }
1229- } else {
1230- asdl_seq_SET (expressions , req_index , expr );
1231- req_index ++ ;
1232- }
12331210 }
1234- return expressions ;
1235- }
1236-
1237- expr_ty _PyPegen_joined_str (Parser * p , Token * a , asdl_expr_seq * raw_expressions ,
1238- Token * b ) {
1239-
1240- asdl_expr_seq * expr = unpack_top_level_joined_strs (p , raw_expressions );
1241- Py_ssize_t n_items = asdl_seq_LEN (expr );
12421211
12431212 const char * quote_str = PyBytes_AsString (a -> bytes );
12441213 if (quote_str == NULL ) {
12451214 return NULL ;
12461215 }
12471216 int is_raw = strpbrk (quote_str , "rR" ) != NULL ;
12481217
1249- asdl_expr_seq * seq = _Py_asdl_expr_seq_new (n_items , p -> arena );
1218+ asdl_expr_seq * seq = _Py_asdl_expr_seq_new (total_items , p -> arena );
12501219 if (seq == NULL ) {
12511220 return NULL ;
12521221 }
12531222
12541223 Py_ssize_t index = 0 ;
12551224 for (Py_ssize_t i = 0 ; i < n_items ; i ++ ) {
12561225 expr_ty item = asdl_seq_GET (expr , i );
1226+ // This should correspond to a JoinedStr node of two elements
1227+ // created _PyPegen_formatted_value. This situation can only be the result of
1228+ // a f-string debug expression where the first element is a constant with the text and the second
1229+ // a formatted value with the expression.
1230+ if (item -> kind == JoinedStr_kind ) {
1231+ asdl_expr_seq * values = item -> v .JoinedStr .values ;
1232+ if (asdl_seq_LEN (values ) != 2 ) {
1233+ PyErr_Format (PyExc_SystemError ,
1234+ "unexpected JoinedStr node without debug data in f-string at line %d" ,
1235+ item -> lineno );
1236+ return NULL ;
1237+ }
1238+
1239+ expr_ty first = asdl_seq_GET (values , 0 );
1240+ assert (first -> kind == Constant_kind );
1241+ asdl_seq_SET (seq , index ++ , first );
1242+
1243+ expr_ty second = asdl_seq_GET (values , 1 );
1244+ assert (second -> kind == FormattedValue_kind );
1245+ asdl_seq_SET (seq , index ++ , second );
1246+
1247+ continue ;
1248+ }
12571249 if (item -> kind == Constant_kind ) {
12581250 item = _PyPegen_decode_fstring_part (p , is_raw , item , b );
12591251 if (item == NULL ) {
@@ -1272,7 +1264,7 @@ expr_ty _PyPegen_joined_str(Parser *p, Token *a, asdl_expr_seq *raw_expressions,
12721264 }
12731265
12741266 asdl_expr_seq * resized_exprs ;
1275- if (index != n_items ) {
1267+ if (index != total_items ) {
12761268 resized_exprs = _Py_asdl_expr_seq_new (index , p -> arena );
12771269 if (resized_exprs == NULL ) {
12781270 return NULL ;
0 commit comments