📄 parsermodule.c
字号:
if (TYPE(n) != t) {
PyErr_Format(parser_error, "Expected node type %d, got %d.",
t, TYPE(n));
return 0;
}
return 1;
}
/* 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)
{
if (NCH(n) != num) {
PyErr_Format(parser_error,
"Illegal number of children for %s node.", name);
return 0;
}
return 1;
}
static int
validate_terminal(node *terminal, int type, char *string)
{
int res = (validate_ntype(terminal, type)
&& ((string == 0) || (strcmp(string, STR(terminal)) == 0)));
if (!res && !PyErr_Occurred()) {
PyErr_Format(parser_error,
"Illegal terminal: expected \"%s\"", string);
}
return (res);
}
/* X (',' X) [',']
*/
static int
validate_repeating_list(node *tree, int ntype, int (*vfunc)(node *),
const char *const name)
{
int nch = NCH(tree);
int res = (nch && validate_ntype(tree, ntype)
&& vfunc(CHILD(tree, 0)));
if (!res && !PyErr_Occurred())
(void) validate_numnodes(tree, 1, 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)));
}
}
return (res);
}
/* validate_class()
*
* classdef:
* 'class' NAME ['(' testlist ')'] ':' suite
*/
static int
validate_class(node *tree)
{
int nch = NCH(tree);
int res = validate_ntype(tree, classdef) && ((nch == 4) || (nch == 7));
if (res) {
res = (validate_name(CHILD(tree, 0), "class")
&& validate_ntype(CHILD(tree, 1), NAME)
&& validate_colon(CHILD(tree, nch - 2))
&& validate_suite(CHILD(tree, nch - 1)));
}
else
(void) validate_numnodes(tree, 4, "class");
if (res && (nch == 7)) {
res = (validate_lparen(CHILD(tree, 2))
&& validate_testlist(CHILD(tree, 3))
&& validate_rparen(CHILD(tree, 4)));
}
return (res);
}
/* if_stmt:
* 'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite]
*/
static int
validate_if(node *tree)
{
int nch = NCH(tree);
int res = (validate_ntype(tree, if_stmt)
&& (nch >= 4)
&& validate_name(CHILD(tree, 0), "if")
&& validate_test(CHILD(tree, 1))
&& validate_colon(CHILD(tree, 2))
&& validate_suite(CHILD(tree, 3)));
if (res && ((nch % 4) == 3)) {
/* ... 'else' ':' suite */
res = (validate_name(CHILD(tree, nch - 3), "else")
&& validate_colon(CHILD(tree, nch - 2))
&& validate_suite(CHILD(tree, nch - 1)));
nch -= 3;
}
else if (!res && !PyErr_Occurred())
(void) validate_numnodes(tree, 4, "if");
if ((nch % 4) != 0)
/* Will catch the case for nch < 4 */
res = validate_numnodes(tree, 0, "if");
else if (res && (nch > 4)) {
/* ... ('elif' test ':' suite)+ ... */
int j = 4;
while ((j < nch) && res) {
res = (validate_name(CHILD(tree, j), "elif")
&& validate_colon(CHILD(tree, j + 2))
&& validate_test(CHILD(tree, j + 1))
&& validate_suite(CHILD(tree, j + 3)));
j += 4;
}
}
return (res);
}
/* parameters:
* '(' [varargslist] ')'
*
*/
static int
validate_parameters(node *tree)
{
int nch = NCH(tree);
int res = validate_ntype(tree, parameters) && ((nch == 2) || (nch == 3));
if (res) {
res = (validate_lparen(CHILD(tree, 0))
&& validate_rparen(CHILD(tree, nch - 1)));
if (res && (nch == 3))
res = validate_varargslist(CHILD(tree, 1));
}
else {
(void) validate_numnodes(tree, 2, "parameters");
}
return (res);
}
/* validate_suite()
*
* suite:
* simple_stmt
* | NEWLINE INDENT stmt+ DEDENT
*/
static int
validate_suite(node *tree)
{
int nch = NCH(tree);
int res = (validate_ntype(tree, suite) && ((nch == 1) || (nch >= 4)));
if (res && (nch == 1))
res = validate_simple_stmt(CHILD(tree, 0));
else if (res) {
/* NEWLINE INDENT stmt+ DEDENT */
res = (validate_newline(CHILD(tree, 0))
&& validate_indent(CHILD(tree, 1))
&& validate_stmt(CHILD(tree, 2))
&& validate_dedent(CHILD(tree, nch - 1)));
if (res && (nch > 4)) {
int i = 3;
--nch; /* forget the DEDENT */
for ( ; res && (i < nch); ++i)
res = validate_stmt(CHILD(tree, i));
}
else if (nch < 4)
res = validate_numnodes(tree, 4, "suite");
}
return (res);
}
static int
validate_testlist(node *tree)
{
return (validate_repeating_list(tree, testlist,
validate_test, "testlist"));
}
static int
validate_testlist_safe(node *tree)
{
return (validate_repeating_list(tree, testlist_safe,
validate_test, "testlist_safe"));
}
/* '*' 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])* [',']
*
*/
static int
validate_varargslist(node *tree)
{
int nch = NCH(tree);
int res = validate_ntype(tree, varargslist) && (nch != 0);
int sym;
if (!res)
return 0;
if (nch < 1) {
err_string("varargslist missing child nodes");
return 0;
}
sym = TYPE(CHILD(tree, 0));
if (sym == STAR || sym == DOUBLESTAR)
/* whole thing matches:
* '*' NAME [',' '**' NAME] | '**' NAME
*/
res = validate_varargslist_trailer(tree, 0);
else if (sym == fpdef) {
int i = 0;
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));
++i;
if (res && i < nch
&& (TYPE(CHILD(tree, i)) == DOUBLESTAR
|| TYPE(CHILD(tree, i)) == STAR))
break;
}
}
/* ... '*' NAME [',' '**' NAME] | '**' NAME
* i --^^^
*/
if (res)
res = validate_varargslist_trailer(tree, i);
}
else {
/*
* fpdef ['=' test] (',' fpdef ['=' test])* [',']
*/
/* strip trailing comma node */
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, i)) == EQUAL) {
res = (validate_equal(CHILD(tree, i))
&& validate_test(CHILD(tree, i+1)));
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)) == EQUAL) {
res = (validate_equal(CHILD(tree, i))
&& validate_test(CHILD(tree, i+1)));
i += 2;
}
}
if (res && nch - i != 0) {
res = 0;
err_string("illegal formation for varargslist");
}
}
}
return res;
}
/* 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_safe(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
* | '(' fplist ')'
*/
static int
validate_fpdef(node *tree)
{
int nch = NCH(tree);
int res = validate_ntype(tree, fpdef);
if (res) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -