summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Lib/test/test_parser.py4
-rw-r--r--Misc/NEWS.d/next/Core and Builtins/2019-03-21-00-24-18.bpo-12477.OZHa0t.rst2
-rw-r--r--Modules/parsermodule.c22
3 files changed, 23 insertions, 5 deletions
diff --git a/Lib/test/test_parser.py b/Lib/test/test_parser.py
index 5548a871c0..bfa0a5a34e 100644
--- a/Lib/test/test_parser.py
+++ b/Lib/test/test_parser.py
@@ -319,6 +319,10 @@ class RoundtripLegalSyntaxTestCase(unittest.TestCase):
self.check_suite("try: pass\nexcept: pass\nelse: pass\n"
"finally: pass\n")
+ def test_if_stmt(self):
+ self.check_suite("if True:\n pass\nelse:\n pass\n")
+ self.check_suite("if True:\n pass\nelif True:\n pass\nelse:\n pass\n")
+
def test_position(self):
# An absolutely minimal test of position information. Better
# tests would be a big project.
diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-03-21-00-24-18.bpo-12477.OZHa0t.rst b/Misc/NEWS.d/next/Core and Builtins/2019-03-21-00-24-18.bpo-12477.OZHa0t.rst
new file mode 100644
index 0000000000..aada7f912a
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2019-03-21-00-24-18.bpo-12477.OZHa0t.rst
@@ -0,0 +1,2 @@
+Fix bug in parsermodule when parsing a state in a DFA that has two or more
+arcs with labels of the same type. Patch by Pablo Galindo.
diff --git a/Modules/parsermodule.c b/Modules/parsermodule.c
index b0a749a3bc..fd330b5fbe 100644
--- a/Modules/parsermodule.c
+++ b/Modules/parsermodule.c
@@ -675,7 +675,12 @@ validate_node(node *tree)
for (arc = 0; arc < dfa_state->s_narcs; ++arc) {
short a_label = dfa_state->s_arc[arc].a_lbl;
assert(a_label < _PyParser_Grammar.g_ll.ll_nlabels);
- if (_PyParser_Grammar.g_ll.ll_label[a_label].lb_type == ch_type) {
+
+ const char *label_str = _PyParser_Grammar.g_ll.ll_label[a_label].lb_str;
+ if ((_PyParser_Grammar.g_ll.ll_label[a_label].lb_type == ch_type)
+ && ((ch->n_str == NULL) || (label_str == NULL)
+ || (strcmp(ch->n_str, label_str) == 0))
+ ) {
/* The child is acceptable; if non-terminal, validate it recursively. */
if (ISNONTERMINAL(ch_type) && !validate_node(ch))
return 0;
@@ -688,17 +693,24 @@ validate_node(node *tree)
/* What would this state have accepted? */
{
short a_label = dfa_state->s_arc->a_lbl;
- int next_type;
if (!a_label) /* Wouldn't accept any more children */
goto illegal_num_children;
- next_type = _PyParser_Grammar.g_ll.ll_label[a_label].lb_type;
- if (ISNONTERMINAL(next_type))
+ int next_type = _PyParser_Grammar.g_ll.ll_label[a_label].lb_type;
+ const char *expected_str = _PyParser_Grammar.g_ll.ll_label[a_label].lb_str;
+
+ if (ISNONTERMINAL(next_type)) {
PyErr_Format(parser_error, "Expected node type %d, got %d.",
next_type, ch_type);
- else
+ }
+ else if (expected_str != NULL) {
+ PyErr_Format(parser_error, "Illegal terminal: expected '%s'.",
+ expected_str);
+ }
+ else {
PyErr_Format(parser_error, "Illegal terminal: expected %s.",
_PyParser_TokenNames[next_type]);
+ }
return 0;
}