Branch data Line data Source code
1 : : #include <stdbool.h>
2 : :
3 : : #include <Python.h>
4 : :
5 : : #include "tokenizer.h"
6 : : #include "pegen.h"
7 : : #include "string_parser.h"
8 : :
9 : : //// STRING HANDLING FUNCTIONS ////
10 : :
11 : : static int
12 : 732 : warn_invalid_escape_sequence(Parser *p, const char *first_invalid_escape, Token *t)
13 : : {
14 : 732 : unsigned char c = *first_invalid_escape;
15 [ + + + + ]: 732 : int octal = ('4' <= c && c <= '7');
16 : 732 : PyObject *msg =
17 : : octal
18 : 516 : ? PyUnicode_FromFormat("invalid octal escape sequence '\\%.3s'",
19 : : first_invalid_escape)
20 [ + + ]: 732 : : PyUnicode_FromFormat("invalid escape sequence '\\%c'", c);
21 [ - + ]: 732 : if (msg == NULL) {
22 : 0 : return -1;
23 : : }
24 [ + + ]: 732 : if (PyErr_WarnExplicitObject(PyExc_DeprecationWarning, msg, p->tok->filename,
25 : : t->lineno, NULL, NULL) < 0) {
26 [ + - ]: 5 : if (PyErr_ExceptionMatches(PyExc_DeprecationWarning)) {
27 : : /* Replace the DeprecationWarning exception with a SyntaxError
28 : : to get a more accurate error report */
29 : 5 : PyErr_Clear();
30 : :
31 : : /* This is needed, in order for the SyntaxError to point to the token t,
32 : : since _PyPegen_raise_error uses p->tokens[p->fill - 1] for the
33 : : error location, if p->known_err_token is not set. */
34 : 5 : p->known_err_token = t;
35 [ + + ]: 5 : if (octal) {
36 : 2 : RAISE_SYNTAX_ERROR("invalid octal escape sequence '\\%.3s'",
37 : : first_invalid_escape);
38 : : }
39 : : else {
40 : 3 : RAISE_SYNTAX_ERROR("invalid escape sequence '\\%c'", c);
41 : : }
42 : : }
43 : 5 : Py_DECREF(msg);
44 : 5 : return -1;
45 : : }
46 : 727 : Py_DECREF(msg);
47 : 727 : return 0;
48 : : }
49 : :
50 : : static PyObject *
51 : 22168 : decode_utf8(const char **sPtr, const char *end)
52 : : {
53 : : const char *s;
54 : : const char *t;
55 : 22168 : t = s = *sPtr;
56 [ + + + + ]: 152655 : while (s < end && (*s & 0x80)) {
57 : 130487 : s++;
58 : : }
59 : 22168 : *sPtr = s;
60 : 22168 : return PyUnicode_DecodeUTF8(t, s - t, NULL);
61 : : }
62 : :
63 : : static PyObject *
64 : 239777 : decode_unicode_with_escapes(Parser *parser, const char *s, size_t len, Token *t)
65 : : {
66 : : PyObject *v;
67 : : PyObject *u;
68 : : char *buf;
69 : : char *p;
70 : : const char *end;
71 : :
72 : : /* check for integer overflow */
73 [ - + ]: 239777 : if (len > SIZE_MAX / 6) {
74 : 0 : return NULL;
75 : : }
76 : : /* "ä" (2 bytes) may become "\U000000E4" (10 bytes), or 1:5
77 : : "\ä" (3 bytes) may become "\u005c\U000000E4" (16 bytes), or ~1:6 */
78 : 239777 : u = PyBytes_FromStringAndSize((char *)NULL, len * 6);
79 [ - + ]: 239777 : if (u == NULL) {
80 : 0 : return NULL;
81 : : }
82 : 239777 : p = buf = PyBytes_AsString(u);
83 [ - + ]: 239777 : if (p == NULL) {
84 : 0 : return NULL;
85 : : }
86 : 239777 : end = s + len;
87 [ + + ]: 4364519 : while (s < end) {
88 [ + + ]: 4124743 : if (*s == '\\') {
89 : 228116 : *p++ = *s++;
90 [ + + + + ]: 228116 : if (s >= end || *s & 0x80) {
91 : 5 : strcpy(p, "u005c");
92 : 5 : p += 5;
93 [ + + ]: 5 : if (s >= end) {
94 : 1 : break;
95 : : }
96 : : }
97 : : }
98 [ + + ]: 4124742 : if (*s & 0x80) {
99 : : PyObject *w;
100 : : int kind;
101 : : const void *data;
102 : : Py_ssize_t w_len;
103 : : Py_ssize_t i;
104 : 22168 : w = decode_utf8(&s, end);
105 [ - + ]: 22168 : if (w == NULL) {
106 : 0 : Py_DECREF(u);
107 : 0 : return NULL;
108 : : }
109 : 22168 : kind = PyUnicode_KIND(w);
110 : 22168 : data = PyUnicode_DATA(w);
111 : 22168 : w_len = PyUnicode_GET_LENGTH(w);
112 [ + + ]: 60555 : for (i = 0; i < w_len; i++) {
113 : 38387 : Py_UCS4 chr = PyUnicode_READ(kind, data, i);
114 : 38387 : sprintf(p, "\\U%08x", chr);
115 : 38387 : p += 10;
116 : : }
117 : : /* Should be impossible to overflow */
118 : : assert(p - buf <= PyBytes_GET_SIZE(u));
119 : 22168 : Py_DECREF(w);
120 : : }
121 : : else {
122 : 4102574 : *p++ = *s++;
123 : : }
124 : : }
125 : 239777 : len = p - buf;
126 : 239777 : s = buf;
127 : :
128 : : const char *first_invalid_escape;
129 : 239777 : v = _PyUnicode_DecodeUnicodeEscapeInternal(s, len, NULL, NULL, &first_invalid_escape);
130 : :
131 [ + + + + ]: 239777 : if (v != NULL && first_invalid_escape != NULL) {
132 [ + + ]: 365 : if (warn_invalid_escape_sequence(parser, first_invalid_escape, t) < 0) {
133 : : /* We have not decref u before because first_invalid_escape points
134 : : inside u. */
135 : 3 : Py_XDECREF(u);
136 : 3 : Py_DECREF(v);
137 : 3 : return NULL;
138 : : }
139 : : }
140 : 239774 : Py_XDECREF(u);
141 : 239774 : return v;
142 : : }
143 : :
144 : : static PyObject *
145 : 19133 : decode_bytes_with_escapes(Parser *p, const char *s, Py_ssize_t len, Token *t)
146 : : {
147 : : const char *first_invalid_escape;
148 : 19133 : PyObject *result = _PyBytes_DecodeEscape(s, len, NULL, &first_invalid_escape);
149 [ + + ]: 19133 : if (result == NULL) {
150 : 2 : return NULL;
151 : : }
152 : :
153 [ + + ]: 19131 : if (first_invalid_escape != NULL) {
154 [ + + ]: 366 : if (warn_invalid_escape_sequence(p, first_invalid_escape, t) < 0) {
155 : 2 : Py_DECREF(result);
156 : 2 : return NULL;
157 : : }
158 : : }
159 : 19129 : return result;
160 : : }
161 : :
162 : : /* s must include the bracketing quote characters, and r, b, u,
163 : : &/or f prefixes (if any), and embedded escape sequences (if any).
164 : : _PyPegen_parsestr parses it, and sets *result to decoded Python string object.
165 : : If the string is an f-string, set *fstr and *fstrlen to the unparsed
166 : : string object. Return 0 if no errors occurred. */
167 : : int
168 : 1685857 : _PyPegen_parsestr(Parser *p, int *bytesmode, int *rawmode, PyObject **result,
169 : : const char **fstr, Py_ssize_t *fstrlen, Token *t)
170 : : {
171 : 1685857 : const char *s = PyBytes_AsString(t->bytes);
172 [ - + ]: 1685857 : if (s == NULL) {
173 : 0 : return -1;
174 : : }
175 : :
176 : : size_t len;
177 : 1685857 : int quote = Py_CHARMASK(*s);
178 : 1685857 : int fmode = 0;
179 : 1685857 : *bytesmode = 0;
180 : 1685857 : *rawmode = 0;
181 : 1685857 : *result = NULL;
182 : 1685857 : *fstr = NULL;
183 [ + + ]: 1685857 : if (Py_ISALPHA(quote)) {
184 [ + + + + ]: 182029 : while (!*bytesmode || !*rawmode) {
185 [ + + - + ]: 181268 : if (quote == 'b' || quote == 'B') {
186 : 52115 : quote =(unsigned char)*++s;
187 : 52115 : *bytesmode = 1;
188 : : }
189 [ + + + + ]: 129153 : else if (quote == 'u' || quote == 'U') {
190 : 909 : quote = (unsigned char)*++s;
191 : : }
192 [ + + + + ]: 128244 : else if (quote == 'r' || quote == 'R') {
193 : 16198 : quote = (unsigned char)*++s;
194 : 16198 : *rawmode = 1;
195 : : }
196 [ + + - + ]: 112046 : else if (quote == 'f' || quote == 'F') {
197 : 22227 : quote = (unsigned char)*++s;
198 : 22227 : fmode = 1;
199 : : }
200 : : else {
201 : : break;
202 : : }
203 : : }
204 : : }
205 : :
206 : : /* fstrings are only allowed in Python 3.6 and greater */
207 [ + + + + ]: 1685857 : if (fmode && p->feature_version < 6) {
208 : 2 : p->error_indicator = 1;
209 : 2 : RAISE_SYNTAX_ERROR("Format strings are only supported in Python 3.6 and greater");
210 : 2 : return -1;
211 : : }
212 : :
213 [ + + - + ]: 1685855 : if (fmode && *bytesmode) {
214 : 0 : PyErr_BadInternalCall();
215 : 0 : return -1;
216 : : }
217 [ + + - + ]: 1685855 : if (quote != '\'' && quote != '\"') {
218 : 0 : PyErr_BadInternalCall();
219 : 0 : return -1;
220 : : }
221 : : /* Skip the leading quote char. */
222 : 1685855 : s++;
223 : 1685855 : len = strlen(s);
224 [ - + ]: 1685855 : if (len > INT_MAX) {
225 : 0 : PyErr_SetString(PyExc_OverflowError, "string to parse is too long");
226 : 0 : return -1;
227 : : }
228 [ - + ]: 1685855 : if (s[--len] != quote) {
229 : : /* Last quote char must match the first. */
230 : 0 : PyErr_BadInternalCall();
231 : 0 : return -1;
232 : : }
233 [ + + + + : 1685855 : if (len >= 4 && s[0] == quote && s[1] == quote) {
+ - ]
234 : : /* A triple quoted string. We've already skipped one quote at
235 : : the start and one at the end of the string. Now skip the
236 : : two at the start. */
237 : 120518 : s += 2;
238 : 120518 : len -= 2;
239 : : /* And check that the last two match. */
240 [ + - - + ]: 120518 : if (s[--len] != quote || s[--len] != quote) {
241 : 0 : PyErr_BadInternalCall();
242 : 0 : return -1;
243 : : }
244 : : }
245 : :
246 [ + + ]: 1685855 : if (fmode) {
247 : : /* Just return the bytes. The caller will parse the resulting
248 : : string. */
249 : 22225 : *fstr = s;
250 : 22225 : *fstrlen = len;
251 : 22225 : return 0;
252 : : }
253 : :
254 : : /* Not an f-string. */
255 : : /* Avoid invoking escape decoding routines if possible. */
256 [ + + + + ]: 1663630 : *rawmode = *rawmode || strchr(s, '\\') == NULL;
257 [ + + ]: 1663630 : if (*bytesmode) {
258 : : /* Disallow non-ASCII characters. */
259 : : const char *ch;
260 [ + + ]: 738050 : for (ch = s; *ch; ch++) {
261 [ + + ]: 686073 : if (Py_CHARMASK(*ch) >= 0x80) {
262 : 138 : RAISE_SYNTAX_ERROR(
263 : : "bytes can only contain ASCII "
264 : : "literal characters");
265 : 138 : return -1;
266 : : }
267 : : }
268 [ + + ]: 51977 : if (*rawmode) {
269 : 32844 : *result = PyBytes_FromStringAndSize(s, len);
270 : : }
271 : : else {
272 : 19133 : *result = decode_bytes_with_escapes(p, s, len, t);
273 : : }
274 : : }
275 : : else {
276 [ + + ]: 1611515 : if (*rawmode) {
277 : 1472738 : *result = PyUnicode_DecodeUTF8Stateful(s, len, NULL, NULL);
278 : : }
279 : : else {
280 : 138777 : *result = decode_unicode_with_escapes(p, s, len, t);
281 : : }
282 : : }
283 [ + + ]: 1663492 : return *result == NULL ? -1 : 0;
284 : : }
285 : :
286 : :
287 : :
288 : : // FSTRING STUFF
289 : :
290 : : /* Fix locations for the given node and its children.
291 : :
292 : : `parent` is the enclosing node.
293 : : `expr_start` is the starting position of the expression (pointing to the open brace).
294 : : `n` is the node which locations are going to be fixed relative to parent.
295 : : `expr_str` is the child node's string representation, including braces.
296 : : */
297 : : static bool
298 : 96068 : fstring_find_expr_location(Token *parent, const char* expr_start, char *expr_str, int *p_lines, int *p_cols)
299 : : {
300 : 96068 : *p_lines = 0;
301 : 96068 : *p_cols = 0;
302 : : assert(expr_start != NULL && *expr_start == '{');
303 [ + - + - ]: 96068 : if (parent && parent->bytes) {
304 : 96068 : const char *parent_str = PyBytes_AsString(parent->bytes);
305 [ - + ]: 96068 : if (!parent_str) {
306 : 0 : return false;
307 : : }
308 : : // The following is needed, in order to correctly shift the column
309 : : // offset, in the case that (disregarding any whitespace) a newline
310 : : // immediately follows the opening curly brace of the fstring expression.
311 : 96068 : bool newline_after_brace = 1;
312 : 96068 : const char *start = expr_start + 1;
313 [ + - + - : 96110 : while (start && *start != '}' && *start != '\n') {
+ + ]
314 [ + + + - : 96103 : if (*start != ' ' && *start != '\t' && *start != '\f') {
+ - ]
315 : 96061 : newline_after_brace = 0;
316 : 96061 : break;
317 : : }
318 : 42 : start++;
319 : : }
320 : :
321 : : // Account for the characters from the last newline character to our
322 : : // left until the beginning of expr_start.
323 [ + + ]: 96068 : if (!newline_after_brace) {
324 : 96061 : start = expr_start;
325 [ + + + + ]: 36137786 : while (start > parent_str && *start != '\n') {
326 : 36041725 : start--;
327 : : }
328 : 96061 : *p_cols += (int)(expr_start - start);
329 [ + + ]: 96061 : if (*start == '\n') {
330 : 489 : *p_cols -= 1;
331 : : }
332 : : }
333 : : /* adjust the start based on the number of newlines encountered
334 : : before the f-string expression */
335 [ + + ]: 36263462 : for (const char *p = parent_str; p < expr_start; p++) {
336 [ + + ]: 36167394 : if (*p == '\n') {
337 : 4707 : (*p_lines)++;
338 : : }
339 : : }
340 : : }
341 : 96068 : return true;
342 : : }
343 : :
344 : :
345 : : /* Compile this expression in to an expr_ty. Add parens around the
346 : : expression, in order to allow leading spaces in the expression. */
347 : : static expr_ty
348 : 96097 : fstring_compile_expr(Parser *p, const char *expr_start, const char *expr_end,
349 : : Token *t)
350 : : {
351 : 96097 : expr_ty expr = NULL;
352 : : char *str;
353 : : Py_ssize_t len;
354 : : const char *s;
355 : 96097 : expr_ty result = NULL;
356 : :
357 : : assert(expr_end >= expr_start);
358 : : assert(*(expr_start-1) == '{');
359 : : assert(*expr_end == '}' || *expr_end == '!' || *expr_end == ':' ||
360 : : *expr_end == '=');
361 : :
362 : : /* If the substring is all whitespace, it's an error. We need to catch this
363 : : here, and not when we call PyParser_SimpleParseStringFlagsFilename,
364 : : because turning the expression '' in to '()' would go from being invalid
365 : : to valid. */
366 [ + + ]: 96219 : for (s = expr_start; s != expr_end; s++) {
367 : 96190 : char c = *s;
368 : : /* The Python parser ignores only the following whitespace
369 : : characters (\r already is converted to \n). */
370 [ + + + + : 96190 : if (!(c == ' ' || c == '\t' || c == '\n' || c == '\f')) {
+ + + + ]
371 : 96068 : break;
372 : : }
373 : : }
374 : :
375 [ + + ]: 96097 : if (s == expr_end) {
376 [ + + + + : 29 : if (*expr_end == '!' || *expr_end == ':' || *expr_end == '=') {
+ + ]
377 : 23 : RAISE_SYNTAX_ERROR("f-string: expression required before '%c'", *expr_end);
378 : 23 : return NULL;
379 : : }
380 : 6 : RAISE_SYNTAX_ERROR("f-string: empty expression not allowed");
381 : 6 : return NULL;
382 : : }
383 : :
384 : 96068 : len = expr_end - expr_start;
385 : : /* Allocate 3 extra bytes: open paren, close paren, null byte. */
386 : 96068 : str = PyMem_Calloc(len + 3, sizeof(char));
387 [ - + ]: 96068 : if (str == NULL) {
388 : : PyErr_NoMemory();
389 : 0 : return NULL;
390 : : }
391 : :
392 : : // The call to fstring_find_expr_location is responsible for finding the column offset
393 : : // the generated AST nodes need to be shifted to the right, which is equal to the number
394 : : // of the f-string characters before the expression starts.
395 : 96068 : memcpy(str+1, expr_start, len);
396 : : int lines, cols;
397 [ - + ]: 96068 : if (!fstring_find_expr_location(t, expr_start-1, str+1, &lines, &cols)) {
398 : 0 : PyMem_Free(str);
399 : 0 : return NULL;
400 : : }
401 : :
402 : : // The parentheses are needed in order to allow for leading whitespace within
403 : : // the f-string expression. This consequently gets parsed as a group (see the
404 : : // group rule in python.gram).
405 : 96068 : str[0] = '(';
406 : 96068 : str[len+1] = ')';
407 : :
408 : 96068 : struct tok_state* tok = _PyTokenizer_FromString(str, 1);
409 [ - + ]: 96068 : if (tok == NULL) {
410 : 0 : PyMem_Free(str);
411 : 0 : return NULL;
412 : : }
413 : 96068 : Py_INCREF(p->tok->filename);
414 : :
415 : 96068 : tok->filename = p->tok->filename;
416 : 96068 : tok->lineno = t->lineno + lines - 1;
417 : :
418 : 96068 : Parser *p2 = _PyPegen_Parser_New(tok, Py_fstring_input, p->flags, p->feature_version,
419 : : NULL, p->arena);
420 : :
421 : 96068 : p2->starting_lineno = t->lineno + lines;
422 [ + + ]: 96068 : p2->starting_col_offset = lines != 0 ? cols : t->col_offset + cols;
423 : :
424 : 96068 : expr = _PyPegen_run_parser(p2);
425 : :
426 [ + + ]: 96068 : if (expr == NULL) {
427 : 16 : goto exit;
428 : : }
429 : 96052 : result = expr;
430 : :
431 : 96068 : exit:
432 : 96068 : PyMem_Free(str);
433 : 96068 : _PyPegen_Parser_Free(p2);
434 : 96068 : _PyTokenizer_Free(tok);
435 : 96068 : return result;
436 : : }
437 : :
438 : : /* Return -1 on error.
439 : :
440 : : Return 0 if we reached the end of the literal.
441 : :
442 : : Return 1 if we haven't reached the end of the literal, but we want
443 : : the caller to process the literal up to this point. Used for
444 : : doubled braces.
445 : : */
446 : : static int
447 : 119721 : fstring_find_literal(Parser *p, const char **str, const char *end, int raw,
448 : : PyObject **literal, int recurse_lvl, Token *t)
449 : : {
450 : : /* Get any literal string. It ends when we hit an un-doubled left
451 : : brace (which isn't part of a unicode name escape such as
452 : : "\N{EULER CONSTANT}"), or the end of the string. */
453 : :
454 : 119721 : const char *s = *str;
455 : 119721 : const char *literal_start = s;
456 : 119721 : int result = 0;
457 : :
458 : : assert(*literal == NULL);
459 [ + + ]: 671363 : while (s < end) {
460 : 649256 : char ch = *s++;
461 [ + + + + : 649256 : if (!raw && ch == '\\' && s < end) {
+ - ]
462 : 3149 : ch = *s++;
463 [ + + ]: 3149 : if (ch == 'N') {
464 : : /* We need to look at and skip matching braces for "\N{name}"
465 : : sequences because otherwise we'll think the opening '{'
466 : : starts an expression, which is not the case with "\N".
467 : : Keep looking for either a matched '{' '}' pair, or the end
468 : : of the string. */
469 : :
470 [ + + + + ]: 27 : if (s < end && *s++ == '{') {
471 [ + + + + ]: 524 : while (s < end && *s++ != '}') {
472 : : }
473 : 24 : continue;
474 : : }
475 : :
476 : : /* This is an invalid "\N" sequence, since it's a "\N" not
477 : : followed by a "{". Just keep parsing this literal. This
478 : : error will be caught later by
479 : : decode_unicode_with_escapes(). */
480 : 3 : continue;
481 : : }
482 [ + + - + ]: 3122 : if (ch == '{' && warn_invalid_escape_sequence(p, s-1, t) < 0) {
483 : 0 : return -1;
484 : : }
485 : : }
486 [ + + + + ]: 649229 : if (ch == '{' || ch == '}') {
487 : : /* Check for doubled braces, but only at the top level. If
488 : : we checked at every level, then f'{0:{3}}' would fail
489 : : with the two closing braces. */
490 [ + + ]: 97614 : if (recurse_lvl == 0) {
491 [ + + + + ]: 96502 : if (s < end && *s == ch) {
492 : : /* We're going to tell the caller that the literal ends
493 : : here, but that they should continue scanning. But also
494 : : skip over the second brace when we resume scanning. */
495 : 509 : *str = s + 1;
496 : 509 : result = 1;
497 : 509 : goto done;
498 : : }
499 : :
500 : : /* Where a single '{' is the start of a new expression, a
501 : : single '}' is not allowed. */
502 [ + + ]: 95993 : if (ch == '}') {
503 : 8 : *str = s - 1;
504 : 8 : RAISE_SYNTAX_ERROR("f-string: single '}' is not allowed");
505 : 8 : return -1;
506 : : }
507 : : }
508 : : /* We're either at a '{', which means we're starting another
509 : : expression; or a '}', which means we're at the end of this
510 : : f-string (for a nested format_spec). */
511 : 97097 : s--;
512 : 97097 : break;
513 : : }
514 : : }
515 : 119204 : *str = s;
516 : : assert(s <= end);
517 : : assert(s == end || *s == '{' || *s == '}');
518 : 119713 : done:
519 [ + + ]: 119713 : if (literal_start != s) {
520 [ + + ]: 101358 : if (raw) {
521 : 358 : *literal = PyUnicode_DecodeUTF8Stateful(literal_start,
522 : : s - literal_start,
523 : : NULL, NULL);
524 : : }
525 : : else {
526 : 101000 : *literal = decode_unicode_with_escapes(p, literal_start,
527 : 101000 : s - literal_start, t);
528 : : }
529 [ + + ]: 101358 : if (!*literal) {
530 : 5 : return -1;
531 : : }
532 : : }
533 : 119708 : return result;
534 : : }
535 : :
536 : : /* Forward declaration because parsing is recursive. */
537 : : static expr_ty
538 : : fstring_parse(Parser *p, const char **str, const char *end, int raw, int recurse_lvl,
539 : : Token *first_token, Token* t, Token *last_token);
540 : :
541 : : /* Parse the f-string at *str, ending at end. We know *str starts an
542 : : expression (so it must be a '{'). Returns the FormattedValue node, which
543 : : includes the expression, conversion character, format_spec expression, and
544 : : optionally the text of the expression (if = is used).
545 : :
546 : : Note that I don't do a perfect job here: I don't make sure that a
547 : : closing brace doesn't match an opening paren, for example. It
548 : : doesn't need to error on all invalid expressions, just correctly
549 : : find the end of all valid ones. Any errors inside the expression
550 : : will be caught when we parse it later.
551 : :
552 : : *expression is set to the expression. For an '=' "debug" expression,
553 : : *expr_text is set to the debug text (the original text of the expression,
554 : : including the '=' and any whitespace around it, as a string object). If
555 : : not a debug expression, *expr_text set to NULL. */
556 : : static int
557 : 96132 : fstring_find_expr(Parser *p, const char **str, const char *end, int raw, int recurse_lvl,
558 : : PyObject **expr_text, expr_ty *expression, Token *first_token,
559 : : Token *t, Token *last_token)
560 : : {
561 : : /* Return -1 on error, else 0. */
562 : :
563 : : const char *expr_start;
564 : : const char *expr_end;
565 : : expr_ty simple_expression;
566 : 96132 : expr_ty format_spec = NULL; /* Optional format specifier. */
567 : 96132 : int conversion = -1; /* The conversion char. Use default if not
568 : : specified, or !r if using = and no format
569 : : spec. */
570 : :
571 : : /* 0 if we're not in a string, else the quote char we're trying to
572 : : match (single or double quote). */
573 : 96132 : char quote_char = 0;
574 : :
575 : : /* If we're inside a string, 1=normal, 3=triple-quoted. */
576 : 96132 : int string_type = 0;
577 : :
578 : : /* Keep track of nesting level for braces/parens/brackets in
579 : : expressions. */
580 : 96132 : Py_ssize_t nested_depth = 0;
581 : : char parenstack[MAXLEVEL];
582 : :
583 : 96132 : *expr_text = NULL;
584 : :
585 : : /* Can only nest one level deep. */
586 [ + + ]: 96132 : if (recurse_lvl >= 2) {
587 : 1 : RAISE_SYNTAX_ERROR("f-string: expressions nested too deeply");
588 : 1 : goto error;
589 : : }
590 : :
591 : : /* The first char must be a left brace, or we wouldn't have gotten
592 : : here. Skip over it. */
593 : : assert(**str == '{');
594 : 96131 : *str += 1;
595 : :
596 : 96131 : expr_start = *str;
597 [ + + ]: 427806 : for (; *str < end; (*str)++) {
598 : : char ch;
599 : :
600 : : /* Loop invariants. */
601 : : assert(nested_depth >= 0);
602 : : assert(*str >= expr_start && *str < end);
603 : : if (quote_char) {
604 : : assert(string_type == 1 || string_type == 3);
605 : : } else {
606 : : assert(string_type == 0);
607 : : }
608 : :
609 : 427791 : ch = **str;
610 : : /* Nowhere inside an expression is a backslash allowed. */
611 [ + + ]: 427791 : if (ch == '\\') {
612 : : /* Error: can't include a backslash character, inside
613 : : parens or strings or not. */
614 : 8 : RAISE_SYNTAX_ERROR(
615 : : "f-string expression part "
616 : : "cannot include a backslash");
617 : 8 : goto error;
618 : : }
619 [ + + ]: 427783 : if (quote_char) {
620 : : /* We're inside a string. See if we're at the end. */
621 : : /* This code needs to implement the same non-error logic
622 : : as tok_get from tokenizer.c, at the letter_quote
623 : : label. To actually share that code would be a
624 : : nightmare. But, it's unlikely to change and is small,
625 : : so duplicate it here. Note we don't need to catch all
626 : : of the errors, since they'll be caught when parsing the
627 : : expression. We just need to match the non-error
628 : : cases. Thus we can ignore \n in single-quoted strings,
629 : : for example. Or non-terminated strings. */
630 [ + + ]: 3337 : if (ch == quote_char) {
631 : : /* Does this match the string_type (single or triple
632 : : quoted)? */
633 [ + + ]: 927 : if (string_type == 3) {
634 [ + - + + : 62 : if (*str+2 < end && *(*str+1) == ch && *(*str+2) == ch) {
+ - ]
635 : : /* We're at the end of a triple quoted string. */
636 : 38 : *str += 2;
637 : 38 : string_type = 0;
638 : 38 : quote_char = 0;
639 : 38 : continue;
640 : : }
641 : : } else {
642 : : /* We're at the end of a normal string. */
643 : 865 : quote_char = 0;
644 : 865 : string_type = 0;
645 : 865 : continue;
646 : : }
647 : : }
648 [ + + + + ]: 424446 : } else if (ch == '\'' || ch == '"') {
649 : : /* Is this a triple quoted string? */
650 [ + + + + : 908 : if (*str+2 < end && *(*str+1) == ch && *(*str+2) == ch) {
+ + ]
651 : 38 : string_type = 3;
652 : 38 : *str += 2;
653 : : } else {
654 : : /* Start of a normal string. */
655 : 870 : string_type = 1;
656 : : }
657 : : /* Start looking for the end of the string. */
658 : 908 : quote_char = ch;
659 [ + + + + : 423538 : } else if (ch == '[' || ch == '{' || ch == '(') {
+ + ]
660 [ + + ]: 3621 : if (nested_depth >= MAXLEVEL) {
661 : 1 : RAISE_SYNTAX_ERROR("f-string: too many nested parenthesis");
662 : 1 : goto error;
663 : : }
664 : 3620 : parenstack[nested_depth] = ch;
665 : 3620 : nested_depth++;
666 [ + + ]: 419917 : } else if (ch == '#') {
667 : : /* Error: can't include a comment character, inside parens
668 : : or not. */
669 : 3 : RAISE_SYNTAX_ERROR("f-string expression part cannot include '#'");
670 : 3 : goto error;
671 [ + + + + ]: 419914 : } else if (nested_depth == 0 &&
672 [ + + + + : 390371 : (ch == '!' || ch == ':' || ch == '}' ||
+ + ]
673 [ + + + + ]: 301148 : ch == '=' || ch == '>' || ch == '<')) {
674 : : /* See if there's a next character. */
675 [ + + ]: 96210 : if (*str+1 < end) {
676 : 89432 : char next = *(*str+1);
677 : :
678 : : /* For "!=". since '=' is not an allowed conversion character,
679 : : nothing is lost in this test. */
680 [ + + + + : 89432 : if ((ch == '!' && next == '=') || /* != */
+ + ]
681 [ + + + + ]: 89414 : (ch == '=' && next == '=') || /* == */
682 [ - + + + ]: 89407 : (ch == '<' && next == '=') || /* <= */
683 [ + + ]: 83 : (ch == '>' && next == '=') /* >= */
684 : : ) {
685 : 31 : *str += 1;
686 : 31 : continue;
687 : : }
688 : : }
689 : : /* Don't get out of the loop for these, if they're single
690 : : chars (not part of 2-char tokens). If by themselves, they
691 : : don't end an expression (unlike say '!'). */
692 [ + + + + ]: 96179 : if (ch == '>' || ch == '<') {
693 : 82 : continue;
694 : : }
695 : :
696 : : /* Normal way out of this loop. */
697 : 96097 : break;
698 [ + + + + : 323704 : } else if (ch == ']' || ch == '}' || ch == ')') {
+ + ]
699 [ + + ]: 3418 : if (!nested_depth) {
700 : 2 : RAISE_SYNTAX_ERROR("f-string: unmatched '%c'", ch);
701 : 2 : goto error;
702 : : }
703 : 3416 : nested_depth--;
704 : 3416 : int opening = (unsigned char)parenstack[nested_depth];
705 [ + + + + : 3418 : if (!((opening == '(' && ch == ')') ||
+ + + + ]
706 [ + + ]: 890 : (opening == '[' && ch == ']') ||
707 [ - + ]: 23 : (opening == '{' && ch == '}')))
708 : : {
709 : 5 : RAISE_SYNTAX_ERROR(
710 : : "f-string: closing parenthesis '%c' "
711 : : "does not match opening parenthesis '%c'",
712 : : ch, opening);
713 : 5 : goto error;
714 : : }
715 : : } else {
716 : : /* Just consume this char and loop around. */
717 : : }
718 : : }
719 : 96112 : expr_end = *str;
720 : : /* If we leave the above loop in a string or with mismatched parens, we
721 : : don't really care. We'll get a syntax error when compiling the
722 : : expression. But, we can produce a better error message, so let's just
723 : : do that.*/
724 [ + + ]: 96112 : if (quote_char) {
725 : 4 : RAISE_SYNTAX_ERROR("f-string: unterminated string");
726 : 4 : goto error;
727 : : }
728 [ - + ]: 96108 : if (nested_depth) {
729 : 0 : int opening = (unsigned char)parenstack[nested_depth - 1];
730 : 0 : RAISE_SYNTAX_ERROR("f-string: unmatched '%c'", opening);
731 : 0 : goto error;
732 : : }
733 : :
734 [ + + ]: 96108 : if (*str >= end) {
735 : 11 : goto unexpected_end_of_string;
736 : : }
737 : :
738 : : /* Compile the expression as soon as possible, so we show errors
739 : : related to the expression before errors related to the
740 : : conversion or format_spec. */
741 : 96097 : simple_expression = fstring_compile_expr(p, expr_start, expr_end, t);
742 [ + + ]: 96097 : if (!simple_expression) {
743 : 45 : goto error;
744 : : }
745 : :
746 : : /* Check for =, which puts the text value of the expression in
747 : : expr_text. */
748 [ + + ]: 96052 : if (**str == '=') {
749 [ + + ]: 169 : if (p->feature_version < 8) {
750 : 1 : RAISE_SYNTAX_ERROR("f-string: self documenting expressions are "
751 : : "only supported in Python 3.8 and greater");
752 : 1 : goto error;
753 : : }
754 : 168 : *str += 1;
755 : :
756 : : /* Skip over ASCII whitespace. No need to test for end of string
757 : : here, since we know there's at least a trailing quote somewhere
758 : : ahead. */
759 [ + + ]: 178 : while (Py_ISSPACE(**str)) {
760 : 10 : *str += 1;
761 : : }
762 [ + + ]: 168 : if (*str >= end) {
763 : 1 : goto unexpected_end_of_string;
764 : : }
765 : : /* Set *expr_text to the text of the expression. */
766 : 167 : *expr_text = PyUnicode_FromStringAndSize(expr_start, *str-expr_start);
767 [ - + ]: 167 : if (!*expr_text) {
768 : 0 : goto error;
769 : : }
770 : : }
771 : :
772 : : /* Check for a conversion char, if present. */
773 [ + + ]: 96050 : if (**str == '!') {
774 : 6921 : *str += 1;
775 : 6921 : const char *conv_start = *str;
776 : : while (1) {
777 [ + + ]: 13852 : if (*str >= end) {
778 : 5 : goto unexpected_end_of_string;
779 : : }
780 [ + + + + ]: 13847 : if (**str == '}' || **str == ':') {
781 : : break;
782 : : }
783 : 6931 : *str += 1;
784 : : }
785 [ + + ]: 6916 : if (*str == conv_start) {
786 : 3 : RAISE_SYNTAX_ERROR(
787 : : "f-string: missed conversion character");
788 : 3 : goto error;
789 : : }
790 : :
791 : 6913 : conversion = (unsigned char)*conv_start;
792 : : /* Validate the conversion. */
793 [ + + + + ]: 6913 : if ((*str != conv_start + 1) ||
794 [ + + + + ]: 6816 : !(conversion == 's' || conversion == 'r' || conversion == 'a'))
795 : : {
796 : 16 : PyObject *conv_obj = PyUnicode_FromStringAndSize(conv_start,
797 : 16 : *str-conv_start);
798 [ + - ]: 16 : if (conv_obj) {
799 : 16 : RAISE_SYNTAX_ERROR(
800 : : "f-string: invalid conversion character %R: "
801 : : "expected 's', 'r', or 'a'",
802 : : conv_obj);
803 : 16 : Py_DECREF(conv_obj);
804 : : }
805 : 16 : goto error;
806 : : }
807 : :
808 : : }
809 : :
810 : : /* Check for the format spec, if present. */
811 : : assert(*str < end);
812 [ + + ]: 96026 : if (**str == ':') {
813 : 974 : *str += 1;
814 [ + + ]: 974 : if (*str >= end) {
815 : 2 : goto unexpected_end_of_string;
816 : : }
817 : :
818 : : /* Parse the format spec. */
819 : 972 : format_spec = fstring_parse(p, str, end, raw, recurse_lvl+1,
820 : : first_token, t, last_token);
821 [ + + ]: 972 : if (!format_spec) {
822 : 7 : goto error;
823 : : }
824 : : }
825 : :
826 [ + - + + ]: 96017 : if (*str >= end || **str != '}') {
827 : 1 : goto unexpected_end_of_string;
828 : : }
829 : :
830 : : /* We're at a right brace. Consume it. */
831 : : assert(*str < end);
832 : : assert(**str == '}');
833 : 96016 : *str += 1;
834 : :
835 : : /* If we're in = mode (detected by non-NULL expr_text), and have no format
836 : : spec and no explicit conversion, set the conversion to 'r'. */
837 [ + + + + : 96016 : if (*expr_text && format_spec == NULL && conversion == -1) {
+ + ]
838 : 62 : conversion = 'r';
839 : : }
840 : :
841 : : /* And now create the FormattedValue node that represents this
842 : : entire expression with the conversion and format spec. */
843 : : //TODO: Fix this
844 : 96016 : *expression = _PyAST_FormattedValue(simple_expression, conversion,
845 : : format_spec, first_token->lineno,
846 : : first_token->col_offset,
847 : : last_token->end_lineno,
848 : : last_token->end_col_offset, p->arena);
849 [ - + ]: 96016 : if (!*expression) {
850 : 0 : goto error;
851 : : }
852 : :
853 : 96016 : return 0;
854 : :
855 : 20 : unexpected_end_of_string:
856 : 20 : RAISE_SYNTAX_ERROR("f-string: expecting '}'");
857 : : /* Falls through to error. */
858 : :
859 : 116 : error:
860 : 116 : Py_XDECREF(*expr_text);
861 : 116 : return -1;
862 : :
863 : : }
864 : :
865 : : /* Return -1 on error.
866 : :
867 : : Return 0 if we have a literal (possible zero length) and an
868 : : expression (zero length if at the end of the string.
869 : :
870 : : Return 1 if we have a literal, but no expression, and we want the
871 : : caller to call us again. This is used to deal with doubled
872 : : braces.
873 : :
874 : : When called multiple times on the string 'a{{b{0}c', this function
875 : : will return:
876 : :
877 : : 1. the literal 'a{' with no expression, and a return value
878 : : of 1. Despite the fact that there's no expression, the return
879 : : value of 1 means we're not finished yet.
880 : :
881 : : 2. the literal 'b' and the expression '0', with a return value of
882 : : 0. The fact that there's an expression means we're not finished.
883 : :
884 : : 3. literal 'c' with no expression and a return value of 0. The
885 : : combination of the return value of 0 with no expression means
886 : : we're finished.
887 : : */
888 : : static int
889 : 119721 : fstring_find_literal_and_expr(Parser *p, const char **str, const char *end, int raw,
890 : : int recurse_lvl, PyObject **literal,
891 : : PyObject **expr_text, expr_ty *expression,
892 : : Token *first_token, Token *t, Token *last_token)
893 : : {
894 : : int result;
895 : :
896 : : assert(*literal == NULL && *expression == NULL);
897 : :
898 : : /* Get any literal string. */
899 : 119721 : result = fstring_find_literal(p, str, end, raw, literal, recurse_lvl, t);
900 [ + + ]: 119721 : if (result < 0) {
901 : 13 : goto error;
902 : : }
903 : :
904 : : assert(result == 0 || result == 1);
905 : :
906 [ + + ]: 119708 : if (result == 1) {
907 : : /* We have a literal, but don't look at the expression. */
908 : 509 : return 1;
909 : : }
910 : :
911 [ + + + + ]: 119199 : if (*str >= end || **str == '}') {
912 : : /* We're at the end of the string or the end of a nested
913 : : f-string: no expression. The top-level error case where we
914 : : expect to be at the end of the string but we're at a '}' is
915 : : handled later. */
916 : 23067 : return 0;
917 : : }
918 : :
919 : : /* We must now be the start of an expression, on a '{'. */
920 : : assert(**str == '{');
921 : :
922 [ + + ]: 96132 : if (fstring_find_expr(p, str, end, raw, recurse_lvl, expr_text,
923 : : expression, first_token, t, last_token) < 0) {
924 : 116 : goto error;
925 : : }
926 : :
927 : 96016 : return 0;
928 : :
929 : 129 : error:
930 [ + + ]: 129 : Py_CLEAR(*literal);
931 : 129 : return -1;
932 : : }
933 : :
934 : : #ifdef NDEBUG
935 : : #define ExprList_check_invariants(l)
936 : : #else
937 : : static void
938 : : ExprList_check_invariants(ExprList *l)
939 : : {
940 : : /* Check our invariants. Make sure this object is "live", and
941 : : hasn't been deallocated. */
942 : : assert(l->size >= 0);
943 : : assert(l->p != NULL);
944 : : if (l->size <= EXPRLIST_N_CACHED) {
945 : : assert(l->data == l->p);
946 : : }
947 : : }
948 : : #endif
949 : :
950 : : static void
951 : 1601789 : ExprList_Init(ExprList *l)
952 : : {
953 : 1601789 : l->allocated = EXPRLIST_N_CACHED;
954 : 1601789 : l->size = 0;
955 : :
956 : : /* Until we start allocating dynamically, p points to data. */
957 : 1601789 : l->p = l->data;
958 : :
959 : : ExprList_check_invariants(l);
960 : 1601789 : }
961 : :
962 : : static int
963 : 196172 : ExprList_Append(ExprList *l, expr_ty exp)
964 : : {
965 : : ExprList_check_invariants(l);
966 [ + + ]: 196172 : if (l->size >= l->allocated) {
967 : : /* We need to alloc (or realloc) the memory. */
968 : 58 : Py_ssize_t new_size = l->allocated * 2;
969 : :
970 : : /* See if we've ever allocated anything dynamically. */
971 [ + + ]: 58 : if (l->p == l->data) {
972 : : Py_ssize_t i;
973 : : /* We're still using the cached data. Switch to
974 : : alloc-ing. */
975 : 15 : l->p = PyMem_Malloc(sizeof(expr_ty) * new_size);
976 [ - + ]: 15 : if (!l->p) {
977 : 0 : return -1;
978 : : }
979 : : /* Copy the cached data into the new buffer. */
980 [ + + ]: 975 : for (i = 0; i < l->size; i++) {
981 : 960 : l->p[i] = l->data[i];
982 : : }
983 : : } else {
984 : : /* Just realloc. */
985 : 43 : expr_ty *tmp = PyMem_Realloc(l->p, sizeof(expr_ty) * new_size);
986 [ - + ]: 43 : if (!tmp) {
987 : 0 : PyMem_Free(l->p);
988 : 0 : l->p = NULL;
989 : 0 : return -1;
990 : : }
991 : 43 : l->p = tmp;
992 : : }
993 : :
994 : 58 : l->allocated = new_size;
995 : : assert(l->allocated == 2 * l->size);
996 : : }
997 : :
998 : 196172 : l->p[l->size++] = exp;
999 : :
1000 : : ExprList_check_invariants(l);
1001 : 196172 : return 0;
1002 : : }
1003 : :
1004 : : static void
1005 : 20110 : ExprList_Dealloc(ExprList *l)
1006 : : {
1007 : : ExprList_check_invariants(l);
1008 : :
1009 : : /* If there's been an error, or we've never dynamically allocated,
1010 : : do nothing. */
1011 [ + - + + ]: 20110 : if (!l->p || l->p == l->data) {
1012 : : /* Do nothing. */
1013 : : } else {
1014 : : /* We have dynamically allocated. Free the memory. */
1015 : 15 : PyMem_Free(l->p);
1016 : : }
1017 : 20110 : l->p = NULL;
1018 : 20110 : l->size = -1;
1019 : 20110 : }
1020 : :
1021 : : static asdl_expr_seq *
1022 : 19336 : ExprList_Finish(ExprList *l, PyArena *arena)
1023 : : {
1024 : : asdl_expr_seq *seq;
1025 : :
1026 : : ExprList_check_invariants(l);
1027 : :
1028 : : /* Allocate the asdl_seq and copy the expressions in to it. */
1029 : 19336 : seq = _Py_asdl_expr_seq_new(l->size, arena);
1030 [ + - ]: 19336 : if (seq) {
1031 : : Py_ssize_t i;
1032 [ + + ]: 215506 : for (i = 0; i < l->size; i++) {
1033 : 196170 : asdl_seq_SET(seq, i, l->p[i]);
1034 : : }
1035 : : }
1036 : 19336 : ExprList_Dealloc(l);
1037 : 19336 : return seq;
1038 : : }
1039 : :
1040 : : #ifdef NDEBUG
1041 : : #define FstringParser_check_invariants(state)
1042 : : #else
1043 : : static void
1044 : : FstringParser_check_invariants(FstringParser *state)
1045 : : {
1046 : : if (state->last_str) {
1047 : : assert(PyUnicode_CheckExact(state->last_str));
1048 : : }
1049 : : ExprList_check_invariants(&state->expr_list);
1050 : : }
1051 : : #endif
1052 : :
1053 : : void
1054 : 1601789 : _PyPegen_FstringParser_Init(FstringParser *state)
1055 : : {
1056 : 1601789 : state->last_str = NULL;
1057 : 1601789 : state->fmode = 0;
1058 : 1601789 : ExprList_Init(&state->expr_list);
1059 : : FstringParser_check_invariants(state);
1060 : 1601789 : }
1061 : :
1062 : : void
1063 : 774 : _PyPegen_FstringParser_Dealloc(FstringParser *state)
1064 : : {
1065 : : FstringParser_check_invariants(state);
1066 : :
1067 : 774 : Py_XDECREF(state->last_str);
1068 : 774 : ExprList_Dealloc(&state->expr_list);
1069 : 774 : }
1070 : :
1071 : : /* Make a Constant node, but decref the PyUnicode object being added. */
1072 : : static expr_ty
1073 : 1633428 : make_str_node_and_del(Parser *p, PyObject **str, Token* first_token, Token *last_token)
1074 : : {
1075 : 1633428 : PyObject *s = *str;
1076 : 1633428 : PyObject *kind = NULL;
1077 : 1633428 : *str = NULL;
1078 : : assert(PyUnicode_CheckExact(s));
1079 [ - + ]: 1633428 : if (_PyArena_AddPyObject(p->arena, s) < 0) {
1080 : 0 : Py_DECREF(s);
1081 : 0 : return NULL;
1082 : : }
1083 : 1633428 : const char* the_str = PyBytes_AsString(first_token->bytes);
1084 [ + - + + ]: 1633428 : if (the_str && the_str[0] == 'u') {
1085 : 844 : kind = _PyPegen_new_identifier(p, "u");
1086 : : }
1087 : :
1088 [ + + - + ]: 1633428 : if (kind == NULL && PyErr_Occurred()) {
1089 : 0 : return NULL;
1090 : : }
1091 : :
1092 : 1633428 : return _PyAST_Constant(s, kind, first_token->lineno, first_token->col_offset,
1093 : : last_token->end_lineno, last_token->end_col_offset,
1094 : : p->arena);
1095 : :
1096 : : }
1097 : :
1098 : :
1099 : : /* Add a non-f-string (that is, a regular literal string). str is
1100 : : decref'd. */
1101 : : int
1102 : 1712527 : _PyPegen_FstringParser_ConcatAndDel(FstringParser *state, PyObject *str)
1103 : : {
1104 : : FstringParser_check_invariants(state);
1105 : :
1106 : : assert(PyUnicode_CheckExact(str));
1107 : :
1108 [ + + ]: 1712527 : if (PyUnicode_GET_LENGTH(str) == 0) {
1109 : 100534 : Py_DECREF(str);
1110 : 100534 : return 0;
1111 : : }
1112 : :
1113 [ + + ]: 1611993 : if (!state->last_str) {
1114 : : /* We didn't have a string before, so just remember this one. */
1115 : 1532956 : state->last_str = str;
1116 : : } else {
1117 : : /* Concatenate this with the previous string. */
1118 : 79037 : PyUnicode_AppendAndDel(&state->last_str, str);
1119 [ - + ]: 79037 : if (!state->last_str) {
1120 : 0 : return -1;
1121 : : }
1122 : : }
1123 : : FstringParser_check_invariants(state);
1124 : 1611993 : return 0;
1125 : : }
1126 : :
1127 : : /* Parse an f-string. The f-string is in *str to end, with no
1128 : : 'f' or quotes. */
1129 : : int
1130 : 23196 : _PyPegen_FstringParser_ConcatFstring(Parser *p, FstringParser *state, const char **str,
1131 : : const char *end, int raw, int recurse_lvl,
1132 : : Token *first_token, Token* t, Token *last_token)
1133 : : {
1134 : : FstringParser_check_invariants(state);
1135 : 23196 : state->fmode = 1;
1136 : :
1137 : : /* Parse the f-string. */
1138 : 96525 : while (1) {
1139 : 119721 : PyObject *literal = NULL;
1140 : 119721 : PyObject *expr_text = NULL;
1141 : 119721 : expr_ty expression = NULL;
1142 : :
1143 : : /* If there's a zero length literal in front of the
1144 : : expression, literal will be NULL. If we're at the end of
1145 : : the f-string, expression will be NULL (unless result == 1,
1146 : : see below). */
1147 : 119721 : int result = fstring_find_literal_and_expr(p, str, end, raw, recurse_lvl,
1148 : : &literal, &expr_text,
1149 : : &expression, first_token, t, last_token);
1150 [ + + ]: 119721 : if (result < 0) {
1151 : 129 : return -1;
1152 : : }
1153 : :
1154 : : /* Add the literal, if any. */
1155 [ + + - + ]: 119592 : if (literal && _PyPegen_FstringParser_ConcatAndDel(state, literal) < 0) {
1156 : 0 : Py_XDECREF(expr_text);
1157 : 0 : return -1;
1158 : : }
1159 : : /* Add the expr_text, if any. */
1160 [ + + - + ]: 119592 : if (expr_text && _PyPegen_FstringParser_ConcatAndDel(state, expr_text) < 0) {
1161 : 0 : return -1;
1162 : : }
1163 : :
1164 : : /* We've dealt with the literal and expr_text, their ownership has
1165 : : been transferred to the state object. Don't look at them again. */
1166 : :
1167 : : /* See if we should just loop around to get the next literal
1168 : : and expression, while ignoring the expression this
1169 : : time. This is used for un-doubling braces, as an
1170 : : optimization. */
1171 [ + + ]: 119592 : if (result == 1) {
1172 : 509 : continue;
1173 : : }
1174 : :
1175 [ + + ]: 119083 : if (!expression) {
1176 : : /* We're done with this f-string. */
1177 : 23067 : break;
1178 : : }
1179 : :
1180 : : /* We know we have an expression. Convert any existing string
1181 : : to a Constant node. */
1182 [ + + ]: 96016 : if (state->last_str) {
1183 : : /* Convert the existing last_str literal to a Constant node. */
1184 : 89559 : expr_ty last_str = make_str_node_and_del(p, &state->last_str, first_token, last_token);
1185 [ + - - + ]: 89559 : if (!last_str || ExprList_Append(&state->expr_list, last_str) < 0) {
1186 : 0 : return -1;
1187 : : }
1188 : : }
1189 : :
1190 [ - + ]: 96016 : if (ExprList_Append(&state->expr_list, expression) < 0) {
1191 : 0 : return -1;
1192 : : }
1193 : : }
1194 : :
1195 : : /* If recurse_lvl is zero, then we must be at the end of the
1196 : : string. Otherwise, we must be at a right brace. */
1197 : :
1198 [ + + - + ]: 23067 : if (recurse_lvl == 0 && *str < end-1) {
1199 : 0 : RAISE_SYNTAX_ERROR("f-string: unexpected end of string");
1200 : 0 : return -1;
1201 : : }
1202 [ + + + + ]: 23067 : if (recurse_lvl != 0 && **str != '}') {
1203 : 2 : RAISE_SYNTAX_ERROR("f-string: expecting '}'");
1204 : 2 : return -1;
1205 : : }
1206 : :
1207 : : FstringParser_check_invariants(state);
1208 : 23065 : return 0;
1209 : : }
1210 : :
1211 : : /* Convert the partial state reflected in last_str and expr_list to an
1212 : : expr_ty. The expr_ty can be a Constant, or a JoinedStr. */
1213 : : expr_ty
1214 : 1552608 : _PyPegen_FstringParser_Finish(Parser *p, FstringParser *state, Token* first_token,
1215 : : Token *last_token)
1216 : : {
1217 : : asdl_expr_seq *seq;
1218 : :
1219 : : FstringParser_check_invariants(state);
1220 : :
1221 : : /* If we're just a constant string with no expressions, return
1222 : : that. */
1223 [ + + ]: 1552608 : if (!state->fmode) {
1224 : : assert(!state->expr_list.size);
1225 [ + + ]: 1533272 : if (!state->last_str) {
1226 : : /* Create a zero length string. */
1227 : 100478 : state->last_str = PyUnicode_FromStringAndSize(NULL, 0);
1228 [ - + ]: 100478 : if (!state->last_str) {
1229 : 0 : goto error;
1230 : : }
1231 : : }
1232 : 1533272 : return make_str_node_and_del(p, &state->last_str, first_token, last_token);
1233 : : }
1234 : :
1235 : : /* Create a Constant node out of last_str, if needed. It will be the
1236 : : last node in our expression list. */
1237 [ + + ]: 19336 : if (state->last_str) {
1238 : 10597 : expr_ty str = make_str_node_and_del(p, &state->last_str, first_token, last_token);
1239 [ + - - + ]: 10597 : if (!str || ExprList_Append(&state->expr_list, str) < 0) {
1240 : 0 : goto error;
1241 : : }
1242 : : }
1243 : : /* This has already been freed. */
1244 : : assert(state->last_str == NULL);
1245 : :
1246 : 19336 : seq = ExprList_Finish(&state->expr_list, p->arena);
1247 [ - + ]: 19336 : if (!seq) {
1248 : 0 : goto error;
1249 : : }
1250 : :
1251 : 19336 : return _PyAST_JoinedStr(seq, first_token->lineno, first_token->col_offset,
1252 : : last_token->end_lineno, last_token->end_col_offset,
1253 : : p->arena);
1254 : :
1255 : 0 : error:
1256 : 0 : _PyPegen_FstringParser_Dealloc(state);
1257 : 0 : return NULL;
1258 : : }
1259 : :
1260 : : /* Given an f-string (with no 'f' or quotes) that's in *str and ends
1261 : : at end, parse it into an expr_ty. Return NULL on error. Adjust
1262 : : str to point past the parsed portion. */
1263 : : static expr_ty
1264 : 972 : fstring_parse(Parser *p, const char **str, const char *end, int raw,
1265 : : int recurse_lvl, Token *first_token, Token* t, Token *last_token)
1266 : : {
1267 : : FstringParser state;
1268 : :
1269 : 972 : _PyPegen_FstringParser_Init(&state);
1270 [ + + ]: 972 : if (_PyPegen_FstringParser_ConcatFstring(p, &state, str, end, raw, recurse_lvl,
1271 : : first_token, t, last_token) < 0) {
1272 : 7 : _PyPegen_FstringParser_Dealloc(&state);
1273 : 7 : return NULL;
1274 : : }
1275 : :
1276 : 965 : return _PyPegen_FstringParser_Finish(p, &state, t, t);
1277 : : }
|