Playing with the grammar: part 1, else if
Paul Svensson
paul at svensson.org
Tue Jun 12 11:15:55 EDT 2001
While poking around to figure out the Python lexer/parser/grammar all
hangs together, I happened on the discussion here about the merits of
'else if' vs 'elif'. Changing it turned out to be much easier than I
had expected, so now you can try for yourself which one you like better.
Apply this patch to your Python 1.2, and it will understand both.
/Paul
------------------------------------------------------------------------------
diff -r -c Python-2.1/Grammar/Grammar Python-2.1-UNRESERVED/Grammar/Grammar
*** Python-2.1/Grammar/Grammar Tue Feb 27 13:36:14 2001
--- Python-2.1-UNRESERVED/Grammar/Grammar Fri Jun 8 12:20:47 2001
***************
*** 57,63 ****
assert_stmt: 'assert' test [',' test]
compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt | funcdef | classdef
! if_stmt: 'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite]
while_stmt: 'while' test ':' suite ['else' ':' suite]
for_stmt: 'for' exprlist 'in' testlist ':' suite ['else' ':' suite]
try_stmt: ('try' ':' suite (except_clause ':' suite)+ #diagram:break
--- 57,63 ----
assert_stmt: 'assert' test [',' test]
compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt | funcdef | classdef
! if_stmt: 'if' test ':' suite (('elif' | 'else' 'if') test ':' suite)* ['else' ':' suite]
while_stmt: 'while' test ':' suite ['else' ':' suite]
for_stmt: 'for' exprlist 'in' testlist ':' suite ['else' ':' suite]
try_stmt: ('try' ':' suite (except_clause ':' suite)+ #diagram:break
diff -r -c Python-2.1/Modules/parsermodule.c Python-2.1-UNRESERVED/Modules/parsermodule.c
*** Python-2.1/Modules/parsermodule.c Sun Jan 7 00:59:59 2001
--- Python-2.1-UNRESERVED/Modules/parsermodule.c Thu Jun 7 12:34:22 2001
***************
*** 937,983 ****
}
/* 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] ')'
*
--- 937,1007 ----
}
+
/* if_stmt:
! * 'if' test ':' suite (('elif' | 'else' 'if') test ':' suite)* ['else' ':' suite]
*/
static int
validate_if(node *tree)
{
+ int j = 0;
int nch = NCH(tree);
+ node *last_else = nch > 4 ? CHILD(tree, nch - 3) : NULL;
int res = (validate_ntype(tree, if_stmt)
&& (nch >= 4)
&& validate_name(CHILD(tree, 0), "if")
&& validate_colon(CHILD(tree, 2))
+ && validate_test(CHILD(tree, 1))
&& validate_suite(CHILD(tree, 3)));
! if (res && last_else && TYPE(last_else) == NAME
! && STR(last_else) == "else") {
/* ... 'else' ':' suite */
! res = (validate_name(last_else, "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");
! }
else if (res && (nch > 4)) {
! /* ... (('elif' | 'else' 'if') test ':' suite)+ ... */
! j = 4;
! while (res && j < nch) {
! res = validate_ntype(CHILD(tree, j), NAME);
! if (!res)
! break;
! if (strcmp(STR(CHILD(tree, j)), "else") == 0) {
! if (j > nch - 5)
! break;
! res = (validate_name(CHILD(tree, j), "else")
! && validate_name(CHILD(tree, j + 1), "if")
! && validate_colon(CHILD(tree, j + 3))
! && validate_test(CHILD(tree, j + 2))
! && validate_suite(CHILD(tree, j + 4)));
! j += 5;
! }
! else {
! if (j > nch - 4)
! break;
! 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;
! }
}
}
+ if (res && j != nch) {
+ /* Will catch the case for nch < 4 */
+ res = validate_numnodes(tree, 0, "if");
+ }
return (res);
}
+
/* parameters:
* '(' [varargslist] ')'
*
diff -r -c Python-2.1/Python/compile.c Python-2.1-UNRESERVED/Python/compile.c
*** Python-2.1/Python/compile.c Sat Apr 14 13:51:48 2001
--- Python-2.1-UNRESERVED/Python/compile.c Thu Jun 7 14:00:39 2001
***************
*** 2813,2825 ****
static void
com_if_stmt(struct compiling *c, node *n)
{
! int i;
int anchor = 0;
REQ(n, if_stmt);
! /*'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite] */
for (i = 0; i+3 < NCH(n); i+=4) {
! int a = 0;
! node *ch = CHILD(n, i+1);
if (is_constant_false(c, ch))
continue;
if (i > 0)
--- 2812,2830 ----
static void
com_if_stmt(struct compiling *c, node *n)
{
! int i, a;
int anchor = 0;
+ node *ch;
REQ(n, if_stmt);
! /*'if' test ':' suite (('elif' | 'else' 'if') test ':' suite)* ['else' ':' suite] */
for (i = 0; i+3 < NCH(n); i+=4) {
! a = 0;
! if (TYPE(CHILD(n, i+3)) == COLON) {
! i++;
! if (i+3 >= NCH(n))
! break;
! }
! ch = CHILD(n, i+1);
if (is_constant_false(c, ch))
continue;
if (i > 0)
More information about the Python-list
mailing list