diff options
author | Fred Drake <fdrake@acm.org> | 2000-04-25 04:14:46 (GMT) |
---|---|---|
committer | Fred Drake <fdrake@acm.org> | 2000-04-25 04:14:46 (GMT) |
commit | e7ab64e0702b460bd643c6b0630d37d09614ad46 (patch) | |
tree | e0d985ace06436ad38d74ed0d78446a9db9f8895 /Modules/parsermodule.c | |
parent | c35a20ed1e77302acb82e93efd8525e5b24cf3a3 (diff) | |
download | cpython-e7ab64e0702b460bd643c6b0630d37d09614ad46.zip cpython-e7ab64e0702b460bd643c6b0630d37d09614ad46.tar.gz cpython-e7ab64e0702b460bd643c6b0630d37d09614ad46.tar.bz2 |
validate_arglist(): Re-written to reflect extended call syntax.
validate_numnodes(): Added comment to explain the sometimes idiomatic
usage pattern.
Diffstat (limited to 'Modules/parsermodule.c')
-rw-r--r-- | Modules/parsermodule.c | 83 |
1 files changed, 80 insertions, 3 deletions
diff --git a/Modules/parsermodule.c b/Modules/parsermodule.c index bec7f43..6a8d38c 100644 --- a/Modules/parsermodule.c +++ b/Modules/parsermodule.c @@ -954,6 +954,13 @@ validate_ntype(node *n, int t) } +/* Verifies that the number of child nodes is exactly 'num', raising + * an exception if it isn't. The exception message does not indicate + * the exact number of nodes, allowing this to be used to raise the + * "right" exception when the wrong number of nodes is present in a + * specific variant of a statement's syntax. This is commonly used + * in that fashion. + */ static int validate_numnodes(node *n, int num, const char *const name) { @@ -2094,13 +2101,83 @@ validate_lambdef(node *tree) /* arglist: * - * argument (',' argument)* [','] + * (argument ',')* (argument* [','] | '*' test [',' '**' test] | '**' test) */ static int validate_arglist(node *tree) { - return (validate_repeating_list(tree, arglist, - validate_argument, "arglist")); + int nch = NCH(tree); + int i, ok; + node *last; + + if (nch <= 0) + /* raise the right error from having an invalid number of children */ + return validate_numnodes(tree, nch + 1, "arglist"); + + last = CHILD(tree, nch - 1); + if (TYPE(last) == test) { + /* Extended call syntax introduced in Python 1.6 has been used; + * validate and strip that off and continue; + * adjust nch to perform the cut, and ensure resulting nch is even + * (validation of the first part doesn't require that). + */ + if (nch < 2) { + validate_numnodes(tree, nch + 1, "arglist"); + return 0; + } + ok = validate_test(last); + if (ok) { + node *prev = CHILD(tree, nch - 2); + /* next must be '*' or '**' */ + if (validate_doublestar(prev)) { + nch -= 2; + if (nch >= 3) { + /* may include: '*' test ',' */ + last = CHILD(tree, nch - 1); + prev = CHILD(tree, nch - 2); + if (TYPE(prev) == test) { + ok = validate_comma(last) + && validate_test(prev) + && validate_star(CHILD(tree, nch - 3)); + if (ok) + nch -= 3; + } + /* otherwise, nothing special */ + } + } + else { + /* must be only: '*' test */ + PyErr_Clear(); + ok = validate_star(prev); + nch -= 2; + } + if (ok && is_odd(nch)) { + /* Illegal number of nodes before extended call syntax; + * validation of the "normal" arguments does not require + * a trailing comma, but requiring an even number of + * children will effect the same requirement. + */ + return validate_numnodes(tree, nch + 1, "arglist"); + } + } + } + /* what remains must be: (argument ",")* [argument [","]] */ + i = 0; + while (ok && nch - i >= 2) { + ok = validate_argument(CHILD(tree, i)) + && validate_comma(CHILD(tree, i + 1)); + i += 2; + } + if (ok && i < nch) { + ok = validate_comma(CHILD(tree, i)); + ++i; + } + if (i != nch) { + /* internal error! */ + ok = 0; + err_string("arglist: internal error; nch != i"); + } + return (ok); } |