LCOV - code coverage report
Current view: | top level - Parser - pegen_errors.c (source / functions) |  |  | Hit | Total | Coverage
Test: | CPython 3.12 LCOV report [commit 5e6661bce9] |  | Lines: | 0 | 244 | 0.0 %
Date: | 2023-03-20 08:15:36 |  | Functions: | 0 | 9 | 0.0 %
|  |  | Branches: | 0 | 150 | 0.0 %

               Branch data     Line data    Source code
           1                 :            : #include <Python.h>
           2                 :            : #include <errcode.h>
           3                 :            :
           4                 :            : #include "tokenizer.h"
           5                 :            : #include "pegen.h"
           6                 :            :
           7                 :            : // TOKENIZER ERRORS
           8                 :            :
           9                 :            : void
          10                 :          0 : _PyPegen_raise_tokenizer_init_error(PyObject *filename)
          11                 :            : {
          12   [ #  #  #  # ]:          0 :     if (!(PyErr_ExceptionMatches(PyExc_LookupError)
          13         [ #  # ]:          0 :           || PyErr_ExceptionMatches(PyExc_SyntaxError)
          14         [ #  # ]:          0 :           || PyErr_ExceptionMatches(PyExc_ValueError)
          15                 :          0 :           || PyErr_ExceptionMatches(PyExc_UnicodeDecodeError))) {
          16                 :          0 :         return;
          17                 :            :     }
          18                 :          0 :     PyObject *errstr = NULL;
          19                 :          0 :     PyObject *tuple = NULL;
          20                 :            :     PyObject *type;
          21                 :            :     PyObject *value;
          22                 :            :     PyObject *tback;
          23                 :          0 :     PyErr_Fetch(&type, &value, &tback);
          24                 :          0 :     errstr = PyObject_Str(value);
          25         [ #  # ]:          0 :     if (!errstr) {
          26                 :          0 :         goto error;
          27                 :            :     }
          28                 :            :
          29                 :          0 :     PyObject *tmp = Py_BuildValue("(OiiO)", filename, 0, -1, Py_None);
          30         [ #  # ]:          0 :     if (!tmp) {
          31                 :          0 :         goto error;
          32                 :            :     }
          33                 :            :
          34                 :          0 :     tuple = PyTuple_Pack(2, errstr, tmp);
          35                 :          0 :     Py_DECREF(tmp);
          36         [ #  # ]:          0 :     if (!value) {
          37                 :          0 :         goto error;
          38                 :            :     }
          39                 :          0 :     PyErr_SetObject(PyExc_SyntaxError, tuple);
          40                 :            :
          41                 :          0 : error:
          42                 :          0 :     Py_XDECREF(type);
          43                 :          0 :     Py_XDECREF(value);
          44                 :          0 :     Py_XDECREF(tback);
          45                 :          0 :     Py_XDECREF(errstr);
          46                 :          0 :     Py_XDECREF(tuple);
          47                 :            : }
          48                 :            :
          49                 :            : static inline void
          50                 :          0 : raise_unclosed_parentheses_error(Parser *p) {
          51                 :          0 :        int error_lineno = p->tok->parenlinenostack[p->tok->level-1];
          52                 :          0 :        int error_col = p->tok->parencolstack[p->tok->level-1];
          53                 :          0 :        RAISE_ERROR_KNOWN_LOCATION(p, PyExc_SyntaxError,
          54                 :            :                                   error_lineno, error_col, error_lineno, -1,
          55                 :            :                                   "'%c' was never closed",
          56                 :          0 :                                   p->tok->parenstack[p->tok->level-1]);
          57                 :          0 : }
          58                 :            :
          59                 :            : int
          60                 :          0 : _Pypegen_tokenizer_error(Parser *p)
          61                 :            : {
          62         [ #  # ]:          0 :     if (PyErr_Occurred()) {
          63                 :          0 :         return -1;
          64                 :            :     }
          65                 :            :
          66                 :          0 :     const char *msg = NULL;
          67                 :          0 :     PyObject* errtype = PyExc_SyntaxError;
          68                 :          0 :     Py_ssize_t col_offset = -1;
          69   [ #  #  #  #  :          0 :     switch (p->tok->done) {
                 #  #  #  #
                          # ]
          70                 :          0 :         case E_TOKEN:
          71                 :          0 :             msg = "invalid token";
          72                 :          0 :             break;
          73                 :          0 :         case E_EOF:
          74         [ #  # ]:          0 :             if (p->tok->level) {
          75                 :          0 :                 raise_unclosed_parentheses_error(p);
          76                 :            :             } else {
          77                 :          0 :                 RAISE_SYNTAX_ERROR("unexpected EOF while parsing");
          78                 :            :             }
          79                 :          0 :             return -1;
          80                 :          0 :         case E_DEDENT:
          81                 :          0 :             RAISE_INDENTATION_ERROR("unindent does not match any outer indentation level");
          82                 :          0 :             return -1;
          83                 :          0 :         case E_INTR:
          84         [ #  # ]:          0 :             if (!PyErr_Occurred()) {
          85                 :          0 :                 PyErr_SetNone(PyExc_KeyboardInterrupt);
          86                 :            :             }
          87                 :          0 :             return -1;
          88                 :          0 :         case E_NOMEM:
          89                 :          0 :             PyErr_NoMemory();
          90                 :          0 :             return -1;
          91                 :          0 :         case E_TABSPACE:
          92                 :          0 :             errtype = PyExc_TabError;
          93                 :          0 :             msg = "inconsistent use of tabs and spaces in indentation";
          94                 :          0 :             break;
          95                 :          0 :         case E_TOODEEP:
          96                 :          0 :             errtype = PyExc_IndentationError;
          97                 :          0 :             msg = "too many levels of indentation";
          98                 :          0 :             break;
          99                 :          0 :         case E_LINECONT: {
         100                 :          0 :             col_offset = p->tok->cur - p->tok->buf - 1;
         101                 :          0 :             msg = "unexpected character after line continuation character";
         102                 :          0 :             break;
         103                 :            :         }
         104                 :          0 :         default:
         105                 :          0 :             msg = "unknown parsing error";
         106                 :            :     }
         107                 :            :
         108                 :          0 :     RAISE_ERROR_KNOWN_LOCATION(p, errtype, p->tok->lineno,
         109                 :            :                                col_offset >= 0 ? col_offset : 0,
         110                 :          0 :                                p->tok->lineno, -1, msg);
         111                 :          0 :     return -1;
         112                 :            : }
         113                 :            :
         114                 :            : int
         115                 :          0 : _Pypegen_raise_decode_error(Parser *p)
         116                 :            : {
         117                 :            :     assert(PyErr_Occurred());
         118                 :          0 :     const char *errtype = NULL;
         119         [ #  # ]:          0 :     if (PyErr_ExceptionMatches(PyExc_UnicodeError)) {
         120                 :          0 :         errtype = "unicode error";
         121                 :            :     }
         122         [ #  # ]:          0 :     else if (PyErr_ExceptionMatches(PyExc_ValueError)) {
         123                 :          0 :         errtype = "value error";
         124                 :            :     }
         125         [ #  # ]:          0 :     if (errtype) {
         126                 :            :         PyObject *type;
         127                 :            :         PyObject *value;
         128                 :            :         PyObject *tback;
         129                 :            :         PyObject *errstr;
         130                 :          0 :         PyErr_Fetch(&type, &value, &tback);
         131                 :          0 :         errstr = PyObject_Str(value);
         132         [ #  # ]:          0 :         if (errstr) {
         133                 :          0 :             RAISE_SYNTAX_ERROR("(%s) %U", errtype, errstr);
         134                 :          0 :             Py_DECREF(errstr);
         135                 :            :         }
         136                 :            :         else {
         137                 :          0 :             PyErr_Clear();
         138                 :          0 :             RAISE_SYNTAX_ERROR("(%s) unknown error", errtype);
         139                 :            :         }
         140                 :          0 :         Py_XDECREF(type);
         141                 :          0 :         Py_XDECREF(value);
         142                 :          0 :         Py_XDECREF(tback);
         143                 :            :     }
         144                 :            :
         145                 :          0 :     return -1;
         146                 :            : }
         147                 :            :
         148                 :            : static int
         149                 :          0 : _PyPegen_tokenize_full_source_to_check_for_errors(Parser *p) {
         150                 :            :     // Tokenize the whole input to see if there are any tokenization
         151                 :            :     // errors such as mistmatching parentheses. These will get priority
         152                 :            :     // over generic syntax errors only if the line number of the error is
         153                 :            :     // before the one that we had for the generic error.
         154                 :            :
         155                 :            :     // We don't want to tokenize to the end for interactive input
         156         [ #  # ]:          0 :     if (p->tok->prompt != NULL) {
         157                 :          0 :         return 0;
         158                 :            :     }
         159                 :            :
         160                 :            :     PyObject *type, *value, *traceback;
         161                 :          0 :     PyErr_Fetch(&type, &value, &traceback);
         162                 :            :
         163         [ #  # ]:          0 :     Token *current_token = p->known_err_token != NULL ? p->known_err_token : p->tokens[p->fill - 1];
         164                 :          0 :     Py_ssize_t current_err_line = current_token->lineno;
         165                 :            :
         166                 :          0 :     int ret = 0;
         167                 :            :     struct token new_token;
         168                 :            :
         169                 :            :     for (;;) {
         170      [ #  #  # ]:          0 :         switch (_PyTokenizer_Get(p->tok, &new_token)) {
         171                 :          0 :             case ERRORTOKEN:
         172         [ #  # ]:          0 :                 if (PyErr_Occurred()) {
         173                 :          0 :                     ret = -1;
         174                 :          0 :                     goto exit;
         175                 :            :                 }
         176         [ #  # ]:          0 :                 if (p->tok->level != 0) {
         177                 :          0 :                     int error_lineno = p->tok->parenlinenostack[p->tok->level-1];
         178         [ #  # ]:          0 :                     if (current_err_line > error_lineno) {
         179                 :          0 :                         raise_unclosed_parentheses_error(p);
         180                 :          0 :                         ret = -1;
         181                 :          0 :                         goto exit;
         182                 :            :                     }
         183                 :            :                 }
         184                 :          0 :                 break;
         185                 :          0 :             case ENDMARKER:
         186                 :          0 :                 break;
         187                 :          0 :             default:
         188                 :          0 :                 continue;
         189                 :            :         }
         190                 :          0 :         break;
         191                 :            :     }
         192                 :            :
         193                 :            :
         194                 :          0 : exit:
         195         [ #  # ]:          0 :     if (PyErr_Occurred()) {
         196                 :          0 :         Py_XDECREF(value);
         197                 :          0 :         Py_XDECREF(type);
         198                 :          0 :         Py_XDECREF(traceback);
         199                 :            :     } else {
         200                 :          0 :         PyErr_Restore(type, value, traceback);
         201                 :            :     }
         202                 :          0 :     return ret;
         203                 :            : }
         204                 :            :
         205                 :            : // PARSER ERRORS
         206                 :            :
         207                 :            : void *
         208                 :          0 : _PyPegen_raise_error(Parser *p, PyObject *errtype, const char *errmsg, ...)
         209                 :            : {
         210         [ #  # ]:          0 :     if (p->fill == 0) {
         211                 :            :         va_list va;
         212                 :          0 :         va_start(va, errmsg);
         213                 :          0 :         _PyPegen_raise_error_known_location(p, errtype, 0, 0, 0, -1, errmsg, va);
         214                 :          0 :         va_end(va);
         215                 :          0 :         return NULL;
         216                 :            :     }
         217                 :            :
         218         [ #  # ]:          0 :     Token *t = p->known_err_token != NULL ? p->known_err_token : p->tokens[p->fill - 1];
         219                 :            :     Py_ssize_t col_offset;
         220                 :          0 :     Py_ssize_t end_col_offset = -1;
         221         [ #  # ]:          0 :     if (t->col_offset == -1) {
         222         [ #  # ]:          0 :         if (p->tok->cur == p->tok->buf) {
         223                 :          0 :             col_offset = 0;
         224                 :            :         } else {
         225         [ #  # ]:          0 :             const char* start = p->tok->buf  ? p->tok->line_start : p->tok->buf;
         226                 :          0 :             col_offset = Py_SAFE_DOWNCAST(p->tok->cur - start, intptr_t, int);
         227                 :            :         }
         228                 :            :     } else {
         229                 :          0 :         col_offset = t->col_offset + 1;
         230                 :            :     }
         231                 :            :
         232         [ #  # ]:          0 :     if (t->end_col_offset != -1) {
         233                 :          0 :         end_col_offset = t->end_col_offset + 1;
         234                 :            :     }
         235                 :            :
         236                 :            :     va_list va;
         237                 :          0 :     va_start(va, errmsg);
         238                 :          0 :     _PyPegen_raise_error_known_location(p, errtype, t->lineno, col_offset, t->end_lineno, end_col_offset, errmsg, va);
         239                 :          0 :     va_end(va);
         240                 :            :
         241                 :          0 :     return NULL;
         242                 :            : }
         243                 :            :
         244                 :            : static PyObject *
         245                 :          0 : get_error_line_from_tokenizer_buffers(Parser *p, Py_ssize_t lineno)
         246                 :            : {
         247                 :            :     /* If the file descriptor is interactive, the source lines of the current
         248                 :            :      * (multi-line) statement are stored in p->tok->interactive_src_start.
         249                 :            :      * If not, we're parsing from a string, which means that the whole source
         250                 :            :      * is stored in p->tok->str. */
         251                 :            :     assert((p->tok->fp == NULL && p->tok->str != NULL) || p->tok->fp != NULL);
         252                 :            :
         253         [ #  # ]:          0 :     char *cur_line = p->tok->fp_interactive ? p->tok->interactive_src_start : p->tok->str;
         254         [ #  # ]:          0 :     if (cur_line == NULL) {
         255                 :            :         assert(p->tok->fp_interactive);
         256                 :            :         // We can reach this point if the tokenizer buffers for interactive source have not been
         257                 :            :         // initialized because we failed to decode the original source with the given locale.
         258                 :          0 :         return PyUnicode_FromStringAndSize("", 0);
         259                 :            :     }
         260                 :            :
         261         [ #  # ]:          0 :     Py_ssize_t relative_lineno = p->starting_lineno ? lineno - p->starting_lineno + 1 : lineno;
         262         [ #  # ]:          0 :     const char* buf_end = p->tok->fp_interactive ? p->tok->interactive_src_end : p->tok->inp;
         263                 :            :
         264         [ #  # ]:          0 :     for (int i = 0; i < relative_lineno - 1; i++) {
         265                 :          0 :         char *new_line = strchr(cur_line, '\n');
         266                 :            :         // The assert is here for debug builds but the conditional that
         267                 :            :         // follows is there so in release builds we do not crash at the cost
         268                 :            :         // to report a potentially wrong line.
         269                 :            :         assert(new_line != NULL && new_line + 1 < buf_end);
         270   [ #  #  #  # ]:          0 :         if (new_line == NULL || new_line + 1 > buf_end) {
         271                 :            :             break;
         272                 :            :         }
         273                 :          0 :         cur_line = new_line + 1;
         274                 :            :     }
         275                 :            :
         276                 :            :     char *next_newline;
         277         [ #  # ]:          0 :     if ((next_newline = strchr(cur_line, '\n')) == NULL) { // This is the last line
         278                 :          0 :         next_newline = cur_line + strlen(cur_line);
         279                 :            :     }
         280                 :          0 :     return PyUnicode_DecodeUTF8(cur_line, next_newline - cur_line, "replace");
         281                 :            : }
         282                 :            :
         283                 :            : void *
         284                 :          0 : _PyPegen_raise_error_known_location(Parser *p, PyObject *errtype,
         285                 :            :                                     Py_ssize_t lineno, Py_ssize_t col_offset,
         286                 :            :                                     Py_ssize_t end_lineno, Py_ssize_t end_col_offset,
         287                 :            :                                     const char *errmsg, va_list va)
         288                 :            : {
         289                 :          0 :     PyObject *value = NULL;
         290                 :          0 :     PyObject *errstr = NULL;
         291                 :          0 :     PyObject *error_line = NULL;
         292                 :          0 :     PyObject *tmp = NULL;
         293                 :          0 :     p->error_indicator = 1;
         294                 :            :
         295         [ #  # ]:          0 :     if (end_lineno == CURRENT_POS) {
         296                 :          0 :         end_lineno = p->tok->lineno;
         297                 :            :     }
         298         [ #  # ]:          0 :     if (end_col_offset == CURRENT_POS) {
         299                 :          0 :         end_col_offset = p->tok->cur - p->tok->line_start;
         300                 :            :     }
         301                 :            :
         302         [ #  # ]:          0 :     if (p->start_rule == Py_fstring_input) {
         303                 :          0 :         const char *fstring_msg = "f-string: ";
         304                 :          0 :         Py_ssize_t len = strlen(fstring_msg) + strlen(errmsg);
         305                 :            :
         306                 :          0 :         char *new_errmsg = PyMem_Malloc(len + 1); // Lengths of both strings plus NULL character
         307         [ #  # ]:          0 :         if (!new_errmsg) {
         308                 :          0 :             return (void *) PyErr_NoMemory();
         309                 :            :         }
         310                 :            :
         311                 :            :         // Copy both strings into new buffer
         312                 :          0 :         memcpy(new_errmsg, fstring_msg, strlen(fstring_msg));
         313                 :          0 :         memcpy(new_errmsg + strlen(fstring_msg), errmsg, strlen(errmsg));
         314                 :          0 :         new_errmsg[len] = 0;
         315                 :          0 :         errmsg = new_errmsg;
         316                 :            :     }
         317                 :          0 :     errstr = PyUnicode_FromFormatV(errmsg, va);
         318         [ #  # ]:          0 :     if (!errstr) {
         319                 :          0 :         goto error;
         320                 :            :     }
         321                 :            :
         322   [ #  #  #  # ]:          0 :     if (p->tok->fp_interactive && p->tok->interactive_src_start != NULL) {
         323                 :          0 :         error_line = get_error_line_from_tokenizer_buffers(p, lineno);
         324                 :            :     }
         325         [ #  # ]:          0 :     else if (p->start_rule == Py_file_input) {
         326                 :          0 :         error_line = _PyErr_ProgramDecodedTextObject(p->tok->filename,
         327                 :          0 :                                                      (int) lineno, p->tok->encoding);
         328                 :            :     }
         329                 :            :
         330         [ #  # ]:          0 :     if (!error_line) {
         331                 :            :         /* PyErr_ProgramTextObject was not called or returned NULL. If it was not called,
         332                 :            :            then we need to find the error line from some other source, because
         333                 :            :            p->start_rule != Py_file_input. If it returned NULL, then it either unexpectedly
         334                 :            :            failed or we're parsing from a string or the REPL. There's a third edge case where
         335                 :            :            we're actually parsing from a file, which has an E_EOF SyntaxError and in that case
         336                 :            :            `PyErr_ProgramTextObject` fails because lineno points to last_file_line + 1, which
         337                 :            :            does not physically exist */
         338                 :            :         assert(p->tok->fp == NULL || p->tok->fp == stdin || p->tok->done == E_EOF);
         339                 :            :
         340   [ #  #  #  # ]:          0 :         if (p->tok->lineno <= lineno && p->tok->inp > p->tok->buf) {
         341                 :          0 :             Py_ssize_t size = p->tok->inp - p->tok->buf;
         342                 :          0 :             error_line = PyUnicode_DecodeUTF8(p->tok->buf, size, "replace");
         343                 :            :         }
         344   [ #  #  #  # ]:          0 :         else if (p->tok->fp == NULL || p->tok->fp == stdin) {
         345                 :          0 :             error_line = get_error_line_from_tokenizer_buffers(p, lineno);
         346                 :            :         }
         347                 :            :         else {
         348                 :          0 :             error_line = PyUnicode_FromStringAndSize("", 0);
         349                 :            :         }
         350         [ #  # ]:          0 :         if (!error_line) {
         351                 :          0 :             goto error;
         352                 :            :         }
         353                 :            :     }
         354                 :            :
         355         [ #  # ]:          0 :     if (p->start_rule == Py_fstring_input) {
         356                 :          0 :         col_offset -= p->starting_col_offset;
         357                 :          0 :         end_col_offset -= p->starting_col_offset;
         358                 :            :     }
         359                 :            :
         360                 :          0 :     Py_ssize_t col_number = col_offset;
         361                 :          0 :     Py_ssize_t end_col_number = end_col_offset;
         362                 :            :
         363         [ #  # ]:          0 :     if (p->tok->encoding != NULL) {
         364                 :          0 :         col_number = _PyPegen_byte_offset_to_character_offset(error_line, col_offset);
         365         [ #  # ]:          0 :         if (col_number < 0) {
         366                 :          0 :             goto error;
         367                 :            :         }
         368         [ #  # ]:          0 :         if (end_col_number > 0) {
         369                 :          0 :             Py_ssize_t end_col_offset = _PyPegen_byte_offset_to_character_offset(error_line, end_col_number);
         370         [ #  # ]:          0 :             if (end_col_offset < 0) {
         371                 :          0 :                 goto error;
         372                 :            :             } else {
         373                 :          0 :                 end_col_number = end_col_offset;
         374                 :            :             }
         375                 :            :         }
         376                 :            :     }
         377                 :          0 :     tmp = Py_BuildValue("(OnnNnn)", p->tok->filename, lineno, col_number, error_line, end_lineno, end_col_number);
         378         [ #  # ]:          0 :     if (!tmp) {
         379                 :          0 :         goto error;
         380                 :            :     }
         381                 :          0 :     value = PyTuple_Pack(2, errstr, tmp);
         382                 :          0 :     Py_DECREF(tmp);
         383         [ #  # ]:          0 :     if (!value) {
         384                 :          0 :         goto error;
         385                 :            :     }
         386                 :          0 :     PyErr_SetObject(errtype, value);
         387                 :            :
         388                 :          0 :     Py_DECREF(errstr);
         389                 :          0 :     Py_DECREF(value);
         390         [ #  # ]:          0 :     if (p->start_rule == Py_fstring_input) {
         391                 :          0 :         PyMem_Free((void *)errmsg);
         392                 :            :     }
         393                 :          0 :     return NULL;
         394                 :            :
         395                 :          0 : error:
         396                 :          0 :     Py_XDECREF(errstr);
         397                 :          0 :     Py_XDECREF(error_line);
         398         [ #  # ]:          0 :     if (p->start_rule == Py_fstring_input) {
         399                 :          0 :         PyMem_Free((void *)errmsg);
         400                 :            :     }
         401                 :          0 :     return NULL;
         402                 :            : }
         403                 :            :
         404                 :            : void
         405                 :          0 : _Pypegen_set_syntax_error(Parser* p, Token* last_token) {
         406                 :            :     // Existing sintax error
         407         [ #  # ]:          0 :     if (PyErr_Occurred()) {
         408                 :            :         // Prioritize tokenizer errors to custom syntax errors raised
         409                 :            :         // on the second phase only if the errors come from the parser.
         410   [ #  #  #  # ]:          0 :         int is_tok_ok = (p->tok->done == E_DONE || p->tok->done == E_OK);
         411   [ #  #  #  # ]:          0 :         if (is_tok_ok && PyErr_ExceptionMatches(PyExc_SyntaxError)) {
         412                 :          0 :             _PyPegen_tokenize_full_source_to_check_for_errors(p);
         413                 :            :         }
         414                 :            :         // Propagate the existing syntax error.
         415                 :          0 :         return;
         416                 :            :     }
         417                 :            :     // Initialization error
         418         [ #  # ]:          0 :     if (p->fill == 0) {
         419                 :          0 :         RAISE_SYNTAX_ERROR("error at start before reading any input");
         420                 :            :     }
         421                 :            :     // Parser encountered EOF (End of File) unexpectedtly
         422   [ #  #  #  # ]:          0 :     if (last_token->type == ERRORTOKEN && p->tok->done == E_EOF) {
         423         [ #  # ]:          0 :         if (p->tok->level) {
         424                 :          0 :             raise_unclosed_parentheses_error(p);
         425                 :            :         } else {
         426                 :          0 :             RAISE_SYNTAX_ERROR("unexpected EOF while parsing");
         427                 :            :         }
         428                 :          0 :         return;
         429                 :            :     }
         430                 :            :     // Indentation error in the tokenizer
         431   [ #  #  #  # ]:          0 :     if (last_token->type == INDENT || last_token->type == DEDENT) {
         432         [ #  # ]:          0 :         RAISE_INDENTATION_ERROR(last_token->type == INDENT ? "unexpected indent" : "unexpected unindent");
         433                 :          0 :         return;
         434                 :            :     }
         435                 :            :     // Unknown error (generic case)
         436                 :            :
         437                 :            :     // Use the last token we found on the first pass to avoid reporting
         438                 :            :     // incorrect locations for generic syntax errors just because we reached
         439                 :            :     // further away when trying to find specific syntax errors in the second
         440                 :            :     // pass.
         441                 :          0 :     RAISE_SYNTAX_ERROR_KNOWN_LOCATION(last_token, "invalid syntax");
         442                 :            :     // _PyPegen_tokenize_full_source_to_check_for_errors will override the existing
         443                 :            :     // generic SyntaxError we just raised if errors are found.
         444                 :          0 :     _PyPegen_tokenize_full_source_to_check_for_errors(p);
         445                 :            : }

Generated by: LCOV version 1.14