Branch data Line data Source code
1 : : #include <Python.h>
2 : : #include "pycore_ast.h" // _PyAST_Validate(),
3 : : #include <errcode.h>
4 : :
5 : : #include "tokenizer.h"
6 : : #include "pegen.h"
7 : :
8 : : // Internal parser functions
9 : :
10 : : asdl_stmt_seq*
11 : 14 : _PyPegen_interactive_exit(Parser *p)
12 : : {
13 [ + - ]: 14 : if (p->errcode) {
14 : 14 : *(p->errcode) = E_EOF;
15 : : }
16 : 14 : return NULL;
17 : : }
18 : :
19 : : Py_ssize_t
20 : 3877 : _PyPegen_byte_offset_to_character_offset(PyObject *line, Py_ssize_t col_offset)
21 : : {
22 : 3877 : const char *str = PyUnicode_AsUTF8(line);
23 [ - + ]: 3877 : if (!str) {
24 : 0 : return -1;
25 : : }
26 : 3877 : Py_ssize_t len = strlen(str);
27 [ + + ]: 3877 : if (col_offset > len + 1) {
28 : 8 : col_offset = len + 1;
29 : : }
30 : : assert(col_offset >= 0);
31 : 3877 : PyObject *text = PyUnicode_DecodeUTF8(str, col_offset, "replace");
32 [ - + ]: 3877 : if (!text) {
33 : 0 : return -1;
34 : : }
35 : 3877 : Py_ssize_t size = PyUnicode_GET_LENGTH(text);
36 : 3877 : Py_DECREF(text);
37 : 3877 : return size;
38 : : }
39 : :
40 : : // Here, mark is the start of the node, while p->mark is the end.
41 : : // If node==NULL, they should be the same.
42 : : int
43 : 194514777 : _PyPegen_insert_memo(Parser *p, int mark, int type, void *node)
44 : : {
45 : : // Insert in front
46 : 194514777 : Memo *m = _PyArena_Malloc(p->arena, sizeof(Memo));
47 [ - + ]: 194514777 : if (m == NULL) {
48 : 0 : return -1;
49 : : }
50 : 194514777 : m->type = type;
51 : 194514777 : m->node = node;
52 : 194514777 : m->mark = p->mark;
53 : 194514777 : m->next = p->tokens[mark]->memo;
54 : 194514777 : p->tokens[mark]->memo = m;
55 : 194514777 : return 0;
56 : : }
57 : :
58 : : // Like _PyPegen_insert_memo(), but updates an existing node if found.
59 : : int
60 : 170488319 : _PyPegen_update_memo(Parser *p, int mark, int type, void *node)
61 : : {
62 [ + + ]: 853361249 : for (Memo *m = p->tokens[mark]->memo; m != NULL; m = m->next) {
63 [ + + ]: 761854285 : if (m->type == type) {
64 : : // Update existing node.
65 : 78981355 : m->node = node;
66 : 78981355 : m->mark = p->mark;
67 : 78981355 : return 0;
68 : : }
69 : : }
70 : : // Insert new node.
71 : 91506964 : return _PyPegen_insert_memo(p, mark, type, node);
72 : : }
73 : :
74 : : static int
75 : 589 : init_normalization(Parser *p)
76 : : {
77 [ + + ]: 589 : if (p->normalize) {
78 : 534 : return 1;
79 : : }
80 : 55 : p->normalize = _PyImport_GetModuleAttrString("unicodedata", "normalize");
81 [ - + ]: 55 : if (!p->normalize)
82 : : {
83 : 0 : return 0;
84 : : }
85 : 55 : return 1;
86 : : }
87 : :
88 : : static int
89 : 222224 : growable_comment_array_init(growable_comment_array *arr, size_t initial_size) {
90 : : assert(initial_size > 0);
91 : 222224 : arr->items = PyMem_Malloc(initial_size * sizeof(*arr->items));
92 : 222224 : arr->size = initial_size;
93 : 222224 : arr->num_items = 0;
94 : :
95 : 222224 : return arr->items != NULL;
96 : : }
97 : :
98 : : static int
99 : 74 : growable_comment_array_add(growable_comment_array *arr, int lineno, char *comment) {
100 [ - + ]: 74 : if (arr->num_items >= arr->size) {
101 : 0 : size_t new_size = arr->size * 2;
102 : 0 : void *new_items_array = PyMem_Realloc(arr->items, new_size * sizeof(*arr->items));
103 [ # # ]: 0 : if (!new_items_array) {
104 : 0 : return 0;
105 : : }
106 : 0 : arr->items = new_items_array;
107 : 0 : arr->size = new_size;
108 : : }
109 : :
110 : 74 : arr->items[arr->num_items].lineno = lineno;
111 : 74 : arr->items[arr->num_items].comment = comment; // Take ownership
112 : 74 : arr->num_items++;
113 : 74 : return 1;
114 : : }
115 : :
116 : : static void
117 : 222224 : growable_comment_array_deallocate(growable_comment_array *arr) {
118 [ + + ]: 222298 : for (unsigned i = 0; i < arr->num_items; i++) {
119 : 74 : PyMem_Free(arr->items[i].comment);
120 : : }
121 : 222224 : PyMem_Free(arr->items);
122 : 222224 : }
123 : :
124 : : static int
125 : 12380231 : _get_keyword_or_name_type(Parser *p, const char *name, int name_len)
126 : : {
127 : : assert(name_len > 0);
128 [ + + ]: 12380231 : if (name_len >= p->n_keyword_lists ||
129 [ + - ]: 10138034 : p->keywords[name_len] == NULL ||
130 [ + + ]: 10138034 : p->keywords[name_len]->type == -1) {
131 : 3937388 : return NAME;
132 : : }
133 [ + - + + ]: 45096198 : for (KeywordToken *k = p->keywords[name_len]; k != NULL && k->type != -1; k++) {
134 [ + + ]: 39141292 : if (strncmp(k->str, name, name_len) == 0) {
135 : 2487937 : return k->type;
136 : : }
137 : : }
138 : 5954906 : return NAME;
139 : : }
140 : :
141 : : static int
142 : 39430438 : initialize_token(Parser *p, Token *token, const char *start, const char *end, int token_type) {
143 : : assert(token != NULL);
144 : :
145 [ + + ]: 39430438 : token->type = (token_type == NAME) ? _get_keyword_or_name_type(p, start, (int)(end - start)) : token_type;
146 : 39430438 : token->bytes = PyBytes_FromStringAndSize(start, end - start);
147 [ - + ]: 39430438 : if (token->bytes == NULL) {
148 : 0 : return -1;
149 : : }
150 : :
151 [ - + ]: 39430438 : if (_PyArena_AddPyObject(p->arena, token->bytes) < 0) {
152 : 0 : Py_DECREF(token->bytes);
153 : 0 : return -1;
154 : : }
155 : :
156 : 39430438 : token->level = p->tok->level;
157 : :
158 [ + + ]: 39430438 : const char *line_start = token_type == STRING ? p->tok->multi_line_start : p->tok->line_start;
159 [ + + ]: 39430438 : int lineno = token_type == STRING ? p->tok->first_lineno : p->tok->lineno;
160 : 39430438 : int end_lineno = p->tok->lineno;
161 : :
162 [ + + + - ]: 39430438 : int col_offset = (start != NULL && start >= line_start) ? (int)(start - line_start) : -1;
163 [ + + + - ]: 39430438 : int end_col_offset = (end != NULL && end >= p->tok->line_start) ? (int)(end - p->tok->line_start) : -1;
164 : :
165 : 39430438 : token->lineno = lineno;
166 [ + + ]: 39430438 : token->col_offset = p->tok->lineno == p->starting_lineno ? p->starting_col_offset + col_offset : col_offset;
167 : 39430438 : token->end_lineno = end_lineno;
168 [ + + ]: 39430438 : token->end_col_offset = p->tok->lineno == p->starting_lineno ? p->starting_col_offset + end_col_offset : end_col_offset;
169 : :
170 : 39430438 : p->fill += 1;
171 : :
172 [ + + + + ]: 39430438 : if (token_type == ERRORTOKEN && p->tok->done == E_DECODE) {
173 : 7 : return _Pypegen_raise_decode_error(p);
174 : : }
175 : :
176 [ + + ]: 39430431 : return (token_type == ERRORTOKEN ? _Pypegen_tokenizer_error(p) : 0);
177 : : }
178 : :
179 : : static int
180 : 759469 : _resize_tokens_array(Parser *p) {
181 : 759469 : int newsize = p->size * 2;
182 : 759469 : Token **new_tokens = PyMem_Realloc(p->tokens, newsize * sizeof(Token *));
183 [ - + ]: 759469 : if (new_tokens == NULL) {
184 : : PyErr_NoMemory();
185 : 0 : return -1;
186 : : }
187 : 759469 : p->tokens = new_tokens;
188 : :
189 [ + + ]: 57267623 : for (int i = p->size; i < newsize; i++) {
190 : 56508154 : p->tokens[i] = PyMem_Calloc(1, sizeof(Token));
191 [ - + ]: 56508154 : if (p->tokens[i] == NULL) {
192 : 0 : p->size = i; // Needed, in order to cleanup correctly after parser fails
193 : : PyErr_NoMemory();
194 : 0 : return -1;
195 : : }
196 : : }
197 : 759469 : p->size = newsize;
198 : 759469 : return 0;
199 : : }
200 : :
201 : : int
202 : 39430438 : _PyPegen_fill_token(Parser *p)
203 : : {
204 : : const char *start;
205 : : const char *end;
206 : 39430438 : int type = _PyTokenizer_Get(p->tok, &start, &end);
207 : :
208 : : // Record and skip '# type: ignore' comments
209 [ + + ]: 39430512 : while (type == TYPE_IGNORE) {
210 : 74 : Py_ssize_t len = end - start;
211 : 74 : char *tag = PyMem_Malloc(len + 1);
212 [ - + ]: 74 : if (tag == NULL) {
213 : : PyErr_NoMemory();
214 : 0 : return -1;
215 : : }
216 : 74 : strncpy(tag, start, len);
217 : 74 : tag[len] = '\0';
218 : : // Ownership of tag passes to the growable array
219 [ - + ]: 74 : if (!growable_comment_array_add(&p->type_ignore_comments, p->tok->lineno, tag)) {
220 : : PyErr_NoMemory();
221 : 0 : return -1;
222 : : }
223 : 74 : type = _PyTokenizer_Get(p->tok, &start, &end);
224 : : }
225 : :
226 : : // If we have reached the end and we are in single input mode we need to insert a newline and reset the parsing
227 [ + + + + : 39430438 : if (p->start_rule == Py_single_input && type == ENDMARKER && p->parsing_started) {
+ + ]
228 : 809 : type = NEWLINE; /* Add an extra newline */
229 : 809 : p->parsing_started = 0;
230 : :
231 [ + + + + ]: 809 : if (p->tok->indent && !(p->flags & PyPARSE_DONT_IMPLY_DEDENT)) {
232 : 9 : p->tok->pendin = -p->tok->indent;
233 : 9 : p->tok->indent = 0;
234 : : }
235 : : }
236 : : else {
237 : 39429629 : p->parsing_started = 1;
238 : : }
239 : :
240 : : // Check if we are at the limit of the token array capacity and resize if needed
241 [ + + - + ]: 39430438 : if ((p->fill == p->size) && (_resize_tokens_array(p) != 0)) {
242 : 0 : return -1;
243 : : }
244 : :
245 : 39430438 : Token *t = p->tokens[p->fill];
246 : 39430438 : return initialize_token(p, t, start, end, type);
247 : : }
248 : :
249 : : #if defined(Py_DEBUG)
250 : : // Instrumentation to count the effectiveness of memoization.
251 : : // The array counts the number of tokens skipped by memoization,
252 : : // indexed by type.
253 : :
254 : : #define NSTATISTICS 2000
255 : : static long memo_statistics[NSTATISTICS];
256 : :
257 : : void
258 : : _PyPegen_clear_memo_statistics()
259 : : {
260 : : for (int i = 0; i < NSTATISTICS; i++) {
261 : : memo_statistics[i] = 0;
262 : : }
263 : : }
264 : :
265 : : PyObject *
266 : : _PyPegen_get_memo_statistics()
267 : : {
268 : : PyObject *ret = PyList_New(NSTATISTICS);
269 : : if (ret == NULL) {
270 : : return NULL;
271 : : }
272 : : for (int i = 0; i < NSTATISTICS; i++) {
273 : : PyObject *value = PyLong_FromLong(memo_statistics[i]);
274 : : if (value == NULL) {
275 : : Py_DECREF(ret);
276 : : return NULL;
277 : : }
278 : : // PyList_SetItem borrows a reference to value.
279 : : if (PyList_SetItem(ret, i, value) < 0) {
280 : : Py_DECREF(ret);
281 : : return NULL;
282 : : }
283 : : }
284 : : return ret;
285 : : }
286 : : #endif
287 : :
288 : : int // bool
289 : 746483324 : _PyPegen_is_memoized(Parser *p, int type, void *pres)
290 : : {
291 [ + + ]: 746483324 : if (p->mark == p->fill) {
292 [ + + ]: 3633016 : if (_PyPegen_fill_token(p) < 0) {
293 : 40 : p->error_indicator = 1;
294 : 40 : return -1;
295 : : }
296 : : }
297 : :
298 : 746483284 : Token *t = p->tokens[p->mark];
299 : :
300 [ + + ]: 2308675290 : for (Memo *m = t->memo; m != NULL; m = m->next) {
301 [ + + ]: 2122950555 : if (m->type == type) {
302 : : #if defined(PY_DEBUG)
303 : : if (0 <= type && type < NSTATISTICS) {
304 : : long count = m->mark - p->mark;
305 : : // A memoized negative result counts for one.
306 : : if (count <= 0) {
307 : : count = 1;
308 : : }
309 : : memo_statistics[type] += count;
310 : : }
311 : : #endif
312 : 560758549 : p->mark = m->mark;
313 : 560758549 : *(void **)(pres) = m->node;
314 : 560758549 : return 1;
315 : : }
316 : : }
317 : 185724735 : return 0;
318 : : }
319 : :
320 : : int
321 : 1 : _PyPegen_lookahead_with_name(int positive, expr_ty (func)(Parser *), Parser *p)
322 : : {
323 : 1 : int mark = p->mark;
324 : 1 : void *res = func(p);
325 : 1 : p->mark = mark;
326 : 1 : return (res != NULL) == positive;
327 : : }
328 : :
329 : : int
330 : 3700 : _PyPegen_lookahead_with_string(int positive, expr_ty (func)(Parser *, const char*), Parser *p, const char* arg)
331 : : {
332 : 3700 : int mark = p->mark;
333 : 3700 : void *res = func(p, arg);
334 : 3700 : p->mark = mark;
335 : 3700 : return (res != NULL) == positive;
336 : : }
337 : :
338 : : int
339 : 53692642 : _PyPegen_lookahead_with_int(int positive, Token *(func)(Parser *, int), Parser *p, int arg)
340 : : {
341 : 53692642 : int mark = p->mark;
342 : 53692642 : void *res = func(p, arg);
343 : 53692642 : p->mark = mark;
344 : 53692642 : return (res != NULL) == positive;
345 : : }
346 : :
347 : : int
348 : 36472518 : _PyPegen_lookahead(int positive, void *(func)(Parser *), Parser *p)
349 : : {
350 : 36472518 : int mark = p->mark;
351 : 36472518 : void *res = (void*)func(p);
352 : 36472518 : p->mark = mark;
353 : 36472518 : return (res != NULL) == positive;
354 : : }
355 : :
356 : : Token *
357 : 756782594 : _PyPegen_expect_token(Parser *p, int type)
358 : : {
359 [ + + ]: 756782594 : if (p->mark == p->fill) {
360 [ + + ]: 26717749 : if (_PyPegen_fill_token(p) < 0) {
361 : 166 : p->error_indicator = 1;
362 : 166 : return NULL;
363 : : }
364 : : }
365 : 756782428 : Token *t = p->tokens[p->mark];
366 [ + + ]: 756782428 : if (t->type != type) {
367 : 660052471 : return NULL;
368 : : }
369 : 96729957 : p->mark += 1;
370 : 96729957 : return t;
371 : : }
372 : :
373 : : void*
374 : 0 : _PyPegen_expect_forced_result(Parser *p, void* result, const char* expected) {
375 : :
376 [ # # ]: 0 : if (p->error_indicator == 1) {
377 : 0 : return NULL;
378 : : }
379 [ # # ]: 0 : if (result == NULL) {
380 : 0 : RAISE_SYNTAX_ERROR("expected (%s)", expected);
381 : 0 : return NULL;
382 : : }
383 : 0 : return result;
384 : : }
385 : :
386 : : Token *
387 : 847612 : _PyPegen_expect_forced_token(Parser *p, int type, const char* expected) {
388 : :
389 [ - + ]: 847612 : if (p->error_indicator == 1) {
390 : 0 : return NULL;
391 : : }
392 : :
393 [ + + ]: 847612 : if (p->mark == p->fill) {
394 [ - + ]: 465257 : if (_PyPegen_fill_token(p) < 0) {
395 : 0 : p->error_indicator = 1;
396 : 0 : return NULL;
397 : : }
398 : : }
399 : 847612 : Token *t = p->tokens[p->mark];
400 [ + + ]: 847612 : if (t->type != type) {
401 : 11 : RAISE_SYNTAX_ERROR_KNOWN_LOCATION(t, "expected '%s'", expected);
402 : 11 : return NULL;
403 : : }
404 : 847601 : p->mark += 1;
405 : 847601 : return t;
406 : : }
407 : :
408 : : expr_ty
409 : 3003077 : _PyPegen_expect_soft_keyword(Parser *p, const char *keyword)
410 : : {
411 [ + + ]: 3003077 : if (p->mark == p->fill) {
412 [ - + ]: 3431 : if (_PyPegen_fill_token(p) < 0) {
413 : 0 : p->error_indicator = 1;
414 : 0 : return NULL;
415 : : }
416 : : }
417 : 3003077 : Token *t = p->tokens[p->mark];
418 [ + + ]: 3003077 : if (t->type != NAME) {
419 : 1632139 : return NULL;
420 : : }
421 : 1370938 : const char *s = PyBytes_AsString(t->bytes);
422 [ - + ]: 1370938 : if (!s) {
423 : 0 : p->error_indicator = 1;
424 : 0 : return NULL;
425 : : }
426 [ + + ]: 1370938 : if (strcmp(s, keyword) != 0) {
427 : 1366081 : return NULL;
428 : : }
429 : 4857 : return _PyPegen_name_token(p);
430 : : }
431 : :
432 : : Token *
433 : 19977442 : _PyPegen_get_last_nonnwhitespace_token(Parser *p)
434 : : {
435 : : assert(p->mark >= 0);
436 : 19977442 : Token *token = NULL;
437 [ + + ]: 22254360 : for (int m = p->mark - 1; m >= 0; m--) {
438 : 22254358 : token = p->tokens[m];
439 [ + - + + : 22254358 : if (token->type != ENDMARKER && (token->type < NEWLINE || token->type > DEDENT)) {
+ + ]
440 : : break;
441 : : }
442 : : }
443 : 19977442 : return token;
444 : : }
445 : :
446 : : PyObject *
447 : 33919542 : _PyPegen_new_identifier(Parser *p, const char *n)
448 : : {
449 : 33919542 : PyObject *id = PyUnicode_DecodeUTF8(n, strlen(n), NULL);
450 [ - + ]: 33919542 : if (!id) {
451 : 0 : goto error;
452 : : }
453 : : /* PyUnicode_DecodeUTF8 should always return a ready string. */
454 : : assert(PyUnicode_IS_READY(id));
455 : : /* Check whether there are non-ASCII characters in the
456 : : identifier; if so, normalize to NFKC. */
457 [ + + ]: 33919542 : if (!PyUnicode_IS_ASCII(id))
458 : : {
459 : : PyObject *id2;
460 [ - + ]: 589 : if (!init_normalization(p))
461 : : {
462 : 0 : Py_DECREF(id);
463 : 1 : goto error;
464 : : }
465 : 589 : PyObject *form = PyUnicode_InternFromString("NFKC");
466 [ - + ]: 589 : if (form == NULL)
467 : : {
468 : 0 : Py_DECREF(id);
469 : 0 : goto error;
470 : : }
471 : 589 : PyObject *args[2] = {form, id};
472 : 589 : id2 = _PyObject_FastCall(p->normalize, args, 2);
473 : 589 : Py_DECREF(id);
474 : 589 : Py_DECREF(form);
475 [ - + ]: 589 : if (!id2) {
476 : 0 : goto error;
477 : : }
478 [ + + ]: 589 : if (!PyUnicode_Check(id2))
479 : : {
480 : 1 : PyErr_Format(PyExc_TypeError,
481 : : "unicodedata.normalize() must return a string, not "
482 : : "%.200s",
483 : : _PyType_Name(Py_TYPE(id2)));
484 : 1 : Py_DECREF(id2);
485 : 1 : goto error;
486 : : }
487 : 588 : id = id2;
488 : : }
489 : 33919541 : PyUnicode_InternInPlace(&id);
490 [ - + ]: 33919541 : if (_PyArena_AddPyObject(p->arena, id) < 0)
491 : : {
492 : 0 : Py_DECREF(id);
493 : 0 : goto error;
494 : : }
495 : 33919541 : return id;
496 : :
497 : 1 : error:
498 : 1 : p->error_indicator = 1;
499 : 1 : return NULL;
500 : : }
501 : :
502 : : static expr_ty
503 : 68829944 : _PyPegen_name_from_token(Parser *p, Token* t)
504 : : {
505 [ + + ]: 68829944 : if (t == NULL) {
506 : 34914042 : return NULL;
507 : : }
508 : 33915902 : const char *s = PyBytes_AsString(t->bytes);
509 [ - + ]: 33915902 : if (!s) {
510 : 0 : p->error_indicator = 1;
511 : 0 : return NULL;
512 : : }
513 : 33915902 : PyObject *id = _PyPegen_new_identifier(p, s);
514 [ + + ]: 33915902 : if (id == NULL) {
515 : 1 : p->error_indicator = 1;
516 : 1 : return NULL;
517 : : }
518 : 33915901 : return _PyAST_Name(id, Load, t->lineno, t->col_offset, t->end_lineno,
519 : : t->end_col_offset, p->arena);
520 : : }
521 : :
522 : : expr_ty
523 : 68829913 : _PyPegen_name_token(Parser *p)
524 : : {
525 : 68829913 : Token *t = _PyPegen_expect_token(p, NAME);
526 : 68829913 : return _PyPegen_name_from_token(p, t);
527 : : }
528 : :
529 : : void *
530 : 17650755 : _PyPegen_string_token(Parser *p)
531 : : {
532 : 17650755 : return _PyPegen_expect_token(p, STRING);
533 : : }
534 : :
535 : 2643 : expr_ty _PyPegen_soft_keyword_token(Parser *p) {
536 : 2643 : Token *t = _PyPegen_expect_token(p, NAME);
537 [ + + ]: 2643 : if (t == NULL) {
538 : 2002 : return NULL;
539 : : }
540 : : char *the_token;
541 : : Py_ssize_t size;
542 : 641 : PyBytes_AsStringAndSize(t->bytes, &the_token, &size);
543 [ + + ]: 2512 : for (char **keyword = p->soft_keywords; *keyword != NULL; keyword++) {
544 [ + + ]: 1902 : if (strncmp(*keyword, the_token, size) == 0) {
545 : 31 : return _PyPegen_name_from_token(p, t);
546 : : }
547 : : }
548 : 610 : return NULL;
549 : : }
550 : :
551 : : static PyObject *
552 : 5873696 : parsenumber_raw(const char *s)
553 : : {
554 : : const char *end;
555 : : long x;
556 : : double dx;
557 : : Py_complex compl;
558 : : int imflag;
559 : :
560 : : assert(s != NULL);
561 : 5873696 : errno = 0;
562 : 5873696 : end = s + strlen(s) - 1;
563 [ + + - + ]: 5873696 : imflag = *end == 'j' || *end == 'J';
564 [ + + ]: 5873696 : if (s[0] == '0') {
565 : 1813334 : x = (long)PyOS_strtoul(s, (char **)&end, 0);
566 [ + + + + ]: 1813334 : if (x < 0 && errno == 0) {
567 : 279 : return PyLong_FromString(s, (char **)0, 0);
568 : : }
569 : : }
570 : : else {
571 : 4060362 : x = PyOS_strtol(s, (char **)&end, 0);
572 : : }
573 [ + + ]: 5873417 : if (*end == '\0') {
574 [ + + ]: 5811636 : if (errno != 0) {
575 : 892 : return PyLong_FromString(s, (char **)0, 0);
576 : : }
577 : 5810744 : return PyLong_FromLong(x);
578 : : }
579 : : /* XXX Huge floats may silently fail */
580 [ + + ]: 61781 : if (imflag) {
581 : 4264 : compl.real = 0.;
582 : 4264 : compl.imag = PyOS_string_to_double(s, (char **)&end, NULL);
583 [ - + - - ]: 4264 : if (compl.imag == -1.0 && PyErr_Occurred()) {
584 : 0 : return NULL;
585 : : }
586 : 4264 : return PyComplex_FromCComplex(compl);
587 : : }
588 : 57517 : dx = PyOS_string_to_double(s, NULL, NULL);
589 [ - + - - ]: 57517 : if (dx == -1.0 && PyErr_Occurred()) {
590 : 0 : return NULL;
591 : : }
592 : 57517 : return PyFloat_FromDouble(dx);
593 : : }
594 : :
595 : : static PyObject *
596 : 5873696 : parsenumber(const char *s)
597 : : {
598 : : char *dup;
599 : : char *end;
600 : 5873696 : PyObject *res = NULL;
601 : :
602 : : assert(s != NULL);
603 : :
604 [ + + ]: 5873696 : if (strchr(s, '_') == NULL) {
605 : 5871879 : return parsenumber_raw(s);
606 : : }
607 : : /* Create a duplicate without underscores. */
608 : 1817 : dup = PyMem_Malloc(strlen(s) + 1);
609 [ - + ]: 1817 : if (dup == NULL) {
610 : : return PyErr_NoMemory();
611 : : }
612 : 1817 : end = dup;
613 [ + + ]: 39769 : for (; *s; s++) {
614 [ + + ]: 37952 : if (*s != '_') {
615 : 33546 : *end++ = *s;
616 : : }
617 : : }
618 : 1817 : *end = '\0';
619 : 1817 : res = parsenumber_raw(dup);
620 : 1817 : PyMem_Free(dup);
621 : 1817 : return res;
622 : : }
623 : :
624 : : expr_ty
625 : 10965494 : _PyPegen_number_token(Parser *p)
626 : : {
627 : 10965494 : Token *t = _PyPegen_expect_token(p, NUMBER);
628 [ + + ]: 10965494 : if (t == NULL) {
629 : 5091796 : return NULL;
630 : : }
631 : :
632 : 5873698 : const char *num_raw = PyBytes_AsString(t->bytes);
633 [ - + ]: 5873698 : if (num_raw == NULL) {
634 : 0 : p->error_indicator = 1;
635 : 0 : return NULL;
636 : : }
637 : :
638 [ + + + + ]: 5873698 : if (p->feature_version < 6 && strchr(num_raw, '_') != NULL) {
639 : 2 : p->error_indicator = 1;
640 : 2 : return RAISE_SYNTAX_ERROR("Underscores in numeric literals are only supported "
641 : : "in Python 3.6 and greater");
642 : : }
643 : :
644 : 5873696 : PyObject *c = parsenumber(num_raw);
645 : :
646 [ - + ]: 5873696 : if (c == NULL) {
647 : 0 : p->error_indicator = 1;
648 : 0 : return NULL;
649 : : }
650 : :
651 [ - + ]: 5873696 : if (_PyArena_AddPyObject(p->arena, c) < 0) {
652 : 0 : Py_DECREF(c);
653 : 0 : p->error_indicator = 1;
654 : 0 : return NULL;
655 : : }
656 : :
657 : 5873696 : return _PyAST_Constant(c, NULL, t->lineno, t->col_offset, t->end_lineno,
658 : : t->end_col_offset, p->arena);
659 : : }
660 : :
661 : : /* Check that the source for a single input statement really is a single
662 : : statement by looking at what is left in the buffer after parsing.
663 : : Trailing whitespace and comments are OK. */
664 : : static int // bool
665 : 4160 : bad_single_statement(Parser *p)
666 : : {
667 : 4160 : char *cur = p->tok->cur;
668 : 4160 : char c = *cur;
669 : :
670 : : for (;;) {
671 [ + + - + : 4346 : while (c == ' ' || c == '\t' || c == '\n' || c == '\014') {
+ + - + ]
672 : 119 : c = *++cur;
673 : : }
674 : :
675 [ + + ]: 4227 : if (!c) {
676 : 4152 : return 0;
677 : : }
678 : :
679 [ + + ]: 75 : if (c != '#') {
680 : 8 : return 1;
681 : : }
682 : :
683 : : /* Suck up comment. */
684 [ + - + + ]: 1551 : while (c && c != '\n') {
685 : 1484 : c = *++cur;
686 : : }
687 : : }
688 : : }
689 : :
690 : : static int
691 : 126156 : compute_parser_flags(PyCompilerFlags *flags)
692 : : {
693 : 126156 : int parser_flags = 0;
694 [ + + ]: 126156 : if (!flags) {
695 : 181 : return 0;
696 : : }
697 [ + + ]: 125975 : if (flags->cf_flags & PyCF_DONT_IMPLY_DEDENT) {
698 : 359 : parser_flags |= PyPARSE_DONT_IMPLY_DEDENT;
699 : : }
700 [ + + ]: 125975 : if (flags->cf_flags & PyCF_IGNORE_COOKIE) {
701 : 113448 : parser_flags |= PyPARSE_IGNORE_COOKIE;
702 : : }
703 [ + + ]: 125975 : if (flags->cf_flags & CO_FUTURE_BARRY_AS_BDFL) {
704 : 3 : parser_flags |= PyPARSE_BARRY_AS_BDFL;
705 : : }
706 [ + + ]: 125975 : if (flags->cf_flags & PyCF_TYPE_COMMENTS) {
707 : 250 : parser_flags |= PyPARSE_TYPE_COMMENTS;
708 : : }
709 [ + + + + ]: 125975 : if ((flags->cf_flags & PyCF_ONLY_AST) && flags->cf_feature_version < 7) {
710 : 69 : parser_flags |= PyPARSE_ASYNC_HACKS;
711 : : }
712 [ + + ]: 125975 : if (flags->cf_flags & PyCF_ALLOW_INCOMPLETE_INPUT) {
713 : 320 : parser_flags |= PyPARSE_ALLOW_INCOMPLETE_INPUT;
714 : : }
715 : 125975 : return parser_flags;
716 : : }
717 : :
718 : : // Parser API
719 : :
720 : : Parser *
721 : 222224 : _PyPegen_Parser_New(struct tok_state *tok, int start_rule, int flags,
722 : : int feature_version, int *errcode, PyArena *arena)
723 : : {
724 : 222224 : Parser *p = PyMem_Malloc(sizeof(Parser));
725 [ - + ]: 222224 : if (p == NULL) {
726 : : return (Parser *) PyErr_NoMemory();
727 : : }
728 : : assert(tok != NULL);
729 : 222224 : tok->type_comments = (flags & PyPARSE_TYPE_COMMENTS) > 0;
730 : 222224 : tok->async_hacks = (flags & PyPARSE_ASYNC_HACKS) > 0;
731 : 222224 : p->tok = tok;
732 : 222224 : p->keywords = NULL;
733 : 222224 : p->n_keyword_lists = -1;
734 : 222224 : p->soft_keywords = NULL;
735 : 222224 : p->tokens = PyMem_Malloc(sizeof(Token *));
736 [ - + ]: 222224 : if (!p->tokens) {
737 : 0 : PyMem_Free(p);
738 : : return (Parser *) PyErr_NoMemory();
739 : : }
740 : 222224 : p->tokens[0] = PyMem_Calloc(1, sizeof(Token));
741 [ - + ]: 222224 : if (!p->tokens) {
742 : 0 : PyMem_Free(p->tokens);
743 : 0 : PyMem_Free(p);
744 : : return (Parser *) PyErr_NoMemory();
745 : : }
746 [ - + ]: 222224 : if (!growable_comment_array_init(&p->type_ignore_comments, 10)) {
747 : 0 : PyMem_Free(p->tokens[0]);
748 : 0 : PyMem_Free(p->tokens);
749 : 0 : PyMem_Free(p);
750 : : return (Parser *) PyErr_NoMemory();
751 : : }
752 : :
753 : 222224 : p->mark = 0;
754 : 222224 : p->fill = 0;
755 : 222224 : p->size = 1;
756 : :
757 : 222224 : p->errcode = errcode;
758 : 222224 : p->arena = arena;
759 : 222224 : p->start_rule = start_rule;
760 : 222224 : p->parsing_started = 0;
761 : 222224 : p->normalize = NULL;
762 : 222224 : p->error_indicator = 0;
763 : :
764 : 222224 : p->starting_lineno = 0;
765 : 222224 : p->starting_col_offset = 0;
766 : 222224 : p->flags = flags;
767 : 222224 : p->feature_version = feature_version;
768 : 222224 : p->known_err_token = NULL;
769 : 222224 : p->level = 0;
770 : 222224 : p->call_invalid_rules = 0;
771 : : #ifdef Py_DEBUG
772 : : p->debug = _Py_GetConfig()->parser_debug;
773 : : #endif
774 : 222224 : return p;
775 : : }
776 : :
777 : : void
778 : 222224 : _PyPegen_Parser_Free(Parser *p)
779 : : {
780 : 222224 : Py_XDECREF(p->normalize);
781 [ + + ]: 56952602 : for (int i = 0; i < p->size; i++) {
782 : 56730378 : PyMem_Free(p->tokens[i]);
783 : : }
784 : 222224 : PyMem_Free(p->tokens);
785 : 222224 : growable_comment_array_deallocate(&p->type_ignore_comments);
786 : 222224 : PyMem_Free(p);
787 : 222224 : }
788 : :
789 : : static void
790 : 2002 : reset_parser_state_for_error_pass(Parser *p)
791 : : {
792 [ + + ]: 10547 : for (int i = 0; i < p->fill; i++) {
793 : 8545 : p->tokens[i]->memo = NULL;
794 : : }
795 : 2002 : p->mark = 0;
796 : 2002 : p->call_invalid_rules = 1;
797 : : // Don't try to get extra tokens in interactive mode when trying to
798 : : // raise specialized errors in the second pass.
799 : 2002 : p->tok->interactive_underflow = IUNDERFLOW_STOP;
800 : 2002 : }
801 : :
802 : : static inline int
803 : 262 : _is_end_of_source(Parser *p) {
804 : 262 : int err = p->tok->done;
805 [ + + + + : 262 : return err == E_EOF || err == E_EOFS || err == E_EOLS;
+ + ]
806 : : }
807 : :
808 : : void *
809 : 222224 : _PyPegen_run_parser(Parser *p)
810 : : {
811 : 222224 : void *res = _PyPegen_parse(p);
812 : : assert(p->level == 0);
813 [ + + ]: 222224 : if (res == NULL) {
814 [ + + + + ]: 2219 : if ((p->flags & PyPARSE_ALLOW_INCOMPLETE_INPUT) && _is_end_of_source(p)) {
815 : 213 : PyErr_Clear();
816 : 213 : return RAISE_SYNTAX_ERROR("incomplete input");
817 : : }
818 [ + + + + ]: 2006 : if (PyErr_Occurred() && !PyErr_ExceptionMatches(PyExc_SyntaxError)) {
819 : 4 : return NULL;
820 : : }
821 : : // Make a second parser pass. In this pass we activate heavier and slower checks
822 : : // to produce better error messages and more complete diagnostics. Extra "invalid_*"
823 : : // rules will be active during parsing.
824 : 2002 : Token *last_token = p->tokens[p->fill - 1];
825 : 2002 : reset_parser_state_for_error_pass(p);
826 : 2002 : _PyPegen_parse(p);
827 : :
828 : : // Set SyntaxErrors accordingly depending on the parser/tokenizer status at the failure
829 : : // point.
830 : 2002 : _Pypegen_set_syntax_error(p, last_token);
831 : 2002 : return NULL;
832 : : }
833 : :
834 [ + + + + ]: 220005 : if (p->start_rule == Py_single_input && bad_single_statement(p)) {
835 : 8 : p->tok->done = E_BADSINGLE; // This is not necessary for now, but might be in the future
836 : 8 : return RAISE_SYNTAX_ERROR("multiple statements found while compiling a single statement");
837 : : }
838 : :
839 : : // test_peg_generator defines _Py_TEST_PEGEN to not call PyAST_Validate()
840 : : #if defined(Py_DEBUG) && !defined(_Py_TEST_PEGEN)
841 : : if (p->start_rule == Py_single_input ||
842 : : p->start_rule == Py_file_input ||
843 : : p->start_rule == Py_eval_input)
844 : : {
845 : : if (!_PyAST_Validate(res)) {
846 : : return NULL;
847 : : }
848 : : }
849 : : #endif
850 : 219997 : return res;
851 : : }
852 : :
853 : : mod_ty
854 : 358 : _PyPegen_run_parser_from_file_pointer(FILE *fp, int start_rule, PyObject *filename_ob,
855 : : const char *enc, const char *ps1, const char *ps2,
856 : : PyCompilerFlags *flags, int *errcode, PyArena *arena)
857 : : {
858 : 358 : struct tok_state *tok = _PyTokenizer_FromFile(fp, enc, ps1, ps2);
859 [ - + ]: 358 : if (tok == NULL) {
860 [ # # ]: 0 : if (PyErr_Occurred()) {
861 : 0 : _PyPegen_raise_tokenizer_init_error(filename_ob);
862 : 0 : return NULL;
863 : : }
864 : 0 : return NULL;
865 : : }
866 [ + - + + : 686 : if (!tok->fp || ps1 != NULL || ps2 != NULL ||
+ - + + ]
867 : 328 : PyUnicode_CompareWithASCIIString(filename_ob, "<stdin>") == 0) {
868 : 43 : tok->fp_interactive = 1;
869 : : }
870 : : // This transfers the ownership to the tokenizer
871 : 358 : tok->filename = filename_ob;
872 : 358 : Py_INCREF(filename_ob);
873 : :
874 : : // From here on we need to clean up even if there's an error
875 : 358 : mod_ty result = NULL;
876 : :
877 : 358 : int parser_flags = compute_parser_flags(flags);
878 : 358 : Parser *p = _PyPegen_Parser_New(tok, start_rule, parser_flags, PY_MINOR_VERSION,
879 : : errcode, arena);
880 [ - + ]: 358 : if (p == NULL) {
881 : 0 : goto error;
882 : : }
883 : :
884 : 358 : result = _PyPegen_run_parser(p);
885 : 358 : _PyPegen_Parser_Free(p);
886 : :
887 : 358 : error:
888 : 358 : _PyTokenizer_Free(tok);
889 : 358 : return result;
890 : : }
891 : :
892 : : mod_ty
893 : 125824 : _PyPegen_run_parser_from_string(const char *str, int start_rule, PyObject *filename_ob,
894 : : PyCompilerFlags *flags, PyArena *arena)
895 : : {
896 : 125824 : int exec_input = start_rule == Py_file_input;
897 : :
898 : : struct tok_state *tok;
899 [ + + + + ]: 125824 : if (flags != NULL && flags->cf_flags & PyCF_IGNORE_COOKIE) {
900 : 113448 : tok = _PyTokenizer_FromUTF8(str, exec_input);
901 : : } else {
902 : 12376 : tok = _PyTokenizer_FromString(str, exec_input);
903 : : }
904 [ + + ]: 125824 : if (tok == NULL) {
905 [ + - ]: 26 : if (PyErr_Occurred()) {
906 : 26 : _PyPegen_raise_tokenizer_init_error(filename_ob);
907 : : }
908 : 26 : return NULL;
909 : : }
910 : : // This transfers the ownership to the tokenizer
911 : 125798 : tok->filename = filename_ob;
912 : 125798 : Py_INCREF(filename_ob);
913 : :
914 : : // We need to clear up from here on
915 : 125798 : mod_ty result = NULL;
916 : :
917 : 125798 : int parser_flags = compute_parser_flags(flags);
918 [ + + ]: 125617 : int feature_version = flags && (flags->cf_flags & PyCF_ONLY_AST) ?
919 [ + + ]: 251415 : flags->cf_feature_version : PY_MINOR_VERSION;
920 : 125798 : Parser *p = _PyPegen_Parser_New(tok, start_rule, parser_flags, feature_version,
921 : : NULL, arena);
922 [ - + ]: 125798 : if (p == NULL) {
923 : 0 : goto error;
924 : : }
925 : :
926 : 125798 : result = _PyPegen_run_parser(p);
927 : 125798 : _PyPegen_Parser_Free(p);
928 : :
929 : 125798 : error:
930 : 125798 : _PyTokenizer_Free(tok);
931 : 125798 : return result;
932 : : }
|