diff options
-rw-r--r-- | Include/errcode.h | 1 | ||||
-rw-r--r-- | Misc/NEWS.d/next/Core and Builtins/2021-05-21-21-16-03.bpo-44201.bGaSjt.rst | 3 | ||||
-rw-r--r-- | Parser/pegen.c | 3 | ||||
-rw-r--r-- | Parser/tokenizer.c | 9 | ||||
-rw-r--r-- | Parser/tokenizer.h | 10 |
5 files changed, 26 insertions, 0 deletions
diff --git a/Include/errcode.h b/Include/errcode.h index f2671d6..2e07fc2 100644 --- a/Include/errcode.h +++ b/Include/errcode.h @@ -28,6 +28,7 @@ extern "C" { #define E_DECODE 22 /* Error in decoding into Unicode */ #define E_LINECONT 25 /* Unexpected characters after a line continuation */ #define E_BADSINGLE 27 /* Ill-formed single statement input */ +#define E_INTERACT_STOP 28 /* Interactive mode stopped tokenization */ #ifdef __cplusplus } diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-05-21-21-16-03.bpo-44201.bGaSjt.rst b/Misc/NEWS.d/next/Core and Builtins/2021-05-21-21-16-03.bpo-44201.bGaSjt.rst new file mode 100644 index 0000000..6f61aac --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-05-21-21-16-03.bpo-44201.bGaSjt.rst @@ -0,0 +1,3 @@ +Avoid side effects of checking for specialized syntax errors in the REPL +that was causing it to ask for extra tokens after a syntax error had been +detected. Patch by Pablo Galindo diff --git a/Parser/pegen.c b/Parser/pegen.c index 3c25e4d..548a647 100644 --- a/Parser/pegen.c +++ b/Parser/pegen.c @@ -1234,6 +1234,9 @@ reset_parser_state(Parser *p) } p->mark = 0; p->call_invalid_rules = 1; + // Don't try to get extra tokens in interactive mode when trying to + // raise specialized errors in the second pass. + p->tok->interactive_underflow = IUNDERFLOW_STOP; } static int diff --git a/Parser/tokenizer.c b/Parser/tokenizer.c index ad32293..a86af9b 100644 --- a/Parser/tokenizer.c +++ b/Parser/tokenizer.c @@ -85,6 +85,7 @@ tok_new(void) tok->async_def = 0; tok->async_def_indent = 0; tok->async_def_nl = 0; + tok->interactive_underflow = IUNDERFLOW_NORMAL; return tok; } @@ -845,6 +846,10 @@ tok_underflow_string(struct tok_state *tok) { static int tok_underflow_interactive(struct tok_state *tok) { + if (tok->interactive_underflow == IUNDERFLOW_STOP) { + tok->done = E_INTERACT_STOP; + return 1; + } char *newtok = PyOS_Readline(stdin, stdout, tok->prompt); if (newtok != NULL) { char *translated = translate_newlines(newtok, 0, tok); @@ -1399,6 +1404,10 @@ tok_get(struct tok_state *tok, const char **p_start, const char **p_end) } } + if (tok->done == E_INTERACT_STOP) { + return ENDMARKER; + } + /* Check for EOF and errors now */ if (c == EOF) { if (tok->level) { diff --git a/Parser/tokenizer.h b/Parser/tokenizer.h index aaa31f3..ff563d5 100644 --- a/Parser/tokenizer.h +++ b/Parser/tokenizer.h @@ -19,6 +19,14 @@ enum decoding_state { STATE_NORMAL }; +enum interactive_underflow_t { + /* Normal mode of operation: return a new token when asked in interactie mode */ + IUNDERFLOW_NORMAL, + /* Forcefully return ENDMARKER when asked for a new token in interactive mode. This + * can be used to prevent the tokenizer to promt the user for new tokens */ + IUNDERFLOW_STOP, +}; + /* Tokenizer state */ struct tok_state { /* Input state; buf <= cur <= inp <= end */ @@ -74,6 +82,8 @@ struct tok_state { int async_def_indent; /* Indentation level of the outermost 'async def'. */ int async_def_nl; /* =1 if the outermost 'async def' had at least one NEWLINE token after it. */ + /* How to proceed when asked for a new token in interactive mode */ + enum interactive_underflow_t interactive_underflow; }; extern struct tok_state *PyTokenizer_FromString(const char *, int); |