mirror of https://github.com/python/cpython
bpo-33306: Improve SyntaxError messages for unbalanced parentheses. (GH-6516)
This commit is contained in:
parent
bdabb0737c
commit
94cf308ee2
|
@ -1004,10 +1004,14 @@ non-important content
|
|||
self.assertEqual('{d[0]}'.format(d=d), 'integer')
|
||||
|
||||
def test_invalid_expressions(self):
|
||||
self.assertAllRaise(SyntaxError, 'invalid syntax',
|
||||
[r"f'{a[4)}'",
|
||||
r"f'{a(4]}'",
|
||||
])
|
||||
self.assertAllRaise(SyntaxError,
|
||||
r"closing parenthesis '\)' does not match "
|
||||
r"opening parenthesis '\[' \(<fstring>, line 1\)",
|
||||
[r"f'{a[4)}'"])
|
||||
self.assertAllRaise(SyntaxError,
|
||||
r"closing parenthesis '\]' does not match "
|
||||
r"opening parenthesis '\(' \(<fstring>, line 1\)",
|
||||
[r"f'{a(4]}'"])
|
||||
|
||||
def test_errors(self):
|
||||
# see issue 26287
|
||||
|
|
|
@ -133,7 +133,7 @@ class HelperFunctionsTests(unittest.TestCase):
|
|||
|
||||
def test_addpackage_import_bad_syntax(self):
|
||||
# Issue 10642
|
||||
pth_dir, pth_fn = self.make_pth("import bad)syntax\n")
|
||||
pth_dir, pth_fn = self.make_pth("import bad-syntax\n")
|
||||
with captured_stderr() as err_out:
|
||||
site.addpackage(pth_dir, pth_fn, set())
|
||||
self.assertRegex(err_out.getvalue(), "line 1")
|
||||
|
@ -143,7 +143,7 @@ class HelperFunctionsTests(unittest.TestCase):
|
|||
# order doesn't matter. The next three could be a single check
|
||||
# but my regex foo isn't good enough to write it.
|
||||
self.assertRegex(err_out.getvalue(), 'Traceback')
|
||||
self.assertRegex(err_out.getvalue(), r'import bad\)syntax')
|
||||
self.assertRegex(err_out.getvalue(), r'import bad-syntax')
|
||||
self.assertRegex(err_out.getvalue(), 'SyntaxError')
|
||||
|
||||
def test_addpackage_import_bad_exec(self):
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Improved syntax error messages for unbalanced parentheses.
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue