summaryrefslogtreecommitdiffstats
path: root/Modules/parsermodule.c
diff options
context:
space:
mode:
Diffstat (limited to 'Modules/parsermodule.c')
-rw-r--r--Modules/parsermodule.c377
1 files changed, 244 insertions, 133 deletions
diff --git a/Modules/parsermodule.c b/Modules/parsermodule.c
index 36e9893..6471b8e 100644
--- a/Modules/parsermodule.c
+++ b/Modules/parsermodule.c
@@ -23,6 +23,11 @@
* that lint detects are gone, but there are still warnings with
* Py_[X]DECREF() and Py_[X]INCREF() macros. The lint annotations
* look like "NOTE(...)".
+ *
+ * To debug parser errors like
+ * "parser.ParserError: Expected node type 12, got 333."
+ * decode symbol numbers using the automatically-generated files
+ * Lib/symbol.h and Include/token.h.
*/
#include "Python.h" /* general Python API */
@@ -392,7 +397,7 @@ parser_sizeof(PyST_Object *st, void *unused)
{
Py_ssize_t res;
- res = sizeof(PyST_Object) + _PyNode_SizeOf(st->st_node);
+ res = _PyObject_SIZE(Py_TYPE(st)) + _PyNode_SizeOf(st->st_node);
return PyLong_FromSsize_t(res);
}
@@ -1036,6 +1041,8 @@ VALIDATER(testlist_comp); VALIDATER(yield_expr);
VALIDATER(or_test);
VALIDATER(test_nocond); VALIDATER(lambdef_nocond);
VALIDATER(yield_arg);
+VALIDATER(async_funcdef); VALIDATER(async_stmt);
+VALIDATER(atom_expr);
#undef VALIDATER
@@ -1087,30 +1094,56 @@ validate_terminal(node *terminal, int type, char *string)
return (res);
}
+/* X (',' X) [','] */
+static int
+validate_repeating_list_variable(node *tree,
+ int list_node_type,
+ int (*validate_child_func_inc)(node *, int *),
+ int *pos,
+ const char *const list_node_type_name)
+{
+ int nch = NCH(tree);
+ int res = (nch && validate_ntype(tree, list_node_type));
-/* X (',' X) [',']
- */
+ if (!res && !PyErr_Occurred()) {
+ /* Unconditionally raise. */
+ (void) validate_numnodes(tree, 1, list_node_type_name);
+ }
+ else {
+ for ( ; res && *pos < nch; ) {
+ res = validate_child_func_inc(tree, pos);
+ if (!res || *pos >= nch)
+ break;
+ res = validate_comma(CHILD(tree, (*pos)++));
+ }
+ }
+ return res;
+}
+
+/* X (',' X) [','] */
static int
-validate_repeating_list(node *tree, int ntype, int (*vfunc)(node *),
- const char *const name)
+validate_repeating_list(node *tree,
+ int list_node_type,
+ int (*validate_child_func)(node *),
+ const char *const list_node_type_name)
{
int nch = NCH(tree);
- int res = (nch && validate_ntype(tree, ntype)
- && vfunc(CHILD(tree, 0)));
+ int res = (nch && validate_ntype(tree, list_node_type));
+ int pos = 0;
- if (!res && !PyErr_Occurred())
- (void) validate_numnodes(tree, 1, name);
+ if (!res && !PyErr_Occurred()) {
+ /* Unconditionally raise. */
+ (void) validate_numnodes(tree, 1, list_node_type_name);
+ }
else {
- if (is_even(nch))
- res = validate_comma(CHILD(tree, --nch));
- if (res && nch > 1) {
- int pos = 1;
- for ( ; res && pos < nch; pos += 2)
- res = (validate_comma(CHILD(tree, pos))
- && vfunc(CHILD(tree, pos + 1)));
+ for ( ; res && pos < nch; ) {
+ res = validate_child_func(CHILD(tree, pos++));
+ if (!res || pos >= nch)
+ break;
+ res = validate_comma(CHILD(tree, pos++));
}
}
- return (res);
+ return res;
}
@@ -1577,6 +1610,7 @@ validate_compound_stmt(node *tree)
|| (ntype == try_stmt)
|| (ntype == with_stmt)
|| (ntype == funcdef)
+ || (ntype == async_stmt)
|| (ntype == classdef)
|| (ntype == decorated))
res = validate_node(tree);
@@ -2409,27 +2443,60 @@ validate_factor(node *tree)
/* power:
*
- * power: atom trailer* ('**' factor)*
+ * power: atom_expr trailer* ['**' factor]
*/
static int
validate_power(node *tree)
{
- int pos = 1;
int nch = NCH(tree);
int res = (validate_ntype(tree, power) && (nch >= 1)
- && validate_atom(CHILD(tree, 0)));
+ && validate_atom_expr(CHILD(tree, 0)));
- while (res && (pos < nch) && (TYPE(CHILD(tree, pos)) == trailer))
- res = validate_trailer(CHILD(tree, pos++));
- if (res && (pos < nch)) {
- if (!is_even(nch - pos)) {
+ if (nch > 1) {
+ if (nch != 3) {
err_string("illegal number of nodes for 'power'");
return (0);
}
- for ( ; res && (pos < (nch - 1)); pos += 2)
- res = (validate_doublestar(CHILD(tree, pos))
- && validate_factor(CHILD(tree, pos + 1)));
+ res = (validate_doublestar(CHILD(tree, 1))
+ && validate_factor(CHILD(tree, 2)));
}
+
+ return (res);
+}
+
+
+/* atom_expr:
+ *
+ * atom_expr: [AWAIT] atom trailer*
+ */
+static int
+validate_atom_expr(node *tree)
+{
+ int start = 0;
+ int nch = NCH(tree);
+ int res;
+ int pos;
+
+ res = validate_ntype(tree, atom_expr) && (nch >= 1);
+ if (!res) {
+ return (res);
+ }
+
+ if (TYPE(CHILD(tree, 0)) == AWAIT) {
+ start = 1;
+ if (nch < 2) {
+ err_string("illegal number of nodes for 'atom_expr'");
+ return (0);
+ }
+ }
+
+ res = validate_atom(CHILD(tree, start));
+ if (res) {
+ pos = start + 1;
+ while (res && (pos < nch) && (TYPE(CHILD(tree, pos)) == trailer))
+ res = validate_trailer(CHILD(tree, pos++));
+ }
+
return (res);
}
@@ -2493,39 +2560,28 @@ validate_atom(node *tree)
/* testlist_comp:
- * test ( comp_for | (',' test)* [','] )
+ * (test|star_expr) ( comp_for | (',' (test|star_expr))* [','] )
*/
static int
validate_testlist_comp(node *tree)
{
int nch = NCH(tree);
- int ok = nch;
+ int ok;
- if (nch == 0)
+ if (nch == 0) {
err_string("missing child nodes of testlist_comp");
- else {
- ok = validate_test_or_star_expr(CHILD(tree, 0));
+ return 0;
}
- /*
- * comp_for | (',' test)* [',']
- */
- if (nch == 2 && TYPE(CHILD(tree, 1)) == comp_for)
- ok = validate_comp_for(CHILD(tree, 1));
+ if (nch == 2 && TYPE(CHILD(tree, 1)) == comp_for) {
+ ok = (validate_test(CHILD(tree, 0))
+ && validate_comp_for(CHILD(tree, 1)));
+ }
else {
- /* (',' test)* [','] */
- int i = 1;
- while (ok && nch - i >= 2) {
- ok = (validate_comma(CHILD(tree, i))
- && validate_test_or_star_expr(CHILD(tree, i+1)));
- i += 2;
- }
- if (ok && i == nch-1)
- ok = validate_comma(CHILD(tree, i));
- else if (i != nch) {
- ok = 0;
- err_string("illegal trailing nodes for testlist_comp");
- }
+ ok = validate_repeating_list(tree,
+ testlist_comp,
+ validate_test_or_star_expr,
+ "testlist_comp");
}
return ok;
}
@@ -2638,6 +2694,55 @@ validate_funcdef(node *tree)
return res;
}
+/* async_funcdef: ASYNC funcdef */
+
+static int
+validate_async_funcdef(node *tree)
+{
+ int nch = NCH(tree);
+ int res = validate_ntype(tree, async_funcdef);
+ if (res) {
+ if (nch == 2) {
+ res = (validate_ntype(CHILD(tree, 0), ASYNC)
+ && validate_funcdef(CHILD(tree, 1)));
+ }
+ else {
+ res = 0;
+ err_string("illegal number of children for async_funcdef");
+ }
+ }
+ return res;
+}
+
+
+/* async_stmt: ASYNC (funcdef | with_stmt | for_stmt) */
+
+static int
+validate_async_stmt(node *tree)
+{
+ int nch = NCH(tree);
+ int res = (validate_ntype(tree, async_stmt)
+ && validate_ntype(CHILD(tree, 0), ASYNC));
+
+ if (nch != 2) {
+ res = 0;
+ err_string("illegal number of children for async_stmt");
+ } else {
+ if (TYPE(CHILD(tree, 1)) == funcdef) {
+ res = validate_funcdef(CHILD(tree, 1));
+ }
+ else if (TYPE(CHILD(tree, 1)) == with_stmt) {
+ res = validate_with_stmt(CHILD(tree, 1));
+ }
+ else if (TYPE(CHILD(tree, 1)) == for_stmt) {
+ res = validate_for(CHILD(tree, 1));
+ }
+ }
+
+ return res;
+}
+
+
/* decorated
* decorators (classdef | funcdef)
@@ -2732,9 +2837,6 @@ validate_arglist(node *tree)
}
ok = 1;
if (nch-i > 0) {
- /*
- * argument | '*' test [',' '**' test] | '**' test
- */
int sym = TYPE(CHILD(tree, i));
if (sym == argument) {
@@ -2745,30 +2847,7 @@ validate_arglist(node *tree)
ok = 0;
}
}
- else if (sym == STAR) {
- ok = validate_star(CHILD(tree, i));
- if (ok && (nch-i == 2))
- ok = validate_test(CHILD(tree, i+1));
- else if (ok && (nch-i == 5))
- ok = (validate_test(CHILD(tree, i+1))
- && validate_comma(CHILD(tree, i+2))
- && validate_doublestar(CHILD(tree, i+3))
- && validate_test(CHILD(tree, i+4)));
- else {
- err_string("illegal use of '*' in arglist");
- ok = 0;
- }
- }
- else if (sym == DOUBLESTAR) {
- if (nch-i == 2)
- ok = (validate_doublestar(CHILD(tree, i))
- && validate_test(CHILD(tree, i+1)));
- else {
- err_string("illegal use of '**' in arglist");
- ok = 0;
- }
- }
- else {
+ else {
err_string("illegal arglist specification");
ok = 0;
}
@@ -2778,9 +2857,10 @@ validate_arglist(node *tree)
-/* argument:
- *
- * [test '='] test [comp_for]
+/* argument: ( test [comp_for] |
+ * test '=' test |
+ * '**' test |
+ * '*' test )
*/
static int
validate_argument(node *tree)
@@ -2788,14 +2868,27 @@ validate_argument(node *tree)
int nch = NCH(tree);
int res = (validate_ntype(tree, argument)
&& ((nch == 1) || (nch == 2) || (nch == 3)));
- if (res)
- res = validate_test(CHILD(tree, 0));
- if (res && (nch == 2))
- res = validate_comp_for(CHILD(tree, 1));
- else if (res && (nch == 3))
- res = (validate_equal(CHILD(tree, 1))
- && validate_test(CHILD(tree, 2)));
+ if (res) {
+ if (TYPE(CHILD(tree, 0)) == DOUBLESTAR) {
+ res = validate_test(CHILD(tree, 1));
+ }
+ else if (TYPE(CHILD(tree, 0)) == STAR) {
+ res = validate_test(CHILD(tree, 1));
+ }
+ else if (nch == 1) {
+ res = validate_test(CHILD(tree, 0));
+ }
+ else if (nch == 2) {
+ res = (validate_test(CHILD(tree, 0))
+ && validate_comp_for(CHILD(tree, 1)));
+ }
+ else if (res && (nch == 3)) {
+ res = (validate_test(CHILD(tree, 0))
+ && validate_equal(CHILD(tree, 1))
+ && validate_test(CHILD(tree, 2)));
+ }
+ }
return (res);
}
@@ -2948,11 +3041,44 @@ validate_exprlist(node *tree)
validate_expr_or_star_expr, "exprlist"));
}
+/* Incrementing validate functions returns nonzero iff success (like other
+ * validate functions, and advance *i by the length of the matched pattern. */
+
+/* test ':' test */
+static int
+validate_test_colon_test_inc(node *tree, int *i)
+{
+ return (validate_test(CHILD(tree, (*i)++))
+ && validate_colon(CHILD(tree, (*i)++))
+ && validate_test(CHILD(tree, (*i)++)));
+}
+
+/* test ':' test | '**' expr */
+static int
+validate_dict_element_inc(node *tree, int *i)
+{
+ int nch = NCH(tree);
+ int res = 0;
+ if (nch - *i >= 2) {
+ if (TYPE(CHILD(tree, *i+1)) == COLON) {
+ /* test ':' test */
+ res = validate_test_colon_test_inc(tree, i);
+ } else {
+ /* '**' expr */
+ res = (validate_doublestar(CHILD(tree, (*i)++))
+ && validate_expr(CHILD(tree, (*i)++)));
+ }
+ }
+ return res;
+}
+
/*
* dictorsetmaker:
*
- * (test ':' test (comp_for | (',' test ':' test)* [','])) |
- * (test (comp_for | (',' test)* [',']))
+ * ( ((test ':' test | '**' expr)
+ * (comp_for | (',' (test ':' test | '**' expr))* [','])) |
+ * ((test | '*' test)
+ * (comp_for | (',' (test | '*' test))* [','])) )
*/
static int
validate_dictorsetmaker(node *tree)
@@ -2966,65 +3092,44 @@ validate_dictorsetmaker(node *tree)
return 0;
if (nch - i < 1) {
+ /* Unconditionally raise. */
(void) validate_numnodes(tree, 1, "dictorsetmaker");
return 0;
}
- res = validate_test(CHILD(tree, i++));
- if (!res)
- return 0;
-
- if (nch - i >= 2 && TYPE(CHILD(tree, i)) == COLON) {
+ if (nch - i >= 2
+ && ((TYPE(CHILD(tree, i+1)) == COLON) ||
+ (TYPE(CHILD(tree, i)) == DOUBLESTAR))) {
/* Dictionary display or dictionary comprehension. */
- res = (validate_colon(CHILD(tree, i++))
- && validate_test(CHILD(tree, i++)));
- if (!res)
- return 0;
-
- if (nch - i >= 1 && TYPE(CHILD(tree, i)) == comp_for) {
+ if (nch - i >= 4 && TYPE(CHILD(tree, i+3)) == comp_for) {
/* Dictionary comprehension. */
- res = validate_comp_for(CHILD(tree, i++));
+ res = (validate_test_colon_test_inc(tree, &i)
+ && validate_comp_for(CHILD(tree, i++)));
if (!res)
return 0;
- }
- else {
+ } else {
/* Dictionary display. */
- while (nch - i >= 4) {
- res = (validate_comma(CHILD(tree, i++))
- && validate_test(CHILD(tree, i++))
- && validate_colon(CHILD(tree, i++))
- && validate_test(CHILD(tree, i++)));
- if (!res)
- return 0;
- }
- if (nch - i == 1) {
- res = validate_comma(CHILD(tree, i++));
- if (!res)
- return 0;
- }
+ return validate_repeating_list_variable(
+ tree,
+ dictorsetmaker,
+ validate_dict_element_inc,
+ &i,
+ "dictorsetmaker");
}
- }
- else {
+ } else {
/* Set display or set comprehension. */
- if (nch - i >= 1 && TYPE(CHILD(tree, i)) == comp_for) {
+ if (nch - i >= 2 && TYPE(CHILD(tree, i + 1)) == comp_for) {
/* Set comprehension. */
- res = validate_comp_for(CHILD(tree, i++));
+ res = (validate_test(CHILD(tree, i++))
+ && validate_comp_for(CHILD(tree, i++)));
if (!res)
return 0;
- }
- else {
+ } else {
/* Set display. */
- while (nch - i >= 2) {
- res = (validate_comma(CHILD(tree, i++))
- && validate_test(CHILD(tree, i++)));
- if (!res)
- return 0;
- }
- if (nch - i == 1) {
- res = validate_comma(CHILD(tree, i++));
- if (!res)
- return 0;
- }
+ return validate_repeating_list(tree,
+ dictorsetmaker,
+ validate_test_or_star_expr,
+ "dictorsetmaker");
}
}
@@ -3068,6 +3173,12 @@ validate_node(node *tree)
/*
* Definition nodes.
*/
+ case async_funcdef:
+ res = validate_async_funcdef(tree);
+ break;
+ case async_stmt:
+ res = validate_async_stmt(tree);
+ break;
case funcdef:
res = validate_funcdef(tree);
break;