#4529: fix parser's validation for try-except-finally statements.

This commit is contained in:
Georg Brandl 2008-12-05 12:09:41 +00:00
parent 3129ea2e05
commit fe879e8a23
3 changed files with 36 additions and 23 deletions

View File

@ -200,6 +200,16 @@ class RoundtripLegalSyntaxTestCase(unittest.TestCase):
self.check_suite("with open('x'): pass\n") self.check_suite("with open('x'): pass\n")
self.check_suite("with open('x') as f: pass\n") self.check_suite("with open('x') as f: pass\n")
def test_try_stmt(self):
self.check_suite("try: pass\nexcept: pass\n")
self.check_suite("try: pass\nfinally: pass\n")
self.check_suite("try: pass\nexcept A: pass\nfinally: pass\n")
self.check_suite("try: pass\nexcept A: pass\nexcept: pass\n"
"finally: pass\n")
self.check_suite("try: pass\nexcept: pass\nelse: pass\n")
self.check_suite("try: pass\nexcept: pass\nelse: pass\n"
"finally: pass\n")
def test_position(self): def test_position(self):
# An absolutely minimal test of position information. Better # An absolutely minimal test of position information. Better
# tests would be a big project. # tests would be a big project.

View File

@ -60,6 +60,9 @@ Core and Builtins
Library Library
------- -------
- Issue #4529: fix the parser module's validation of try-except-finally
statements.
- Issue #4458: getopt.gnu_getopt() now recognizes a single "-" as an argument, - Issue #4458: getopt.gnu_getopt() now recognizes a single "-" as an argument,
not a malformed option. not a malformed option.

View File

@ -2057,6 +2057,7 @@ validate_for(node *tree)
/* try_stmt: /* try_stmt:
* 'try' ':' suite (except_clause ':' suite)+ ['else' ':' suite] * 'try' ':' suite (except_clause ':' suite)+ ['else' ':' suite]
['finally' ':' suite]
* | 'try' ':' suite 'finally' ':' suite * | 'try' ':' suite 'finally' ':' suite
* *
*/ */
@ -2082,35 +2083,34 @@ validate_try(node *tree)
PyErr_Format(parser_error, PyErr_Format(parser_error,
"Illegal number of children for try/%s node.", name); "Illegal number of children for try/%s node.", name);
} }
/* Skip past except_clause sections: */ /* Handle try/finally statement */
if (res && (TYPE(CHILD(tree, pos)) == NAME) &&
(strcmp(STR(CHILD(tree, pos)), "finally") == 0)) {
res = (validate_numnodes(tree, 6, "try/finally")
&& validate_colon(CHILD(tree, 4))
&& validate_suite(CHILD(tree, 5)));
return (res);
}
/* try/except statement: skip past except_clause sections */
while (res && (TYPE(CHILD(tree, pos)) == except_clause)) { while (res && (TYPE(CHILD(tree, pos)) == except_clause)) {
res = (validate_except_clause(CHILD(tree, pos)) res = (validate_except_clause(CHILD(tree, pos))
&& validate_colon(CHILD(tree, pos + 1)) && validate_colon(CHILD(tree, pos + 1))
&& validate_suite(CHILD(tree, pos + 2))); && validate_suite(CHILD(tree, pos + 2)));
pos += 3; pos += 3;
} }
if (res && (pos < nch)) { /* skip else clause */
res = validate_ntype(CHILD(tree, pos), NAME); if (res && (TYPE(CHILD(tree, pos)) == NAME) &&
if (res && (strcmp(STR(CHILD(tree, pos)), "finally") == 0)) (strcmp(STR(CHILD(tree, pos)), "else") == 0)) {
res = (validate_numnodes(tree, 6, "try/finally") res = (validate_colon(CHILD(tree, pos + 1))
&& validate_colon(CHILD(tree, 4)) && validate_suite(CHILD(tree, pos + 2)));
&& validate_suite(CHILD(tree, 5))); pos += 3;
else if (res) { }
if (nch == (pos + 3)) { if (res && pos < nch) {
res = ((strcmp(STR(CHILD(tree, pos)), "except") == 0) /* last clause must be a finally */
|| (strcmp(STR(CHILD(tree, pos)), "else") == 0)); res = (validate_name(CHILD(tree, pos), "finally")
if (!res) && validate_numnodes(tree, pos + 3, "try/except/finally")
err_string("illegal trailing triple in try statement"); && validate_colon(CHILD(tree, pos + 1))
} && validate_suite(CHILD(tree, pos + 2)));
else if (nch == (pos + 6)) {
res = (validate_name(CHILD(tree, pos), "except")
&& validate_colon(CHILD(tree, pos + 1))
&& validate_suite(CHILD(tree, pos + 2))
&& validate_name(CHILD(tree, pos + 3), "else"));
}
else
res = validate_numnodes(tree, pos + 3, "try/except");
}
} }
return (res); return (res);
} }