diff options
author | Serhiy Storchaka <storchaka@gmail.com> | 2018-12-17 15:34:14 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-12-17 15:34:14 (GMT) |
commit | 94cf308ee231bfbfaa9ddc50b9764545a1318773 (patch) | |
tree | adc068a6567b6712226436ad399951ad888cb53c /Parser | |
parent | bdabb0737c631835b246c9823852d20331243315 (diff) | |
download | cpython-94cf308ee231bfbfaa9ddc50b9764545a1318773.zip cpython-94cf308ee231bfbfaa9ddc50b9764545a1318773.tar.gz cpython-94cf308ee231bfbfaa9ddc50b9764545a1318773.tar.bz2 |
bpo-33306: Improve SyntaxError messages for unbalanced parentheses. (GH-6516)
Diffstat (limited to 'Parser')
-rw-r--r-- | Parser/tokenizer.c | 32 | ||||
-rw-r--r-- | Parser/tokenizer.h | 5 |
2 files changed, 36 insertions, 1 deletions
diff --git a/Parser/tokenizer.c b/Parser/tokenizer.c index d319a4c..c246ee2 100644 --- a/Parser/tokenizer.c +++ b/Parser/tokenizer.c @@ -1842,12 +1842,44 @@ tok_get(struct tok_state *tok, char **p_start, char **p_end) case '(': case '[': case '{': +#ifndef PGEN + if (tok->level >= MAXLEVEL) { + return syntaxerror(tok, "too many nested parentheses"); + } + tok->parenstack[tok->level] = c; + tok->parenlinenostack[tok->level] = tok->lineno; +#endif tok->level++; break; case ')': case ']': case '}': +#ifndef PGEN + if (!tok->level) { + return syntaxerror(tok, "unmatched '%c'", c); + } +#endif tok->level--; +#ifndef PGEN + int opening = tok->parenstack[tok->level]; + if (!((opening == '(' && c == ')') || + (opening == '[' && c == ']') || + (opening == '{' && c == '}'))) + { + if (tok->parenlinenostack[tok->level] != tok->lineno) { + return syntaxerror(tok, + "closing parenthesis '%c' does not match " + "opening parenthesis '%c' on line %d", + c, opening, tok->parenlinenostack[tok->level]); + } + else { + return syntaxerror(tok, + "closing parenthesis '%c' does not match " + "opening parenthesis '%c'", + c, opening); + } + } +#endif break; } diff --git a/Parser/tokenizer.h b/Parser/tokenizer.h index 2e31d86..cd18d25 100644 --- a/Parser/tokenizer.h +++ b/Parser/tokenizer.h @@ -11,6 +11,7 @@ extern "C" { #include "token.h" /* For token types */ #define MAXINDENT 100 /* Max indentation level */ +#define MAXLEVEL 200 /* Max parentheses level */ enum decoding_state { STATE_INIT, @@ -39,14 +40,16 @@ struct tok_state { int lineno; /* Current line number */ int level; /* () [] {} Parentheses nesting level */ /* Used to allow free continuations inside them */ - /* Stuff for checking on different tab sizes */ #ifndef PGEN + char parenstack[MAXLEVEL]; + int parenlinenostack[MAXLEVEL]; /* pgen doesn't have access to Python codecs, it cannot decode the input filename. The bytes filename might be kept, but it is only used by indenterror() and it is not really needed: pgen only compiles one file (Grammar/Grammar). */ PyObject *filename; #endif + /* Stuff for checking on different tab sizes */ int altindstack[MAXINDENT]; /* Stack of alternate indents */ /* Stuff for PEP 0263 */ enum decoding_state decoding_state; |