@@ -404,6 +404,51 @@ tok_continuation_line(struct tok_state *tok) {
404404 return c ;
405405}
406406
407+ static int
408+ maybe_raise_syntax_error_for_string_prefixes (struct tok_state * tok ,
409+ int saw_b , int saw_r , int saw_u ,
410+ int saw_f , int saw_t ) {
411+ // Supported: rb, rf, rt (in any order)
412+ // Unsupported: ub, ur, uf, ut, bf, bt, ft (in any order)
413+
414+ #define RETURN_SYNTAX_ERROR (PREFIX1 , PREFIX2 ) \
415+ do { \
416+ (void)_PyTokenizer_syntaxerror_known_range( \
417+ tok, (int)(tok->start + 1 - tok->line_start), \
418+ (int)(tok->cur - tok->line_start), \
419+ "'" PREFIX1 "' and '" PREFIX2 "' prefixes are incompatible"); \
420+ return -1; \
421+ } while (0)
422+
423+ if (saw_u && saw_b ) {
424+ RETURN_SYNTAX_ERROR ("u" , "b" );
425+ }
426+ if (saw_u && saw_r ) {
427+ RETURN_SYNTAX_ERROR ("u" , "r" );
428+ }
429+ if (saw_u && saw_f ) {
430+ RETURN_SYNTAX_ERROR ("u" , "f" );
431+ }
432+ if (saw_u && saw_t ) {
433+ RETURN_SYNTAX_ERROR ("u" , "t" );
434+ }
435+
436+ if (saw_b && saw_f ) {
437+ RETURN_SYNTAX_ERROR ("b" , "f" );
438+ }
439+ if (saw_b && saw_t ) {
440+ RETURN_SYNTAX_ERROR ("b" , "t" );
441+ }
442+
443+ if (saw_f && saw_t ) {
444+ RETURN_SYNTAX_ERROR ("f" , "t" );
445+ }
446+
447+ #undef RETURN_SYNTAX_ERROR
448+
449+ return 0 ;
450+ }
451+
407452static int
408453tok_get_normal_mode (struct tok_state * tok , tokenizer_mode * current_tok , struct token * token )
409454{
@@ -648,40 +693,34 @@ tok_get_normal_mode(struct tok_state *tok, tokenizer_mode* current_tok, struct t
648693 /* Process the various legal combinations of b"", r"", u"", and f"". */
649694 int saw_b = 0 , saw_r = 0 , saw_u = 0 , saw_f = 0 , saw_t = 0 ;
650695 while (1 ) {
651- if (!( saw_b || saw_u || saw_f ) && (c == 'b' || c == 'B' ))
696+ if (!saw_b && (c == 'b' || c == 'B' )) {
652697 saw_b = 1 ;
698+ }
653699 /* Since this is a backwards compatibility support literal we don't
654700 want to support it in arbitrary order like byte literals. */
655- else if (!(saw_b || saw_u || saw_r || saw_f || saw_t )
656- && (c == 'u' || c == 'U' )) {
701+ else if (!saw_u && (c == 'u' || c == 'U' )) {
657702 saw_u = 1 ;
658703 }
659704 /* ur"" and ru"" are not supported */
660- else if (!( saw_r || saw_u ) && (c == 'r' || c == 'R' )) {
705+ else if (!saw_r && (c == 'r' || c == 'R' )) {
661706 saw_r = 1 ;
662707 }
663- else if (!( saw_f || saw_b || saw_u ) && (c == 'f' || c == 'F' )) {
708+ else if (!saw_f && (c == 'f' || c == 'F' )) {
664709 saw_f = 1 ;
665710 }
666- else if (!( saw_t || saw_u ) && (c == 't' || c == 'T' )) {
711+ else if (!saw_t && (c == 't' || c == 'T' )) {
667712 saw_t = 1 ;
668713 }
669714 else {
670715 break ;
671716 }
672717 c = tok_nextc (tok );
673718 if (c == '"' || c == '\'' ) {
674- if (saw_b && saw_t ) {
675- return MAKE_TOKEN (_PyTokenizer_syntaxerror_known_range (
676- tok , (int )(tok -> start + 1 - tok -> line_start ),
677- (int )(tok -> cur - tok -> line_start ),
678- "can't use 'b' and 't' string prefixes together" ));
679- }
680- if (saw_f && saw_t ) {
681- return MAKE_TOKEN (_PyTokenizer_syntaxerror_known_range (
682- tok , (int )(tok -> start + 1 - tok -> line_start ),
683- (int )(tok -> cur - tok -> line_start ),
684- "can't use 'f' and 't' string prefixes together" ));
719+ // Raise error on incompatible string prefixes:
720+ int status = maybe_raise_syntax_error_for_string_prefixes (
721+ tok , saw_b , saw_r , saw_u , saw_f , saw_t );
722+ if (status < 0 ) {
723+ return MAKE_TOKEN (ERRORTOKEN );
685724 }
686725
687726 // Handle valid f or t string creation:
0 commit comments