@@ -169,8 +169,11 @@ tok_continuation_line(struct tok_state *tok) {
169169
170170
171171int
172- _PyLexer_get_normal_mode (struct tok_state * tok , tokenizer_mode * current_tok , struct token * token )
172+ _PyLexer_get_normal (struct tok_state * tok , ftstring_state * current , struct token * token )
173173{
174+ assert (current == NULL ||
175+ (current -> mode == FTSTRING_MODE_EXPRESSION &&
176+ current -> replacement_depth > 0 ));
174177 int c ;
175178 int blankline , nonascii ;
176179
@@ -333,13 +336,13 @@ _PyLexer_get_normal_mode(struct tok_state *tok, tokenizer_mode* current_tok, str
333336 c = tok_nextc (tok );
334337 }
335338
336- if (_PyLexer_InsideFString ( tok ) && INSIDE_FSTRING_EXPR ( current_tok ) ) {
339+ if (current != NULL ) {
337340 const char * comment_end = tok -> cur ;
338341 if (c == '\n' ) {
339342 comment_end -- ;
340343 }
341344 if (_PyLexer_record_ftstring_comment (
342- tok , tok -> start , comment_end ) < 0 ) {
345+ tok , current , tok -> start , comment_end ) < 0 ) {
343346 tok -> done = E_NOMEM ;
344347 return MAKE_TOKEN (ERRORTOKEN );
345348 }
@@ -545,12 +548,11 @@ _PyLexer_get_normal_mode(struct tok_state *tok, tokenizer_mode* current_tok, str
545548
546549 /* Punctuation character */
547550 int is_punctuation = (c == ':' || c == '}' || c == '!' );
548- if (is_punctuation && _PyLexer_InsideFString (tok ) &&
549- INSIDE_FSTRING_EXPR (current_tok )) {
550- int cursor = current_tok -> curly_bracket_depth - 1 ;
551- int in_format_spec = current_tok -> in_format_spec ;
551+ if (is_punctuation && current != NULL ) {
552+ int bracket_depth = _PyLexer_FTStringBracketDepth (tok , current );
553+ int cursor = bracket_depth - 1 ;
552554 int cursor_in_format_with_debug =
553- cursor == 1 && ( current_tok -> in_debug || in_format_spec ) ;
555+ cursor == 1 && current -> debug_expr ;
554556 int cursor_valid = cursor == 0 || cursor_in_format_with_debug ;
555557 if (cursor_valid && c == '!' ) {
556558 int c2 = tok_nextc (tok );
@@ -560,17 +562,15 @@ _PyLexer_get_normal_mode(struct tok_state *tok, tokenizer_mode* current_tok, str
560562 tok_backup (tok , c2 );
561563 }
562564 if (cursor_valid ) {
563- _PyLexer_finish_ftstring_expr (tok );
565+ _PyLexer_finish_ftstring_expr (tok , current );
564566 }
565567 if (cursor_valid &&
566- _PyLexer_set_ftstring_expr_metadata (tok , token )) {
568+ _PyLexer_set_ftstring_expr_metadata (tok , current , token )) {
567569 return MAKE_TOKEN (ERRORTOKEN );
568570 }
569571
570- if (c == ':' &&
571- cursor == current_tok -> curly_bracket_expr_start_depth ) {
572- current_tok -> kind = TOK_FSTRING_MODE ;
573- current_tok -> in_format_spec = 1 ;
572+ if (c == ':' && bracket_depth == current -> replacement_depth ) {
573+ current -> mode = FTSTRING_MODE_FORMAT_SPEC ;
574574 p_start = tok -> start ;
575575 p_end = tok -> cur ;
576576 return MAKE_TOKEN (_PyToken_OneChar (c ));
@@ -609,18 +609,20 @@ _PyLexer_get_normal_mode(struct tok_state *tok, tokenizer_mode* current_tok, str
609609 tok -> parenlinenostack [tok -> level ] = tok -> lineno ;
610610 tok -> parencolstack [tok -> level ] = (int )(tok -> start - tok -> line_start );
611611 tok -> level ++ ;
612- if (_PyLexer_InsideFString (tok )) {
613- current_tok -> curly_bracket_depth ++ ;
614- }
615612 break ;
616613 case ')' :
617614 case ']' :
618615 case '}' :
619- if (_PyLexer_InsideFString (tok ) &&
620- !current_tok -> curly_bracket_depth && c == '}' ) {
621- return MAKE_TOKEN (_PyTokenizer_syntaxerror (tok ,
622- "%c-string: single '}' is not allowed" ,
623- _PyLexer_CurrentStringPrefix (tok )));
616+ if (current != NULL &&
617+ _PyLexer_FTStringBracketDepth (tok , current ) == 0 ) {
618+ if (c == '}' ) {
619+ return MAKE_TOKEN (_PyTokenizer_syntaxerror (tok ,
620+ "%c-string: single '}' is not allowed" ,
621+ _PyLexer_StringPrefix (current -> kind )));
622+ }
623+ return MAKE_TOKEN (_PyTokenizer_syntaxerror (
624+ tok , "%c-string: unmatched '%c'" ,
625+ _PyLexer_StringPrefix (current -> kind ), c ));
624626 }
625627 if (!tok -> tok_extra_tokens && !tok -> level ) {
626628 return MAKE_TOKEN (_PyTokenizer_syntaxerror (tok , "unmatched '%c'" , c ));
@@ -631,18 +633,15 @@ _PyLexer_get_normal_mode(struct tok_state *tok, tokenizer_mode* current_tok, str
631633 if (!tok -> tok_extra_tokens && !((opening == '(' && c == ')' ) ||
632634 (opening == '[' && c == ']' ) ||
633635 (opening == '{' && c == '}' ))) {
634- /* If the opening bracket belongs to an f-string's expression
635- part (e.g. f"{)}") and the closing bracket is an arbitrary
636- nested expression, then instead of matching a different
637- syntactical construct with it; we'll throw an unmatched
638- parentheses error. */
639- if (_PyLexer_InsideFString (tok ) && opening == '{' ) {
640- assert (current_tok -> curly_bracket_depth >= 0 );
641- int previous_bracket = current_tok -> curly_bracket_depth - 1 ;
642- if (previous_bracket == current_tok -> curly_bracket_expr_start_depth ) {
636+ /* Do not match a closer against the brace that opened the
637+ * current replacement field. */
638+ if (current != NULL && opening == '{' ) {
639+ int bracket_depth =
640+ _PyLexer_FTStringBracketDepth (tok , current );
641+ if (bracket_depth == current -> replacement_depth - 1 ) {
643642 return MAKE_TOKEN (_PyTokenizer_syntaxerror (tok ,
644643 "%c-string: unmatched '%c'" ,
645- _PyLexer_CurrentStringPrefix ( tok ), c ));
644+ _PyLexer_StringPrefix ( current -> kind ), c ));
646645 }
647646 }
648647 if (tok -> parenlinenostack [tok -> level ] != tok -> lineno ) {
@@ -660,18 +659,16 @@ _PyLexer_get_normal_mode(struct tok_state *tok, tokenizer_mode* current_tok, str
660659 }
661660 }
662661
663- if (_PyLexer_InsideFString ( tok ) ) {
664- current_tok -> curly_bracket_depth -- ;
665- if (current_tok -> curly_bracket_depth < 0 ) {
662+ if (current != NULL ) {
663+ int bracket_depth = _PyLexer_FTStringBracketDepth ( tok , current ) ;
664+ if (bracket_depth < 0 ) {
666665 return MAKE_TOKEN (_PyTokenizer_syntaxerror (tok , "%c-string: unmatched '%c'" ,
667- _PyLexer_CurrentStringPrefix ( tok ), c ));
666+ _PyLexer_StringPrefix ( current -> kind ), c ));
668667 }
669- if (c == '}' && current_tok -> curly_bracket_depth ==
670- current_tok -> curly_bracket_expr_start_depth ) {
671- current_tok -> curly_bracket_expr_start_depth -- ;
672- current_tok -> kind = TOK_FSTRING_MODE ;
673- current_tok -> in_format_spec = 0 ;
674- current_tok -> in_debug = 0 ;
668+ if (c == '}' && bracket_depth == current -> replacement_depth - 1 ) {
669+ current -> replacement_depth -- ;
670+ current -> mode = FTSTRING_MODE_MIDDLE ;
671+ current -> debug_expr = 0 ;
675672 }
676673 }
677674 break ;
@@ -683,8 +680,9 @@ _PyLexer_get_normal_mode(struct tok_state *tok, tokenizer_mode* current_tok, str
683680 return MAKE_TOKEN (_PyTokenizer_syntaxerror (tok , "invalid non-printable character U+%04X" , c ));
684681 }
685682
686- if (c == '=' && INSIDE_FSTRING_EXPR_AT_TOP (current_tok )) {
687- current_tok -> in_debug = 1 ;
683+ if (c == '=' && current != NULL &&
684+ _PyLexer_FTStringBracketDepth (tok , current ) == current -> replacement_depth ) {
685+ current -> debug_expr = 1 ;
688686 }
689687
690688 /* Punctuation character */
@@ -697,12 +695,11 @@ _PyLexer_get_normal_mode(struct tok_state *tok, tokenizer_mode* current_tok, str
697695static int
698696tok_get (struct tok_state * tok , struct token * token )
699697{
700- tokenizer_mode * current_tok = _PyLexer_CurrentMode (tok );
701- if (current_tok -> kind == TOK_REGULAR_MODE ) {
702- return _PyLexer_get_normal_mode (tok , current_tok , token );
703- } else {
704- return _PyLexer_get_fstring_mode (tok , current_tok , token );
698+ ftstring_state * current = _PyLexer_CurrentFTString (tok );
699+ if (current == NULL || current -> mode == FTSTRING_MODE_EXPRESSION ) {
700+ return _PyLexer_get_normal (tok , current , token );
705701 }
702+ return _PyLexer_get_ftstring (tok , current , token );
706703}
707704
708705int
0 commit comments