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