mirror of
https://github.com/python/cpython.git
synced 2025-07-23 11:15:24 +00:00
bpo-36256: Fix bug in parsermodule when parsing if statements (GH-12477)
bpo-36256: Fix bug in parsermodule when parsing if statements In the parser module, when validating nodes before starting the parsing with to create a ST in "parser_newstobject" there is a problem that appears when two arcs in the same DFA state has transitions with labels with the same type. For example, the DFA for if_stmt has a state with two labels with the same type: "elif" and "else" (type NAME). The algorithm tries one by one the arcs until the label that starts the arc transition has a label with the same type of the current child label we are trying to accept. In this case, the arc for "elif" comes before the arc for "else"and passes this test (because the current child label is "else" and has the same type as "elif"). This lead to expecting a namedexpr_test (305) instead of a colon (11). The solution is to compare also the string representation (in case there is one) of the labels to see if the transition that we have is the correct one.
This commit is contained in:
parent
aedc273fd9
commit
9a0000d15d
3 changed files with 23 additions and 5 deletions
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue