@@ -1001,14 +1001,33 @@ result_token_with_metadata(Parser *p, void *result, PyObject *metadata)
10011001 return res ;
10021002}
10031003
1004+ static char
1005+ formatted_string_prefix (const Parser * p )
1006+ {
1007+ int nested = 0 ;
1008+ for (int i = p -> mark - 1 ; i >= 0 ; i -- ) {
1009+ int type = p -> tokens [i ]-> type ;
1010+ if (type == FSTRING_END || type == TSTRING_END ) {
1011+ nested ++ ;
1012+ }
1013+ else if (type == FSTRING_START || type == TSTRING_START ) {
1014+ if (nested == 0 ) {
1015+ return type == TSTRING_START ? 't' : 'f' ;
1016+ }
1017+ nested -- ;
1018+ }
1019+ }
1020+ Py_UNREACHABLE ();
1021+ }
1022+
10041023ResultTokenWithMetadata *
10051024_PyPegen_check_fstring_conversion (Parser * p , Token * conv_token , expr_ty conv )
10061025{
10071026 if (conv_token -> lineno != conv -> lineno || conv_token -> end_col_offset != conv -> col_offset ) {
10081027 return RAISE_SYNTAX_ERROR_KNOWN_RANGE (
10091028 conv_token , conv ,
10101029 "%c-string: conversion type must come right after the exclamation mark" ,
1011- TOK_GET_STRING_PREFIX ( p -> tok )
1030+ formatted_string_prefix ( p )
10121031 );
10131032 }
10141033
@@ -1017,7 +1036,7 @@ _PyPegen_check_fstring_conversion(Parser *p, Token* conv_token, expr_ty conv)
10171036 !(first == 's' || first == 'r' || first == 'a' )) {
10181037 RAISE_SYNTAX_ERROR_KNOWN_LOCATION (conv ,
10191038 "%c-string: invalid conversion character %R: expected 's', 'r', or 'a'" ,
1020- TOK_GET_STRING_PREFIX ( p -> tok ),
1039+ formatted_string_prefix ( p ),
10211040 conv -> v .Name .id );
10221041 return NULL ;
10231042 }
@@ -1344,7 +1363,8 @@ _PyPegen_decode_fstring_part(Parser* p, int is_raw, expr_ty constant, Token* tok
13441363}
13451364
13461365static asdl_expr_seq *
1347- _get_resized_exprs (Parser * p , Token * a , asdl_expr_seq * raw_expressions , Token * b , enum string_kind_t string_kind )
1366+ _get_resized_exprs (Parser * p , Token * a , asdl_expr_seq * raw_expressions ,
1367+ Token * b , int is_tstring )
13481368{
13491369 Py_ssize_t n_items = asdl_seq_LEN (raw_expressions );
13501370 Py_ssize_t total_items = n_items ;
@@ -1370,15 +1390,13 @@ _get_resized_exprs(Parser *p, Token *a, asdl_expr_seq *raw_expressions, Token *b
13701390 for (Py_ssize_t i = 0 ; i < n_items ; i ++ ) {
13711391 expr_ty item = asdl_seq_GET (raw_expressions , i );
13721392
1373- // This should correspond to a JoinedStr node of two elements
1374- // created _PyPegen_formatted_value. This situation can only be the result of
1375- // a (f|t)-string debug expression where the first element is a constant with the text and the second
1376- // a formatted value with the expression.
1393+ /* Debug expressions arrive as JoinedStr(text, value); flatten them
1394+ into the surrounding string. */
13771395 if (item -> kind == JoinedStr_kind ) {
13781396 asdl_expr_seq * values = item -> v .JoinedStr .values ;
13791397 if (asdl_seq_LEN (values ) != 2 ) {
13801398 PyErr_Format (PyExc_SystemError ,
1381- string_kind == TSTRING
1399+ is_tstring
13821400 ? "unexpected TemplateStr node without debug data in t-string at line %d"
13831401 : "unexpected JoinedStr node without debug data in f-string at line %d" ,
13841402 item -> lineno );
@@ -1390,7 +1408,9 @@ _get_resized_exprs(Parser *p, Token *a, asdl_expr_seq *raw_expressions, Token *b
13901408 asdl_seq_SET (seq , index ++ , first );
13911409
13921410 expr_ty second = asdl_seq_GET (values , 1 );
1393- assert ((string_kind == TSTRING && second -> kind == Interpolation_kind ) || second -> kind == FormattedValue_kind );
1411+ assert ((is_tstring &&
1412+ second -> kind == Interpolation_kind ) ||
1413+ second -> kind == FormattedValue_kind );
13941414 asdl_seq_SET (seq , index ++ , second );
13951415
13961416 continue ;
@@ -1432,7 +1452,7 @@ _get_resized_exprs(Parser *p, Token *a, asdl_expr_seq *raw_expressions, Token *b
14321452expr_ty
14331453_PyPegen_template_str (Parser * p , Token * a , asdl_expr_seq * raw_expressions , Token * b ) {
14341454
1435- asdl_expr_seq * resized_exprs = _get_resized_exprs (p , a , raw_expressions , b , TSTRING );
1455+ asdl_expr_seq * resized_exprs = _get_resized_exprs (p , a , raw_expressions , b , 1 );
14361456 if (resized_exprs == NULL ) {
14371457 return NULL ;
14381458 }
@@ -1444,7 +1464,7 @@ _PyPegen_template_str(Parser *p, Token *a, asdl_expr_seq *raw_expressions, Token
14441464expr_ty
14451465_PyPegen_joined_str (Parser * p , Token * a , asdl_expr_seq * raw_expressions , Token * b ) {
14461466
1447- asdl_expr_seq * resized_exprs = _get_resized_exprs (p , a , raw_expressions , b , FSTRING );
1467+ asdl_expr_seq * resized_exprs = _get_resized_exprs (p , a , raw_expressions , b , 0 );
14481468 if (resized_exprs == NULL ) {
14491469 return NULL ;
14501470 }
@@ -1460,12 +1480,7 @@ expr_ty _PyPegen_decoded_constant_from_token(Parser* p, Token* tok) {
14601480 return NULL ;
14611481 }
14621482
1463- // Check if we're inside a raw f-string for format spec decoding
1464- int is_raw = 0 ;
1465- if (INSIDE_FSTRING (p -> tok )) {
1466- tokenizer_mode * mode = TOK_GET_MODE (p -> tok );
1467- is_raw = mode -> raw ;
1468- }
1483+ int is_raw = tok -> is_raw ;
14691484
14701485 PyObject * str = _PyPegen_decode_string (p , is_raw , bstr , bsize , tok );
14711486 if (str == NULL ) {
@@ -2047,13 +2062,14 @@ _warn_relative_import_of_lazy(Parser *p, asdl_seq *dots, expr_ty module)
20472062 return -1 ;
20482063 }
20492064
2065+ _PyTokenizer_Info info = _PyTokenizer_GetInfo (p -> tok );
20502066 int res = _PyErr_EmitSyntaxWarning (msg ,
2051- p -> tok -> filename ,
2067+ info . filename ,
20522068 module -> lineno ,
20532069 module -> col_offset + 1 ,
20542070 module -> end_lineno ,
20552071 module -> end_col_offset + 1 ,
2056- p -> tok -> module );
2072+ info . module );
20572073 Py_DECREF (msg );
20582074 return res ;
20592075}
0 commit comments