@@ -119,15 +119,19 @@ set_ftstring_expr(struct tok_state* tok, struct token *token, char c) {
119119 if (!(tok_mode -> in_debug || tok_mode -> string_kind == TSTRING ) || token -> metadata ) {
120120 return 0 ;
121121 }
122+ const char * expression = tok_mode -> last_expr_start ;
123+ assert (expression != NULL );
124+ assert (expression <= tok -> start );
125+ Py_ssize_t expression_size = tok -> start - expression ;
122126 PyObject * res = NULL ;
123127
124128 // Look for a # character outside of string literals
125129 int hash_detected = 0 ;
126130 int in_string = 0 ;
127131 char quote_char = 0 ;
128132
129- for (Py_ssize_t i = 0 ; i < tok_mode -> last_expr_size - tok_mode -> last_expr_end ; i ++ ) {
130- char ch = tok_mode -> last_expr_buffer [i ];
133+ for (Py_ssize_t i = 0 ; i < expression_size ; i ++ ) {
134+ char ch = expression [i ];
131135
132136 // Skip escaped characters
133137 if (ch == '\\' ) {
@@ -163,7 +167,7 @@ set_ftstring_expr(struct tok_state* tok, struct token *token, char c) {
163167 // If we found a # character in the expression, we need to handle comments
164168 if (hash_detected ) {
165169 // Allocate buffer for processed result
166- char * result = (char * )PyMem_Malloc ((tok_mode -> last_expr_size - tok_mode -> last_expr_end + 1 ) * sizeof (char ));
170+ char * result = (char * )PyMem_Malloc ((expression_size + 1 ) * sizeof (char ));
167171 if (!result ) {
168172 return -1 ;
169173 }
@@ -174,16 +178,16 @@ set_ftstring_expr(struct tok_state* tok, struct token *token, char c) {
174178 quote_char = 0 ; // Current string quote char
175179
176180 // Process each character
177- while (i < tok_mode -> last_expr_size - tok_mode -> last_expr_end ) {
178- char ch = tok_mode -> last_expr_buffer [i ];
181+ while (i < expression_size ) {
182+ char ch = expression [i ];
179183
180184 // Copy escaped characters without interpreting the escaped
181185 // character as a quote or comment marker.
182186 if (ch == '\\' ) {
183187 result [j ++ ] = ch ;
184188 i ++ ;
185- if (i < tok_mode -> last_expr_size - tok_mode -> last_expr_end ) {
186- result [j ++ ] = tok_mode -> last_expr_buffer [i ];
189+ if (i < expression_size ) {
190+ result [j ++ ] = expression [i ];
187191 }
188192 }
189193 // Handle string quotes
@@ -199,11 +203,11 @@ set_ftstring_expr(struct tok_state* tok, struct token *token, char c) {
199203 }
200204 // Skip comments
201205 else if (ch == '#' && !in_string ) {
202- while (i < tok_mode -> last_expr_size - tok_mode -> last_expr_end &&
203- tok_mode -> last_expr_buffer [i ] != '\n' ) {
206+ while (i < expression_size &&
207+ expression [i ] != '\n' ) {
204208 i ++ ;
205209 }
206- if (i < tok_mode -> last_expr_size - tok_mode -> last_expr_end ) {
210+ if (i < expression_size ) {
207211 result [j ++ ] = '\n' ;
208212 }
209213 }
@@ -219,8 +223,8 @@ set_ftstring_expr(struct tok_state* tok, struct token *token, char c) {
219223 PyMem_Free (result );
220224 } else {
221225 res = PyUnicode_DecodeUTF8 (
222- tok_mode -> last_expr_buffer ,
223- tok_mode -> last_expr_size - tok_mode -> last_expr_end ,
226+ expression ,
227+ expression_size ,
224228 NULL
225229 );
226230 }
@@ -232,61 +236,6 @@ set_ftstring_expr(struct tok_state* tok, struct token *token, char c) {
232236 return 0 ;
233237}
234238
235- int
236- _PyLexer_update_ftstring_expr (struct tok_state * tok , char cur )
237- {
238- assert (tok -> cur != NULL );
239-
240- Py_ssize_t size = strlen (tok -> cur );
241- tokenizer_mode * tok_mode = TOK_GET_MODE (tok );
242-
243- switch (cur ) {
244- case 0 :
245- if (!tok_mode -> last_expr_buffer || tok_mode -> last_expr_end >= 0 ) {
246- return 1 ;
247- }
248- char * new_buffer = PyMem_Realloc (
249- tok_mode -> last_expr_buffer ,
250- tok_mode -> last_expr_size + size
251- );
252- if (new_buffer == NULL ) {
253- PyMem_Free (tok_mode -> last_expr_buffer );
254- goto error ;
255- }
256- tok_mode -> last_expr_buffer = new_buffer ;
257- strncpy (tok_mode -> last_expr_buffer + tok_mode -> last_expr_size , tok -> cur , size );
258- tok_mode -> last_expr_size += size ;
259- break ;
260- case '{' :
261- if (tok_mode -> last_expr_buffer != NULL ) {
262- PyMem_Free (tok_mode -> last_expr_buffer );
263- }
264- tok_mode -> last_expr_buffer = PyMem_Malloc (size );
265- if (tok_mode -> last_expr_buffer == NULL ) {
266- goto error ;
267- }
268- tok_mode -> last_expr_size = size ;
269- tok_mode -> last_expr_end = -1 ;
270- strncpy (tok_mode -> last_expr_buffer , tok -> cur , size );
271- break ;
272- case '}' :
273- case '!' :
274- tok_mode -> last_expr_end = strlen (tok -> start );
275- break ;
276- case ':' :
277- if (tok_mode -> last_expr_end == -1 ) {
278- tok_mode -> last_expr_end = strlen (tok -> start );
279- }
280- break ;
281- default :
282- Py_UNREACHABLE ();
283- }
284- return 1 ;
285- error :
286- tok -> done = E_NOMEM ;
287- return 0 ;
288- }
289-
290239static int
291240lookahead (struct tok_state * tok , const char * test )
292241{
@@ -1103,9 +1052,8 @@ tok_get_normal_mode(struct tok_state *tok, tokenizer_mode* current_tok, struct t
11031052 the_current_tok -> first_line = tok -> lineno ;
11041053 the_current_tok -> start_offset = -1 ;
11051054 the_current_tok -> multi_line_start_offset = -1 ;
1106- the_current_tok -> last_expr_buffer = NULL ;
1107- the_current_tok -> last_expr_size = 0 ;
1108- the_current_tok -> last_expr_end = -1 ;
1055+ the_current_tok -> last_expr_start = NULL ;
1056+ the_current_tok -> last_expr_start_offset = -1 ;
11091057 the_current_tok -> in_format_spec = 0 ;
11101058 the_current_tok -> in_debug = 0 ;
11111059
@@ -1270,9 +1218,6 @@ tok_get_normal_mode(struct tok_state *tok, tokenizer_mode* current_tok, struct t
12701218 int cursor_in_format_with_debug =
12711219 cursor == 1 && (current_tok -> in_debug || in_format_spec );
12721220 int cursor_valid = cursor == 0 || cursor_in_format_with_debug ;
1273- if ((cursor_valid ) && !_PyLexer_update_ftstring_expr (tok , c )) {
1274- return MAKE_TOKEN (ENDMARKER );
1275- }
12761221 if ((cursor_valid ) & & c != '{' && set_ftstring_expr (tok , token , c )) {
12771222 return MAKE_TOKEN (ERRORTOKEN );
12781223 }
@@ -1416,6 +1361,9 @@ tok_get_fstring_mode(struct tok_state *tok, tokenizer_mode* current_tok, struct
14161361 if (start_char == '{' ) {
14171362 int peek1 = tok_nextc (tok );
14181363 tok_backup (tok , peek1 );
1364+ if (peek1 != '{' ) {
1365+ current_tok -> last_expr_start = tok -> cur ;
1366+ }
14191367 tok_backup (tok , start_char );
14201368 if (peek1 != '{' ) {
14211369 current_tok -> curly_bracket_expr_start_depth ++ ;
@@ -1440,13 +1388,6 @@ tok_get_fstring_mode(struct tok_state *tok, tokenizer_mode* current_tok, struct
14401388 }
14411389 }
14421390
1443- if (current_tok -> last_expr_buffer != NULL ) {
1444- PyMem_Free (current_tok -> last_expr_buffer );
1445- current_tok -> last_expr_buffer = NULL ;
1446- current_tok -> last_expr_size = 0 ;
1447- current_tok -> last_expr_end = -1 ;
1448- }
1449-
14501391 p_start = tok -> start ;
14511392 p_end = tok -> cur ;
14521393 tok -> tok_mode_stack_index -- ;
@@ -1531,12 +1472,10 @@ tok_get_fstring_mode(struct tok_state *tok, tokenizer_mode* current_tok, struct
15311472 }
15321473
15331474 if (c == '{' ) {
1534- if (!_PyLexer_update_ftstring_expr (tok , c )) {
1535- return MAKE_TOKEN (ENDMARKER );
1536- }
15371475 int peek = tok_nextc (tok );
15381476 if (peek != '{' || in_format_spec ) {
15391477 tok_backup (tok , peek );
1478+ current_tok -> last_expr_start = tok -> cur ;
15401479 tok_backup (tok , c );
15411480 current_tok -> curly_bracket_expr_start_depth ++ ;
15421481 if (current_tok -> curly_bracket_expr_start_depth >= MAX_EXPR_NESTING ) {
0 commit comments