Skip to content

Commit 513d142

Browse files
pablogsaltyomitch
andauthored
[3.7] bpo-36440: include node names in ParserError messages, instead of numeric IDs (GH-12565) (GH-12671)
The error messages in the parser module are referring to numeric IDs for the nodes. To improve readability, use the node names when reporting errors.. (cherry picked from commit cb0748d) Co-authored-by: tyomitch <tyomitch@gmail.com>
1 parent 9c08eeb commit 513d142

3 files changed

Lines changed: 29 additions & 6 deletions

File tree

Lib/test/test_parser.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -713,6 +713,22 @@ def test_illegal_encoding(self):
713713
with self.assertRaises(UnicodeEncodeError):
714714
parser.sequence2st(tree)
715715

716+
def test_invalid_node_id(self):
717+
tree = (257, (269, (-7, '')))
718+
self.check_bad_tree(tree, "negative node id")
719+
tree = (257, (269, (99, '')))
720+
self.check_bad_tree(tree, "invalid token id")
721+
tree = (257, (269, (9999, (0, ''))))
722+
self.check_bad_tree(tree, "invalid symbol id")
723+
724+
def test_ParserError_message(self):
725+
try:
726+
parser.sequence2st((257,(269,(257,(0,'')))))
727+
except parser.ParserError as why:
728+
self.assertIn("simple_stmt", str(why)) # Expected
729+
self.assertIn("file_input", str(why)) # Got
730+
731+
716732

717733
class CompileTestCase(unittest.TestCase):
718734

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Include node names in ``ParserError`` messages, instead of numeric IDs.
2+
Patch by A. Skrobov.

Modules/parsermodule.c

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,6 @@
2424
* Py_[X]DECREF() and Py_[X]INCREF() macros. The lint annotations
2525
* look like "NOTE(...)".
2626
*
27-
* To debug parser errors like
28-
* "parser.ParserError: Expected node type 12, got 333."
29-
* decode symbol numbers using the automatically-generated files
30-
* Lib/symbol.h and Include/token.h.
3127
*/
3228

3329
#include "Python.h" /* general Python API */
@@ -663,6 +659,13 @@ validate_node(node *tree)
663659
for (pos = 0; pos < nch; ++pos) {
664660
node *ch = CHILD(tree, pos);
665661
int ch_type = TYPE(ch);
662+
if ((ch_type >= NT_OFFSET + _PyParser_Grammar.g_ndfas)
663+
|| (ISTERMINAL(ch_type) && (ch_type >= N_TOKENS))
664+
|| (ch_type < 0)
665+
) {
666+
PyErr_Format(parser_error, "Unrecognized node type %d.", ch_type);
667+
return 0;
668+
}
666669
for (arc = 0; arc < dfa_state->s_narcs; ++arc) {
667670
short a_label = dfa_state->s_arc[arc].a_lbl;
668671
assert(a_label < _PyParser_Grammar.g_ll.ll_nlabels);
@@ -691,8 +694,10 @@ validate_node(node *tree)
691694
const char *expected_str = _PyParser_Grammar.g_ll.ll_label[a_label].lb_str;
692695

693696
if (ISNONTERMINAL(next_type)) {
694-
PyErr_Format(parser_error, "Expected node type %d, got %d.",
695-
next_type, ch_type);
697+
PyErr_Format(parser_error, "Expected %s, got %s.",
698+
_PyParser_Grammar.g_dfa[next_type - NT_OFFSET].d_name,
699+
ISTERMINAL(ch_type) ? _PyParser_TokenNames[ch_type] :
700+
_PyParser_Grammar.g_dfa[ch_type - NT_OFFSET].d_name);
696701
}
697702
else if (expected_str != NULL) {
698703
PyErr_Format(parser_error, "Illegal terminal: expected '%s'.",

0 commit comments

Comments
 (0)