diff --git a/Parser/tokenizer.c b/Parser/tokenizer.c index bdaa65b100f376..34413158672a0e 100644 --- a/Parser/tokenizer.c +++ b/Parser/tokenizer.c @@ -1889,7 +1889,7 @@ tok_get_normal_mode(struct tok_state *tok, tokenizer_mode* current_tok, struct t } c = tok_nextc(tok); } - if (c == '"' || c == '\'') { + if ((c == '"' || c == '\'') && !current_tok->f_string_conversion) { in_tag_string = 1; goto f_string_quote; } @@ -2225,6 +2225,7 @@ tok_get_normal_mode(struct tok_state *tok, tokenizer_mode* current_tok, struct t the_current_tok->kind = TOK_FSTRING_MODE; the_current_tok->f_string_quote = quote; the_current_tok->f_string_quote_size = quote_size; + the_current_tok->f_string_conversion = 0; the_current_tok->f_string_start = tok->start; the_current_tok->f_string_multi_line_start = tok->line_start; the_current_tok->f_string_start_offset = -1; @@ -2368,6 +2369,10 @@ tok_get_normal_mode(struct tok_state *tok, tokenizer_mode* current_tok, struct t return MAKE_TOKEN(ENDMARKER); } + if (c != '!' && current_tok->f_string_conversion) { + current_tok->f_string_conversion = 0; + } + if (c == ':' && cursor == current_tok->curly_bracket_expr_start_depth) { current_tok->kind = TOK_FSTRING_MODE; p_start = tok->start; @@ -2471,6 +2476,10 @@ tok_get_normal_mode(struct tok_state *tok, tokenizer_mode* current_tok, struct t return MAKE_TOKEN(syntaxerror(tok, "invalid non-printable character U+%s", hex)); } + if (INSIDE_FSTRING_EXPR(current_tok) && c == '!') { + current_tok->f_string_conversion = 1; + } + /* Punctuation character */ p_start = tok->start; p_end = tok->cur; diff --git a/Parser/tokenizer.h b/Parser/tokenizer.h index 2b94aecce626c3..f28d9dcbe1d4d1 100644 --- a/Parser/tokenizer.h +++ b/Parser/tokenizer.h @@ -52,6 +52,8 @@ typedef struct _tokenizer_mode { const char* f_string_start; const char* f_string_multi_line_start; + int f_string_conversion; + Py_ssize_t f_string_start_offset; Py_ssize_t f_string_multi_line_start_offset;