@@ -383,14 +383,18 @@ _PyPegen_raise_error(Parser *p, PyObject *errtype, const char *errmsg, ...)
383
383
static PyObject *
384
384
get_error_line (Parser * p , Py_ssize_t lineno )
385
385
{
386
+ // If p->tok->fp == NULL, the we're parsing from a string, which means that
387
+ // the whole source is stored in p->tok->str. If not, then we're parsing
388
+ // from the REPL, so the source lines of the current (multi-line) statement
389
+ // are stored in p->tok->stdin_content
386
390
char * cur_line = p -> tok -> fp == NULL ? p -> tok -> str : p -> tok -> stdin_content ;
387
391
for (int i = 0 ; i < lineno - 1 ; i ++ ) {
388
392
cur_line = strchr (cur_line , '\n' ) + 1 ;
389
393
}
390
394
391
395
char * next_newline ;
392
396
if ((next_newline = strchr (cur_line , '\n' )) == NULL ) { // This is the last line
393
- return PyUnicode_DecodeUTF8 ( cur_line , strlen (cur_line ), "replace" );
397
+ next_newline = cur_line + strlen (cur_line );
394
398
}
395
399
return PyUnicode_DecodeUTF8 (cur_line , next_newline - cur_line , "replace" );
396
400
}
@@ -431,6 +435,8 @@ _PyPegen_raise_error_known_location(Parser *p, PyObject *errtype,
431
435
}
432
436
433
437
if (!error_line ) {
438
+ // PyErr_ProgramTextObject returned NULL, so we're not parsing from a file
439
+ assert (p -> tok -> fp == NULL || p -> tok -> fp == stdin );
434
440
if (p -> tok -> lineno == lineno ) {
435
441
Py_ssize_t size = p -> tok -> inp - p -> tok -> buf ;
436
442
error_line = PyUnicode_DecodeUTF8 (p -> tok -> buf , size , "replace" );
0 commit comments