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 3963 : _PyPegen_byte_offset_to_character_offset(PyObject *line, Py_ssize_t col_offset)
21 : {
22 3963 : const char *str = PyUnicode_AsUTF8(line);
23 3963 : if (!str) {
24 0 : return -1;
25 : }
26 3963 : Py_ssize_t len = strlen(str);
27 3963 : if (col_offset > len + 1) {
28 10 : col_offset = len + 1;
29 : }
30 3963 : assert(col_offset >= 0);
31 3963 : PyObject *text = PyUnicode_DecodeUTF8(str, col_offset, "replace");
32 3963 : if (!text) {
33 0 : return -1;
34 : }
35 3963 : Py_ssize_t size = PyUnicode_GET_LENGTH(text);
36 3963 : Py_DECREF(text);
37 3963 : 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 195276000 : _PyPegen_insert_memo(Parser *p, int mark, int type, void *node)
44 : {
45 : // Insert in front
46 195276000 : Memo *m = _PyArena_Malloc(p->arena, sizeof(Memo));
47 195276000 : if (m == NULL) {
48 0 : return -1;
49 : }
50 195276000 : m->type = type;
51 195276000 : m->node = node;
52 195276000 : m->mark = p->mark;
53 195276000 : m->next = p->tokens[mark]->memo;
54 195276000 : p->tokens[mark]->memo = m;
55 195276000 : return 0;
56 : }
57 :
58 : // Like _PyPegen_insert_memo(), but updates an existing node if found.
59 : int
60 171061000 : _PyPegen_update_memo(Parser *p, int mark, int type, void *node)
61 : {
62 856401000 : for (Memo *m = p->tokens[mark]->memo; m != NULL; m = m->next) {
63 764557000 : if (m->type == type) {
64 : // Update existing node.
65 79216800 : m->node = node;
66 79216800 : m->mark = p->mark;
67 79216800 : return 0;
68 : }
69 : }
70 : // Insert new node.
71 91843900 : 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 223947 : growable_comment_array_init(growable_comment_array *arr, size_t initial_size) {
90 223947 : assert(initial_size > 0);
91 223947 : arr->items = PyMem_Malloc(initial_size * sizeof(*arr->items));
92 223947 : arr->size = initial_size;
93 223947 : arr->num_items = 0;
94 :
95 223947 : 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 223947 : growable_comment_array_deallocate(growable_comment_array *arr) {
118 224021 : for (unsigned i = 0; i < arr->num_items; i++) {
119 74 : PyMem_Free(arr->items[i].comment);
120 : }
121 223947 : PyMem_Free(arr->items);
122 223947 : }
123 :
124 : static int
125 12437000 : _get_keyword_or_name_type(Parser *p, const char *name, int name_len)
126 : {
127 12437000 : assert(name_len > 0);
128 12437000 : if (name_len >= p->n_keyword_lists ||
129 10186300 : p->keywords[name_len] == NULL ||
130 10186300 : p->keywords[name_len]->type == -1) {
131 3946410 : return NAME;
132 : }
133 45341500 : for (KeywordToken *k = p->keywords[name_len]; k != NULL && k->type != -1; k++) {
134 39354900 : if (strncmp(k->str, name, name_len) == 0) {
135 2504030 : return k->type;
136 : }
137 : }
138 5986600 : return NAME;
139 : }
140 :
141 : static int
142 39577500 : initialize_token(Parser *p, Token *token, const char *start, const char *end, int token_type) {
143 39577500 : assert(token != NULL);
144 :
145 39577500 : token->type = (token_type == NAME) ? _get_keyword_or_name_type(p, start, (int)(end - start)) : token_type;
146 39577500 : token->bytes = PyBytes_FromStringAndSize(start, end - start);
147 39577500 : if (token->bytes == NULL) {
148 0 : return -1;
149 : }
150 :
151 39577500 : if (_PyArena_AddPyObject(p->arena, token->bytes) < 0) {
152 0 : Py_DECREF(token->bytes);
153 0 : return -1;
154 : }
155 :
156 39577500 : token->level = p->tok->level;
157 :
158 39577500 : const char *line_start = token_type == STRING ? p->tok->multi_line_start : p->tok->line_start;
159 39577500 : int lineno = token_type == STRING ? p->tok->first_lineno : p->tok->lineno;
160 39577500 : int end_lineno = p->tok->lineno;
161 :
162 39577500 : int col_offset = (start != NULL && start >= line_start) ? (int)(start - line_start) : -1;
163 39577500 : int end_col_offset = (end != NULL && end >= p->tok->line_start) ? (int)(end - p->tok->line_start) : -1;
164 :
165 39577500 : token->lineno = lineno;
166 39577500 : token->col_offset = p->tok->lineno == p->starting_lineno ? p->starting_col_offset + col_offset : col_offset;
167 39577500 : token->end_lineno = end_lineno;
168 39577500 : token->end_col_offset = p->tok->lineno == p->starting_lineno ? p->starting_col_offset + end_col_offset : end_col_offset;
169 :
170 39577500 : p->fill += 1;
171 :
172 39577500 : if (token_type == ERRORTOKEN && p->tok->done == E_DECODE) {
173 7 : return _Pypegen_raise_decode_error(p);
174 : }
175 :
176 39577500 : return (token_type == ERRORTOKEN ? _Pypegen_tokenizer_error(p) : 0);
177 : }
178 :
179 : static int
180 763916 : _resize_tokens_array(Parser *p) {
181 763916 : int newsize = p->size * 2;
182 763916 : Token **new_tokens = PyMem_Realloc(p->tokens, newsize * sizeof(Token *));
183 763916 : if (new_tokens == NULL) {
184 0 : PyErr_NoMemory();
185 0 : return -1;
186 : }
187 763916 : p->tokens = new_tokens;
188 :
189 57520500 : for (int i = p->size; i < newsize; i++) {
190 56756600 : p->tokens[i] = PyMem_Calloc(1, sizeof(Token));
191 56756600 : if (p->tokens[i] == NULL) {
192 0 : p->size = i; // Needed, in order to cleanup correctly after parser fails
193 0 : PyErr_NoMemory();
194 0 : return -1;
195 : }
196 : }
197 763916 : p->size = newsize;
198 763916 : return 0;
199 : }
200 :
201 : int
202 39577500 : _PyPegen_fill_token(Parser *p)
203 : {
204 : const char *start;
205 : const char *end;
206 39577500 : int type = _PyTokenizer_Get(p->tok, &start, &end);
207 :
208 : // Record and skip '# type: ignore' comments
209 39577600 : 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 0 : 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 0 : 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 39577500 : if (p->start_rule == Py_single_input && type == ENDMARKER && p->parsing_started) {
228 812 : type = NEWLINE; /* Add an extra newline */
229 812 : p->parsing_started = 0;
230 :
231 812 : 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 39576700 : p->parsing_started = 1;
238 : }
239 :
240 : // Check if we are at the limit of the token array capacity and resize if needed
241 39577500 : if ((p->fill == p->size) && (_resize_tokens_array(p) != 0)) {
242 0 : return -1;
243 : }
244 :
245 39577500 : Token *t = p->tokens[p->fill];
246 39577500 : 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 0 : _PyPegen_clear_memo_statistics()
259 : {
260 0 : for (int i = 0; i < NSTATISTICS; i++) {
261 0 : memo_statistics[i] = 0;
262 : }
263 0 : }
264 :
265 : PyObject *
266 0 : _PyPegen_get_memo_statistics()
267 : {
268 0 : PyObject *ret = PyList_New(NSTATISTICS);
269 0 : if (ret == NULL) {
270 0 : return NULL;
271 : }
272 0 : for (int i = 0; i < NSTATISTICS; i++) {
273 0 : PyObject *value = PyLong_FromLong(memo_statistics[i]);
274 0 : if (value == NULL) {
275 0 : Py_DECREF(ret);
276 0 : return NULL;
277 : }
278 : // PyList_SetItem borrows a reference to value.
279 0 : if (PyList_SetItem(ret, i, value) < 0) {
280 0 : Py_DECREF(ret);
281 0 : return NULL;
282 : }
283 : }
284 0 : return ret;
285 : }
286 : #endif
287 :
288 : int // bool
289 749151000 : _PyPegen_is_memoized(Parser *p, int type, void *pres)
290 : {
291 749151000 : if (p->mark == p->fill) {
292 3642320 : if (_PyPegen_fill_token(p) < 0) {
293 40 : p->error_indicator = 1;
294 40 : return -1;
295 : }
296 : }
297 :
298 749151000 : Token *t = p->tokens[p->mark];
299 :
300 2316980000 : for (Memo *m = t->memo; m != NULL; m = m->next) {
301 2130550000 : 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 562715000 : p->mark = m->mark;
313 562715000 : *(void **)(pres) = m->node;
314 562715000 : return 1;
315 : }
316 : }
317 186436000 : 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 3682 : _PyPegen_lookahead_with_string(int positive, expr_ty (func)(Parser *, const char*), Parser *p, const char* arg)
331 : {
332 3682 : int mark = p->mark;
333 3682 : void *res = func(p, arg);
334 3682 : p->mark = mark;
335 3682 : return (res != NULL) == positive;
336 : }
337 :
338 : int
339 53979700 : _PyPegen_lookahead_with_int(int positive, Token *(func)(Parser *, int), Parser *p, int arg)
340 : {
341 53979700 : int mark = p->mark;
342 53979700 : void *res = func(p, arg);
343 53979700 : p->mark = mark;
344 53979700 : return (res != NULL) == positive;
345 : }
346 :
347 : int
348 36644100 : _PyPegen_lookahead(int positive, void *(func)(Parser *), Parser *p)
349 : {
350 36644100 : int mark = p->mark;
351 36644100 : void *res = (void*)func(p);
352 36644100 : p->mark = mark;
353 36644100 : return (res != NULL) == positive;
354 : }
355 :
356 : Token *
357 759672000 : _PyPegen_expect_token(Parser *p, int type)
358 : {
359 759672000 : if (p->mark == p->fill) {
360 26819300 : if (_PyPegen_fill_token(p) < 0) {
361 166 : p->error_indicator = 1;
362 166 : return NULL;
363 : }
364 : }
365 759672000 : Token *t = p->tokens[p->mark];
366 759672000 : if (t->type != type) {
367 662567000 : return NULL;
368 : }
369 97105000 : p->mark += 1;
370 97105000 : 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 853883 : _PyPegen_expect_forced_token(Parser *p, int type, const char* expected) {
388 :
389 853883 : if (p->error_indicator == 1) {
390 0 : return NULL;
391 : }
392 :
393 853883 : if (p->mark == p->fill) {
394 468732 : if (_PyPegen_fill_token(p) < 0) {
395 0 : p->error_indicator = 1;
396 0 : return NULL;
397 : }
398 : }
399 853883 : Token *t = p->tokens[p->mark];
400 853883 : if (t->type != type) {
401 11 : RAISE_SYNTAX_ERROR_KNOWN_LOCATION(t, "expected '%s'", expected);
402 11 : return NULL;
403 : }
404 853872 : p->mark += 1;
405 853872 : return t;
406 : }
407 :
408 : expr_ty
409 3022660 : _PyPegen_expect_soft_keyword(Parser *p, const char *keyword)
410 : {
411 3022660 : if (p->mark == p->fill) {
412 3416 : if (_PyPegen_fill_token(p) < 0) {
413 0 : p->error_indicator = 1;
414 0 : return NULL;
415 : }
416 : }
417 3022660 : Token *t = p->tokens[p->mark];
418 3022660 : if (t->type != NAME) {
419 1645110 : return NULL;
420 : }
421 1377550 : const char *s = PyBytes_AsString(t->bytes);
422 1377550 : if (!s) {
423 0 : p->error_indicator = 1;
424 0 : return NULL;
425 : }
426 1377550 : if (strcmp(s, keyword) != 0) {
427 1372710 : return NULL;
428 : }
429 4842 : return _PyPegen_name_token(p);
430 : }
431 :
432 : Token *
433 20074800 : _PyPegen_get_last_nonnwhitespace_token(Parser *p)
434 : {
435 20074800 : assert(p->mark >= 0);
436 20074800 : Token *token = NULL;
437 22365500 : for (int m = p->mark - 1; m >= 0; m--) {
438 22365500 : token = p->tokens[m];
439 22365500 : if (token->type != ENDMARKER && (token->type < NEWLINE || token->type > DEDENT)) {
440 : break;
441 : }
442 : }
443 20074800 : return token;
444 : }
445 :
446 : PyObject *
447 34074200 : _PyPegen_new_identifier(Parser *p, const char *n)
448 : {
449 34074200 : PyObject *id = PyUnicode_DecodeUTF8(n, strlen(n), NULL);
450 34074200 : if (!id) {
451 0 : goto error;
452 : }
453 : /* PyUnicode_DecodeUTF8 should always return a ready string. */
454 34074200 : assert(PyUnicode_IS_READY(id));
455 : /* Check whether there are non-ASCII characters in the
456 : identifier; if so, normalize to NFKC. */
457 34074200 : 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 34074200 : PyUnicode_InternInPlace(&id);
490 34074200 : if (_PyArena_AddPyObject(p->arena, id) < 0)
491 : {
492 0 : Py_DECREF(id);
493 0 : goto error;
494 : }
495 34074200 : return id;
496 :
497 1 : error:
498 1 : p->error_indicator = 1;
499 1 : return NULL;
500 : }
501 :
502 : static expr_ty
503 69126700 : _PyPegen_name_from_token(Parser *p, Token* t)
504 : {
505 69126700 : if (t == NULL) {
506 35056200 : return NULL;
507 : }
508 34070500 : const char *s = PyBytes_AsString(t->bytes);
509 34070500 : if (!s) {
510 0 : p->error_indicator = 1;
511 0 : return NULL;
512 : }
513 34070500 : PyObject *id = _PyPegen_new_identifier(p, s);
514 34070500 : if (id == NULL) {
515 1 : p->error_indicator = 1;
516 1 : return NULL;
517 : }
518 34070500 : 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 69126700 : _PyPegen_name_token(Parser *p)
524 : {
525 69126700 : Token *t = _PyPegen_expect_token(p, NAME);
526 69126700 : return _PyPegen_name_from_token(p, t);
527 : }
528 :
529 : void *
530 17709100 : _PyPegen_string_token(Parser *p)
531 : {
532 17709100 : 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 5874740 : 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 5874740 : assert(s != NULL);
561 5874740 : errno = 0;
562 5874740 : end = s + strlen(s) - 1;
563 5874740 : imflag = *end == 'j' || *end == 'J';
564 5874740 : if (s[0] == '0') {
565 1814730 : x = (long)PyOS_strtoul(s, (char **)&end, 0);
566 1814730 : if (x < 0 && errno == 0) {
567 277 : return PyLong_FromString(s, (char **)0, 0);
568 : }
569 : }
570 : else {
571 4060010 : x = PyOS_strtol(s, (char **)&end, 0);
572 : }
573 5874470 : if (*end == '\0') {
574 5813940 : if (errno != 0) {
575 892 : return PyLong_FromString(s, (char **)0, 0);
576 : }
577 5813050 : return PyLong_FromLong(x);
578 : }
579 : /* XXX Huge floats may silently fail */
580 60523 : if (imflag) {
581 4262 : compl.real = 0.;
582 4262 : compl.imag = PyOS_string_to_double(s, (char **)&end, NULL);
583 4262 : if (compl.imag == -1.0 && PyErr_Occurred()) {
584 0 : return NULL;
585 : }
586 4262 : return PyComplex_FromCComplex(compl);
587 : }
588 56261 : dx = PyOS_string_to_double(s, NULL, NULL);
589 56261 : if (dx == -1.0 && PyErr_Occurred()) {
590 0 : return NULL;
591 : }
592 56261 : return PyFloat_FromDouble(dx);
593 : }
594 :
595 : static PyObject *
596 5874740 : parsenumber(const char *s)
597 : {
598 : char *dup;
599 : char *end;
600 5874740 : PyObject *res = NULL;
601 :
602 5874740 : assert(s != NULL);
603 :
604 5874740 : if (strchr(s, '_') == NULL) {
605 5873040 : return parsenumber_raw(s);
606 : }
607 : /* Create a duplicate without underscores. */
608 1703 : dup = PyMem_Malloc(strlen(s) + 1);
609 1703 : if (dup == NULL) {
610 0 : return PyErr_NoMemory();
611 : }
612 1703 : end = dup;
613 38803 : for (; *s; s++) {
614 37100 : if (*s != '_') {
615 32836 : *end++ = *s;
616 : }
617 : }
618 1703 : *end = '\0';
619 1703 : res = parsenumber_raw(dup);
620 1703 : PyMem_Free(dup);
621 1703 : return res;
622 : }
623 :
624 : expr_ty
625 10995100 : _PyPegen_number_token(Parser *p)
626 : {
627 10995100 : Token *t = _PyPegen_expect_token(p, NUMBER);
628 10995100 : if (t == NULL) {
629 5120390 : return NULL;
630 : }
631 :
632 5874740 : const char *num_raw = PyBytes_AsString(t->bytes);
633 5874740 : if (num_raw == NULL) {
634 0 : p->error_indicator = 1;
635 0 : return NULL;
636 : }
637 :
638 5874740 : 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 5874740 : PyObject *c = parsenumber(num_raw);
645 :
646 5874740 : if (c == NULL) {
647 0 : p->error_indicator = 1;
648 0 : return NULL;
649 : }
650 :
651 5874740 : 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 5874740 : 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 4163 : bad_single_statement(Parser *p)
666 : {
667 4163 : char *cur = p->tok->cur;
668 4163 : char c = *cur;
669 :
670 : for (;;) {
671 4349 : while (c == ' ' || c == '\t' || c == '\n' || c == '\014') {
672 119 : c = *++cur;
673 : }
674 :
675 4230 : if (!c) {
676 4155 : 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 127837 : compute_parser_flags(PyCompilerFlags *flags)
692 : {
693 127837 : int parser_flags = 0;
694 127837 : if (!flags) {
695 181 : return 0;
696 : }
697 127656 : if (flags->cf_flags & PyCF_DONT_IMPLY_DEDENT) {
698 362 : parser_flags |= PyPARSE_DONT_IMPLY_DEDENT;
699 : }
700 127656 : if (flags->cf_flags & PyCF_IGNORE_COOKIE) {
701 115007 : parser_flags |= PyPARSE_IGNORE_COOKIE;
702 : }
703 127656 : if (flags->cf_flags & CO_FUTURE_BARRY_AS_BDFL) {
704 3 : parser_flags |= PyPARSE_BARRY_AS_BDFL;
705 : }
706 127656 : if (flags->cf_flags & PyCF_TYPE_COMMENTS) {
707 250 : parser_flags |= PyPARSE_TYPE_COMMENTS;
708 : }
709 127656 : if ((flags->cf_flags & PyCF_ONLY_AST) && flags->cf_feature_version < 7) {
710 69 : parser_flags |= PyPARSE_ASYNC_HACKS;
711 : }
712 127656 : if (flags->cf_flags & PyCF_ALLOW_INCOMPLETE_INPUT) {
713 323 : parser_flags |= PyPARSE_ALLOW_INCOMPLETE_INPUT;
714 : }
715 127656 : return parser_flags;
716 : }
717 :
718 : // Parser API
719 :
720 : Parser *
721 223947 : _PyPegen_Parser_New(struct tok_state *tok, int start_rule, int flags,
722 : int feature_version, int *errcode, PyArena *arena)
723 : {
724 223947 : Parser *p = PyMem_Malloc(sizeof(Parser));
725 223947 : if (p == NULL) {
726 0 : return (Parser *) PyErr_NoMemory();
727 : }
728 223947 : assert(tok != NULL);
729 223947 : tok->type_comments = (flags & PyPARSE_TYPE_COMMENTS) > 0;
730 223947 : tok->async_hacks = (flags & PyPARSE_ASYNC_HACKS) > 0;
731 223947 : p->tok = tok;
732 223947 : p->keywords = NULL;
733 223947 : p->n_keyword_lists = -1;
734 223947 : p->soft_keywords = NULL;
735 223947 : p->tokens = PyMem_Malloc(sizeof(Token *));
736 223947 : if (!p->tokens) {
737 0 : PyMem_Free(p);
738 0 : return (Parser *) PyErr_NoMemory();
739 : }
740 223947 : p->tokens[0] = PyMem_Calloc(1, sizeof(Token));
741 223947 : if (!p->tokens) {
742 0 : PyMem_Free(p->tokens);
743 0 : PyMem_Free(p);
744 0 : return (Parser *) PyErr_NoMemory();
745 : }
746 223947 : 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 0 : return (Parser *) PyErr_NoMemory();
751 : }
752 :
753 223947 : p->mark = 0;
754 223947 : p->fill = 0;
755 223947 : p->size = 1;
756 :
757 223947 : p->errcode = errcode;
758 223947 : p->arena = arena;
759 223947 : p->start_rule = start_rule;
760 223947 : p->parsing_started = 0;
761 223947 : p->normalize = NULL;
762 223947 : p->error_indicator = 0;
763 :
764 223947 : p->starting_lineno = 0;
765 223947 : p->starting_col_offset = 0;
766 223947 : p->flags = flags;
767 223947 : p->feature_version = feature_version;
768 223947 : p->known_err_token = NULL;
769 223947 : p->level = 0;
770 223947 : p->call_invalid_rules = 0;
771 : #ifdef Py_DEBUG
772 223947 : p->debug = _Py_GetConfig()->parser_debug;
773 : #endif
774 223947 : return p;
775 : }
776 :
777 : void
778 223947 : _PyPegen_Parser_Free(Parser *p)
779 : {
780 223947 : Py_XDECREF(p->normalize);
781 57204500 : for (int i = 0; i < p->size; i++) {
782 56980500 : PyMem_Free(p->tokens[i]);
783 : }
784 223947 : PyMem_Free(p->tokens);
785 223947 : growable_comment_array_deallocate(&p->type_ignore_comments);
786 223947 : PyMem_Free(p);
787 223947 : }
788 :
789 : static void
790 2000 : reset_parser_state_for_error_pass(Parser *p)
791 : {
792 10529 : for (int i = 0; i < p->fill; i++) {
793 8529 : p->tokens[i]->memo = NULL;
794 : }
795 2000 : p->mark = 0;
796 2000 : 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 2000 : p->tok->interactive_underflow = IUNDERFLOW_STOP;
800 2000 : }
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 223947 : _PyPegen_run_parser(Parser *p)
810 : {
811 223947 : void *res = _PyPegen_parse(p);
812 223947 : assert(p->level == 0);
813 223947 : if (res == NULL) {
814 2217 : 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 2004 : 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 2000 : Token *last_token = p->tokens[p->fill - 1];
825 2000 : reset_parser_state_for_error_pass(p);
826 2000 : _PyPegen_parse(p);
827 :
828 : // Set SyntaxErrors accordingly depending on the parser/tokenizer status at the failure
829 : // point.
830 2000 : _Pypegen_set_syntax_error(p, last_token);
831 2000 : return NULL;
832 : }
833 :
834 221730 : 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 221722 : if (p->start_rule == Py_single_input ||
842 217567 : p->start_rule == Py_file_input ||
843 169363 : p->start_rule == Py_eval_input)
844 : {
845 125616 : if (!_PyAST_Validate(res)) {
846 8 : return NULL;
847 : }
848 : }
849 : #endif
850 221714 : return res;
851 : }
852 :
853 : mod_ty
854 354 : _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 354 : struct tok_state *tok = _PyTokenizer_FromFile(fp, enc, ps1, ps2);
859 354 : 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 678 : if (!tok->fp || ps1 != NULL || ps2 != NULL ||
867 324 : PyUnicode_CompareWithASCIIString(filename_ob, "<stdin>") == 0) {
868 43 : tok->fp_interactive = 1;
869 : }
870 : // This transfers the ownership to the tokenizer
871 354 : tok->filename = filename_ob;
872 354 : Py_INCREF(filename_ob);
873 :
874 : // From here on we need to clean up even if there's an error
875 354 : mod_ty result = NULL;
876 :
877 354 : int parser_flags = compute_parser_flags(flags);
878 354 : Parser *p = _PyPegen_Parser_New(tok, start_rule, parser_flags, PY_MINOR_VERSION,
879 : errcode, arena);
880 354 : if (p == NULL) {
881 0 : goto error;
882 : }
883 :
884 354 : result = _PyPegen_run_parser(p);
885 354 : _PyPegen_Parser_Free(p);
886 :
887 354 : error:
888 354 : _PyTokenizer_Free(tok);
889 354 : return result;
890 : }
891 :
892 : mod_ty
893 127509 : _PyPegen_run_parser_from_string(const char *str, int start_rule, PyObject *filename_ob,
894 : PyCompilerFlags *flags, PyArena *arena)
895 : {
896 127509 : int exec_input = start_rule == Py_file_input;
897 :
898 : struct tok_state *tok;
899 127509 : if (flags != NULL && flags->cf_flags & PyCF_IGNORE_COOKIE) {
900 115007 : tok = _PyTokenizer_FromUTF8(str, exec_input);
901 : } else {
902 12502 : tok = _PyTokenizer_FromString(str, exec_input);
903 : }
904 127509 : 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 127483 : tok->filename = filename_ob;
912 127483 : Py_INCREF(filename_ob);
913 :
914 : // We need to clear up from here on
915 127483 : mod_ty result = NULL;
916 :
917 127483 : int parser_flags = compute_parser_flags(flags);
918 127302 : int feature_version = flags && (flags->cf_flags & PyCF_ONLY_AST) ?
919 254785 : flags->cf_feature_version : PY_MINOR_VERSION;
920 127483 : Parser *p = _PyPegen_Parser_New(tok, start_rule, parser_flags, feature_version,
921 : NULL, arena);
922 127483 : if (p == NULL) {
923 0 : goto error;
924 : }
925 :
926 127483 : result = _PyPegen_run_parser(p);
927 127483 : _PyPegen_Parser_Free(p);
928 :
929 127483 : error:
930 127483 : _PyTokenizer_Free(tok);
931 127483 : return result;
932 : }
|