diff options
-rw-r--r-- | Lib/test/test_parser.py | 4 | ||||
-rw-r--r-- | Misc/NEWS.d/next/Core and Builtins/2019-03-21-00-24-18.bpo-12477.OZHa0t.rst | 2 | ||||
-rw-r--r-- | Modules/parsermodule.c | 22 |
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; } |