Update to reflect recent grammar changes (list comprehensions, extended
print statement), and fix up the extended call syntax support. Minor stylistic cleanups.
This commit is contained in:
parent
a893957c8e
commit
cff283c7b3
|
@ -58,7 +58,7 @@ parser_doc_string
|
|||
= "This is an interface to Python's internal parser.";
|
||||
|
||||
static char*
|
||||
parser_version_string = "0.4";
|
||||
parser_version_string = "0.5";
|
||||
|
||||
|
||||
typedef PyObject* (*SeqMaker) (int length);
|
||||
|
@ -888,10 +888,10 @@ VALIDATER(fpdef); VALIDATER(fplist);
|
|||
VALIDATER(stmt); VALIDATER(simple_stmt);
|
||||
VALIDATER(expr_stmt); VALIDATER(power);
|
||||
VALIDATER(print_stmt); VALIDATER(del_stmt);
|
||||
VALIDATER(return_stmt);
|
||||
VALIDATER(return_stmt); VALIDATER(list_iter);
|
||||
VALIDATER(raise_stmt); VALIDATER(import_stmt);
|
||||
VALIDATER(global_stmt);
|
||||
VALIDATER(assert_stmt);
|
||||
VALIDATER(global_stmt); VALIDATER(list_if);
|
||||
VALIDATER(assert_stmt); VALIDATER(list_for);
|
||||
VALIDATER(exec_stmt); VALIDATER(compound_stmt);
|
||||
VALIDATER(while); VALIDATER(for);
|
||||
VALIDATER(try); VALIDATER(except_clause);
|
||||
|
@ -906,6 +906,7 @@ VALIDATER(trailer); VALIDATER(subscript);
|
|||
VALIDATER(subscriptlist); VALIDATER(sliceop);
|
||||
VALIDATER(exprlist); VALIDATER(dictmaker);
|
||||
VALIDATER(arglist); VALIDATER(argument);
|
||||
VALIDATER(listmaker);
|
||||
|
||||
|
||||
#define is_even(n) (((n) & 1) == 0)
|
||||
|
@ -986,7 +987,7 @@ validate_repeating_list(node *tree, int ntype, int (*vfunc)(node *),
|
|||
}
|
||||
|
||||
|
||||
/* VALIDATE(class)
|
||||
/* validate_class()
|
||||
*
|
||||
* classdef:
|
||||
* 'class' NAME ['(' testlist ')'] ':' suite
|
||||
|
@ -1078,7 +1079,7 @@ validate_parameters(node *tree)
|
|||
}
|
||||
|
||||
|
||||
/* VALIDATE(suite)
|
||||
/* validate_suite()
|
||||
*
|
||||
* suite:
|
||||
* simple_stmt
|
||||
|
@ -1120,15 +1121,51 @@ validate_testlist(node *tree)
|
|||
}
|
||||
|
||||
|
||||
/* VALIDATE(varargslist)
|
||||
/* '*' NAME [',' '**' NAME] | '**' NAME
|
||||
*/
|
||||
static int
|
||||
validate_varargslist_trailer(node *tree, int start)
|
||||
{
|
||||
int nch = NCH(tree);
|
||||
int res = 0;
|
||||
int sym;
|
||||
|
||||
if (nch <= start) {
|
||||
err_string("expected variable argument trailer for varargslist");
|
||||
return 0;
|
||||
}
|
||||
sym = TYPE(CHILD(tree, start));
|
||||
if (sym == STAR) {
|
||||
/*
|
||||
* ('*' NAME [',' '**' NAME]
|
||||
*/
|
||||
if (nch-start == 2)
|
||||
res = validate_name(CHILD(tree, start+1), NULL);
|
||||
else if (nch-start == 5)
|
||||
res = (validate_name(CHILD(tree, start+1), NULL)
|
||||
&& validate_comma(CHILD(tree, start+2))
|
||||
&& validate_doublestar(CHILD(tree, start+3))
|
||||
&& validate_name(CHILD(tree, start+4), NULL));
|
||||
}
|
||||
else if (sym == DOUBLESTAR) {
|
||||
/*
|
||||
* '**' NAME
|
||||
*/
|
||||
if (nch-start == 2)
|
||||
res = validate_name(CHILD(tree, start+1), NULL);
|
||||
}
|
||||
if (!res)
|
||||
err_string("illegal variable argument trailer for varargslist");
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/* validate_varargslist()
|
||||
*
|
||||
* varargslist:
|
||||
* (fpdef ['=' test] ',')* ('*' NAME [',' '*' '*' NAME] | '*' '*' NAME)
|
||||
* | fpdef ['=' test] (',' fpdef ['=' test])* [',']
|
||||
*
|
||||
* (fpdef ['=' test] ',')*
|
||||
* ('*' NAME [',' ('**'|'*' '*') NAME]
|
||||
* | ('**'|'*' '*') NAME)
|
||||
* ('*' NAME [',' '**' NAME]
|
||||
* | '**' NAME)
|
||||
* | fpdef ['=' test] (',' fpdef ['=' test])* [',']
|
||||
*
|
||||
*/
|
||||
|
@ -1137,97 +1174,150 @@ validate_varargslist(node *tree)
|
|||
{
|
||||
int nch = NCH(tree);
|
||||
int res = validate_ntype(tree, varargslist) && (nch != 0);
|
||||
int sym;
|
||||
|
||||
if (res && (nch >= 2) && (TYPE(CHILD(tree, nch - 1)) == NAME)) {
|
||||
/* (fpdef ['=' test] ',')*
|
||||
* ('*' NAME [',' '*' '*' NAME] | '*' '*' NAME)
|
||||
*/
|
||||
int pos = 0;
|
||||
int remaining = nch;
|
||||
|
||||
while (res && (TYPE(CHILD(tree, pos)) == fpdef)) {
|
||||
res = validate_fpdef(CHILD(tree, pos));
|
||||
if (res) {
|
||||
if (TYPE(CHILD(tree, pos + 1)) == EQUAL) {
|
||||
res = validate_test(CHILD(tree, pos + 2));
|
||||
pos += 2;
|
||||
}
|
||||
res = res && validate_comma(CHILD(tree, pos + 1));
|
||||
pos += 2;
|
||||
}
|
||||
}
|
||||
if (res) {
|
||||
remaining = nch - pos;
|
||||
res = ((remaining == 2) || (remaining == 3)
|
||||
|| (remaining == 5) || (remaining == 6));
|
||||
if (!res)
|
||||
(void) validate_numnodes(tree, 2, "varargslist");
|
||||
else if (TYPE(CHILD(tree, pos)) == DOUBLESTAR)
|
||||
return ((remaining == 2)
|
||||
&& validate_ntype(CHILD(tree, pos+1), NAME));
|
||||
else {
|
||||
res = validate_star(CHILD(tree, pos++));
|
||||
--remaining;
|
||||
}
|
||||
}
|
||||
if (res) {
|
||||
if (remaining == 2) {
|
||||
res = (validate_star(CHILD(tree, pos))
|
||||
&& validate_ntype(CHILD(tree, pos + 1), NAME));
|
||||
}
|
||||
else {
|
||||
res = validate_ntype(CHILD(tree, pos++), NAME);
|
||||
if (res && (remaining >= 4)) {
|
||||
res = validate_comma(CHILD(tree, pos));
|
||||
if (--remaining == 3)
|
||||
res = (validate_star(CHILD(tree, pos + 1))
|
||||
&& validate_star(CHILD(tree, pos + 2)));
|
||||
else
|
||||
res = validate_ntype(CHILD(tree, pos + 1), DOUBLESTAR);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!res && !PyErr_Occurred())
|
||||
err_string("Incorrect validation of variable arguments list.");
|
||||
if (nch < 1) {
|
||||
err_string("varargslist missing child nodes");
|
||||
return 0;
|
||||
}
|
||||
else if (res) {
|
||||
/* fpdef ['=' test] (',' fpdef ['=' test])* [','] */
|
||||
if (TYPE(CHILD(tree, nch - 1)) == COMMA)
|
||||
--nch;
|
||||
sym = TYPE(CHILD(tree, 0));
|
||||
if (sym == STAR || sym == DOUBLESTAR)
|
||||
res = validate_varargslist_trailer(tree, 0);
|
||||
else if (sym == fpdef) {
|
||||
int i = 0;
|
||||
|
||||
/* fpdef ['=' test] (',' fpdef ['=' test])* */
|
||||
res = (is_odd(nch)
|
||||
&& validate_fpdef(CHILD(tree, 0)));
|
||||
|
||||
if (res && (nch > 1)) {
|
||||
int pos = 1;
|
||||
if (TYPE(CHILD(tree, 1)) == EQUAL) {
|
||||
res = validate_test(CHILD(tree, 2));
|
||||
pos += 2;
|
||||
}
|
||||
/* ... (',' fpdef ['=' test])* */
|
||||
for ( ; res && (pos < nch); pos += 2) {
|
||||
/* ',' fpdef */
|
||||
res = (validate_comma(CHILD(tree, pos))
|
||||
&& validate_fpdef(CHILD(tree, pos + 1)));
|
||||
if (res
|
||||
&& ((nch - pos) > 2)
|
||||
&& (TYPE(CHILD(tree, pos + 2)) == EQUAL)) {
|
||||
/* ['=' test] */
|
||||
res = validate_test(CHILD(tree, pos + 3));
|
||||
pos += 2;
|
||||
sym = TYPE(CHILD(tree, nch-1));
|
||||
if (sym == NAME) {
|
||||
/*
|
||||
* (fpdef ['=' test] ',')+
|
||||
* ('*' NAME [',' '**' NAME]
|
||||
* | '**' NAME)
|
||||
*/
|
||||
/* skip over (fpdef ['=' test] ',')+ */
|
||||
while (res && (i+2 <= nch)) {
|
||||
res = validate_fpdef(CHILD(tree, i));
|
||||
++i;
|
||||
if (res && TYPE(CHILD(tree, i)) == EQUAL && (i+2 <= nch)) {
|
||||
res = (validate_equal(CHILD(tree, i))
|
||||
&& validate_test(CHILD(tree, i+1)));
|
||||
if (res)
|
||||
i += 2;
|
||||
}
|
||||
if (res && i < nch) {
|
||||
res = validate_comma(CHILD(tree, i));
|
||||
if (res)
|
||||
++i;
|
||||
}
|
||||
}
|
||||
/* handle '*' NAME [',' '**' NAME] | '**' NAME */
|
||||
if (res)
|
||||
res = validate_varargslist_trailer(tree, i);
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* fpdef ['=' test] (',' fpdef ['=' test])* [',']
|
||||
*/
|
||||
if (sym == COMMA) {
|
||||
res = validate_comma(CHILD(tree, nch-1));
|
||||
if (!res)
|
||||
return 0;
|
||||
--nch;
|
||||
}
|
||||
/*
|
||||
* fpdef ['=' test] (',' fpdef ['=' test])*
|
||||
*/
|
||||
res = validate_fpdef(CHILD(tree, 0));
|
||||
++i;
|
||||
if (res && (i+2 < nch) && TYPE(CHILD(tree, 1)) == EQUAL) {
|
||||
res = (validate_equal(CHILD(tree, 1))
|
||||
&& validate_test(CHILD(tree, 2)));
|
||||
i += 2;
|
||||
}
|
||||
/*
|
||||
* ... (',' fpdef ['=' test])*
|
||||
* i ---^^^
|
||||
*/
|
||||
while (res && (nch - i) >= 2) {
|
||||
res = (validate_comma(CHILD(tree, i))
|
||||
&& validate_fpdef(CHILD(tree, i+1)));
|
||||
i += 2;
|
||||
if (res && (nch - i) >= 2
|
||||
&& TYPE(CHILD(tree, i)) == COMMA) {
|
||||
res = (validate_comma(CHILD(tree, i))
|
||||
&& validate_test(CHILD(tree, i+1)));
|
||||
if (res)
|
||||
i += 2;
|
||||
}
|
||||
}
|
||||
if (res && nch - i != 0) {
|
||||
res = 0;
|
||||
err_string("illegal formation for varargslist");
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
err_string("Improperly formed argument list.");
|
||||
}
|
||||
return (res);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/* VALIDATE(fpdef)
|
||||
/* list_iter: list_for | list_if
|
||||
*/
|
||||
static int
|
||||
validate_list_iter(node *tree)
|
||||
{
|
||||
int res = (validate_ntype(tree, list_iter)
|
||||
&& validate_numnodes(tree, 1, "list_iter"));
|
||||
if (res && TYPE(CHILD(tree, 0)) == list_for)
|
||||
res = validate_list_for(CHILD(tree, 0));
|
||||
else
|
||||
res = validate_list_if(CHILD(tree, 0));
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/* list_for: 'for' exprlist 'in' testlist [list_iter]
|
||||
*/
|
||||
static int
|
||||
validate_list_for(node *tree)
|
||||
{
|
||||
int nch = NCH(tree);
|
||||
int res;
|
||||
|
||||
if (nch == 5)
|
||||
res = validate_list_iter(CHILD(tree, 4));
|
||||
else
|
||||
res = validate_numnodes(tree, 4, "list_for");
|
||||
|
||||
if (res)
|
||||
res = (validate_name(CHILD(tree, 0), "for")
|
||||
&& validate_exprlist(CHILD(tree, 1))
|
||||
&& validate_name(CHILD(tree, 2), "in")
|
||||
&& validate_testlist(CHILD(tree, 3)));
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/* list_if: 'if' test [list_iter]
|
||||
*/
|
||||
static int
|
||||
validate_list_if(node *tree)
|
||||
{
|
||||
int nch = NCH(tree);
|
||||
int res;
|
||||
|
||||
if (nch == 3)
|
||||
res = validate_list_iter(CHILD(tree, 2));
|
||||
else
|
||||
res = validate_numnodes(tree, 2, "list_if");
|
||||
|
||||
if (res)
|
||||
res = (validate_name(CHILD(tree, 0), "if")
|
||||
&& validate_test(CHILD(tree, 1)));
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/* validate_fpdef()
|
||||
*
|
||||
* fpdef:
|
||||
* NAME
|
||||
|
@ -1387,8 +1477,8 @@ validate_expr_stmt(node *tree)
|
|||
|
||||
/* print_stmt:
|
||||
*
|
||||
* 'print' (test ',')* [test]
|
||||
*
|
||||
* 'print' ( [ test (',' test)* [','] ]
|
||||
* | '>>' test [ (',' test)+ [','] ] )
|
||||
*/
|
||||
static int
|
||||
validate_print_stmt(node *tree)
|
||||
|
@ -1396,19 +1486,40 @@ validate_print_stmt(node *tree)
|
|||
int j;
|
||||
int nch = NCH(tree);
|
||||
int res = (validate_ntype(tree, print_stmt)
|
||||
&& (nch != 0)
|
||||
&& (nch > 0)
|
||||
&& validate_name(CHILD(tree, 0), "print"));
|
||||
|
||||
if (res && is_even(nch)) {
|
||||
res = validate_test(CHILD(tree, nch - 1));
|
||||
--nch;
|
||||
}
|
||||
else if (!res && !PyErr_Occurred())
|
||||
(void) validate_numnodes(tree, 1, "print_stmt");
|
||||
for (j = 1; res && (j < nch); j += 2)
|
||||
res = (validate_test(CHILD(tree, j))
|
||||
&& validate_ntype(CHILD(tree, j + 1), COMMA));
|
||||
if (res && nch > 1) {
|
||||
int sym = TYPE(CHILD(tree, 1));
|
||||
int i = 1;
|
||||
int allow_trailing_comma = 1;
|
||||
|
||||
if (sym == test)
|
||||
res = validate_test(CHILD(tree, i++));
|
||||
else {
|
||||
if (nch < 3)
|
||||
res = validate_numnodes(tree, 3, "print_stmt");
|
||||
else {
|
||||
res = (validate_ntype(CHILD(tree, i), RIGHTSHIFT)
|
||||
&& validate_test(CHILD(tree, i+1)));
|
||||
i += 2;
|
||||
allow_trailing_comma = 0;
|
||||
}
|
||||
}
|
||||
if (res) {
|
||||
/* ... (',' test)* [','] */
|
||||
while (res && i+2 <= nch) {
|
||||
res = (validate_comma(CHILD(tree, i))
|
||||
&& validate_test(CHILD(tree, i+1)));
|
||||
allow_trailing_comma = 1;
|
||||
i += 2;
|
||||
}
|
||||
if (res && !allow_trailing_comma)
|
||||
res = validate_numnodes(tree, i, "print_stmt");
|
||||
else if (res && i < nch)
|
||||
res = validate_comma(CHILD(tree, i));
|
||||
}
|
||||
}
|
||||
return (res);
|
||||
}
|
||||
|
||||
|
@ -1466,10 +1577,54 @@ validate_raise_stmt(node *tree)
|
|||
}
|
||||
|
||||
|
||||
static int
|
||||
validate_import_as_name(node *tree)
|
||||
{
|
||||
int nch = NCH(tree);
|
||||
int ok = validate_ntype(tree, import_as_name);
|
||||
|
||||
if (ok) {
|
||||
if (nch == 1)
|
||||
ok = validate_name(CHILD(tree, 0), NULL);
|
||||
else if (nch == 3)
|
||||
ok = (validate_name(CHILD(tree, 0), NULL)
|
||||
&& validate_name(CHILD(tree, 1), "as")
|
||||
&& validate_name(CHILD(tree, 2), NULL));
|
||||
else
|
||||
ok = validate_numnodes(tree, 3, "import_as_name");
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
|
||||
/* dotted_as_name: dotted_name [NAME NAME]
|
||||
*/
|
||||
static int
|
||||
validate_dotted_as_name(node *tree)
|
||||
{
|
||||
int nch = NCH(tree);
|
||||
int res = validate_ntype(tree, dotted_as_name);
|
||||
|
||||
if (res) {
|
||||
if (nch == 1)
|
||||
res = validate_ntype(CHILD(tree, 0), dotted_name);
|
||||
else if (nch == 3)
|
||||
res = (validate_ntype(CHILD(tree, 0), dotted_name)
|
||||
&& validate_name(CHILD(tree, 1), "as")
|
||||
&& validate_name(CHILD(tree, 2), NULL));
|
||||
else {
|
||||
res = 0;
|
||||
err_string("Illegal number of children for dotted_as_name.");
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/* import_stmt:
|
||||
*
|
||||
* 'import' dotted_name (',' dotted_name)*
|
||||
* | 'from' dotted_name 'import' ('*' | NAME (',' NAME)*)
|
||||
* 'import' dotted_as_name (',' dotted_as_name)*
|
||||
* | 'from' dotted_name 'import' ('*' | import_as_name (',' import_as_name)*)
|
||||
*/
|
||||
static int
|
||||
validate_import_stmt(node *tree)
|
||||
|
@ -1477,32 +1632,35 @@ validate_import_stmt(node *tree)
|
|||
int nch = NCH(tree);
|
||||
int res = (validate_ntype(tree, import_stmt)
|
||||
&& (nch >= 2) && is_even(nch)
|
||||
&& validate_ntype(CHILD(tree, 0), NAME)
|
||||
&& validate_ntype(CHILD(tree, 1), dotted_name));
|
||||
&& validate_ntype(CHILD(tree, 0), NAME));
|
||||
|
||||
if (res && (strcmp(STR(CHILD(tree, 0)), "import") == 0)) {
|
||||
int j;
|
||||
|
||||
res = validate_dotted_as_name(CHILD(tree, 1));
|
||||
for (j = 2; res && (j < nch); j += 2)
|
||||
res = (validate_comma(CHILD(tree, j))
|
||||
&& validate_ntype(CHILD(tree, j + 1), dotted_name));
|
||||
}
|
||||
else if (res && validate_name(CHILD(tree, 0), "from")) {
|
||||
else if (res && (res = validate_name(CHILD(tree, 0), "from"))) {
|
||||
res = ((nch >= 4) && is_even(nch)
|
||||
&& validate_name(CHILD(tree, 2), "import"));
|
||||
&& validate_name(CHILD(tree, 2), "import")
|
||||
&& validate_dotted_as_name(CHILD(tree, 1)));
|
||||
if (nch == 4) {
|
||||
res = ((TYPE(CHILD(tree, 3)) == NAME)
|
||||
|| (TYPE(CHILD(tree, 3)) == STAR));
|
||||
if (!res)
|
||||
err_string("Illegal import statement.");
|
||||
if (TYPE(CHILD(tree, 3)) == import_as_name)
|
||||
res = validate_import_as_name(CHILD(tree, 3));
|
||||
else
|
||||
res = validate_star(CHILD(tree, 3));
|
||||
}
|
||||
else {
|
||||
/* 'from' NAME 'import' NAME (',' NAME)+ */
|
||||
/* 'from' dotted_name 'import' import_as_name
|
||||
* (',' import_as_name)+
|
||||
*/
|
||||
int j;
|
||||
res = validate_ntype(CHILD(tree, 3), NAME);
|
||||
res = validate_import_as_name(CHILD(tree, 3));
|
||||
for (j = 4; res && (j < nch); j += 2)
|
||||
res = (validate_comma(CHILD(tree, j))
|
||||
&& validate_ntype(CHILD(tree, j + 1), NAME));
|
||||
&& validate_import_as_name(CHILD(tree, j + 1)));
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -1983,8 +2141,10 @@ validate_atom(node *tree)
|
|||
{
|
||||
int pos;
|
||||
int nch = NCH(tree);
|
||||
int res = validate_ntype(tree, atom) && (nch >= 1);
|
||||
int res = validate_ntype(tree, atom);
|
||||
|
||||
if (res && nch < 1)
|
||||
res = validate_numnodes(tree, nch+1, "atom");
|
||||
if (res) {
|
||||
switch (TYPE(CHILD(tree, 0))) {
|
||||
case LPAR:
|
||||
|
@ -1995,11 +2155,15 @@ validate_atom(node *tree)
|
|||
res = validate_testlist(CHILD(tree, 1));
|
||||
break;
|
||||
case LSQB:
|
||||
res = ((nch <= 3)
|
||||
&& validate_ntype(CHILD(tree, nch - 1), RSQB));
|
||||
|
||||
if (res && (nch == 3))
|
||||
res = validate_testlist(CHILD(tree, 1));
|
||||
if (nch == 2)
|
||||
res = validate_ntype(CHILD(tree, 1), RSQB);
|
||||
else if (nch == 3)
|
||||
res = (validate_listmaker(CHILD(tree, 1))
|
||||
&& validate_ntype(CHILD(tree, 2), RSQB));
|
||||
else {
|
||||
res = 0;
|
||||
err_string("illegal list display atom");
|
||||
}
|
||||
break;
|
||||
case LBRACE:
|
||||
res = ((nch <= 3)
|
||||
|
@ -2030,6 +2194,38 @@ validate_atom(node *tree)
|
|||
}
|
||||
|
||||
|
||||
static int
|
||||
validate_listmaker(node *tree)
|
||||
{
|
||||
int nch = NCH(tree);
|
||||
int ok = nch;
|
||||
|
||||
if (nch == 0)
|
||||
err_string("missing child nodes of listmaker");
|
||||
else
|
||||
ok = validate_test(CHILD(tree, 0));
|
||||
|
||||
/*
|
||||
* list_iter | (',' test)* [',']
|
||||
*/
|
||||
if (nch == 2 && TYPE(CHILD(tree, 1)) == list_iter)
|
||||
ok = validate_list_iter(CHILD(tree, 1));
|
||||
else {
|
||||
/* (',' test)* [','] */
|
||||
int i = 1;
|
||||
while (ok && nch - i >= 2) {
|
||||
ok = (validate_comma(CHILD(tree, i))
|
||||
&& validate_test(CHILD(tree, i+1)));
|
||||
if (ok)
|
||||
i += 2;
|
||||
}
|
||||
if (ok && nch-i)
|
||||
ok = validate_comma(CHILD(tree, nch-1));
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
|
||||
/* funcdef:
|
||||
* 'def' NAME parameters ':' suite
|
||||
*
|
||||
|
@ -2068,81 +2264,70 @@ validate_lambdef(node *tree)
|
|||
|
||||
/* arglist:
|
||||
*
|
||||
* (argument ',')* (argument* [','] | '*' test [',' '**' test] | '**' test)
|
||||
* (argument ',')* (argument [','] | '*' test [',' '**' test] | '**' test)
|
||||
*/
|
||||
static int
|
||||
validate_arglist(node *tree)
|
||||
{
|
||||
int nch = NCH(tree);
|
||||
int i, ok = 1;
|
||||
node *last;
|
||||
int i = 0;
|
||||
int ok = 1;
|
||||
|
||||
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).
|
||||
while (ok && nch-i >= 2) {
|
||||
/* skip leading (argument ',') */
|
||||
ok = (validate_argument(CHILD(tree, i))
|
||||
&& validate_comma(CHILD(tree, i+1)));
|
||||
if (ok)
|
||||
i += 2;
|
||||
else
|
||||
PyErr_Clear();
|
||||
}
|
||||
ok = 1;
|
||||
if (nch-i > 0) {
|
||||
/*
|
||||
* argument | '*' test [',' '**' test] | '**' test
|
||||
*/
|
||||
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 */
|
||||
}
|
||||
int sym = TYPE(CHILD(tree, i));
|
||||
|
||||
if (sym == argument) {
|
||||
ok = validate_argument(CHILD(tree, i));
|
||||
if (ok && i+1 != nch) {
|
||||
err_string("illegal arglist specification"
|
||||
" (extra stuff on end)");
|
||||
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 {
|
||||
/* 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");
|
||||
err_string("illegal use of '*' in arglist");
|
||||
ok = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* 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");
|
||||
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 {
|
||||
err_string("illegal arglist specification");
|
||||
ok = 0;
|
||||
}
|
||||
}
|
||||
return (ok);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue