bpo-40619: Correctly handle error lines in programs without file mode (GH-20090)

diff --git a/Lib/test/test_exceptions.py b/Lib/test/test_exceptions.py
index b689ec7..efd77fd 100644
--- a/Lib/test/test_exceptions.py
+++ b/Lib/test/test_exceptions.py
@@ -228,6 +228,8 @@
             def baz():
                 '''quux'''
             """, 9, 20)
+        check("pass\npass\npass\n(1+)\npass\npass\npass", 4, 4)
+        check("(1+)", 1, 4)
 
         # Errors thrown by symtable.c
         check('x = [(yield i) for i in range(3)]', 1, 5)
diff --git a/Parser/pegen/pegen.c b/Parser/pegen/pegen.c
index 083088b..8b79a73 100644
--- a/Parser/pegen/pegen.c
+++ b/Parser/pegen/pegen.c
@@ -300,30 +300,6 @@
     Py_XDECREF(tuple);
 }
 
-static inline PyObject *
-get_error_line(char *buffer, int is_file)
-{
-    const char *newline;
-    if (is_file) {
-        newline = strrchr(buffer, '\n');
-    } else {
-        newline = strchr(buffer, '\n');
-    }
-
-    if (is_file) {
-        while (newline > buffer && newline[-1] == '\n') {
-            --newline;
-        }
-    }
-
-    if (newline) {
-        return PyUnicode_DecodeUTF8(buffer, newline - buffer, "replace");
-    }
-    else {
-        return PyUnicode_DecodeUTF8(buffer, strlen(buffer), "replace");
-    }
-}
-
 static int
 tokenizer_error(Parser *p)
 {
@@ -422,7 +398,11 @@
     }
 
     if (!error_line) {
-        error_line = get_error_line(p->tok->buf, p->start_rule == Py_file_input);
+        Py_ssize_t size = p->tok->inp - p->tok->buf;
+        if (size && p->tok->buf[size-1] == '\n') {
+            size--;
+        }
+        error_line = PyUnicode_DecodeUTF8(p->tok->buf, size, "replace");
         if (!error_line) {
             goto error;
         }