diff Python/ast.c @ 36666:6165927431d6 legacy-trunk

PEP 308 implementation, including minor refdocs and some testcases. It breaks the parser module, because it adds the if/else construct as well as two new grammar rules for backward compatibility. If no one else fixes parsermodule, I guess I'll go ahead and fix it later this week. The TeX code was checked with texcheck.py, but not rendered. There is actually a slight incompatibility: >>> (x for x in lambda:0) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: iteration over non-sequence changes into >>> (x for x in lambda: 0) File "<stdin>", line 1 (x for x in lambda: 0) ^ SyntaxError: invalid syntax Since there's no way the former version can be useful, it's probably a bugfix ;)
author Thomas Wouters <thomas@python.org>
date Mon, 27 Feb 2006 00:24:13 +0000
parents d1ef23a16760
children 296cda9b3e2f
line wrap: on
line diff
--- a/Python/ast.c	Mon Feb 27 00:09:50 2006 +0000
+++ b/Python/ast.c	Mon Feb 27 00:24:13 2006 +0000
@@ -847,6 +847,25 @@
     return Lambda(args, expression, LINENO(n), c->c_arena);
 }
 
+static expr_ty
+ast_for_ifexpr(struct compiling *c, const node *n)
+{
+    /* test: or_test 'if' or_test 'else' test */ 
+    expr_ty expression, body, orelse;
+
+    assert(NCH(n) >= 3);
+    body = ast_for_expr(c, CHILD(n, 0));
+    if (!body)
+    	return NULL;
+    expression = ast_for_expr(c, CHILD(n, 2));
+    if (!expression)
+    	return NULL;
+    orelse = ast_for_expr(c, CHILD(n, 4));
+    if (!orelse)
+	return NULL;
+    return IfExp(expression, body, orelse, LINENO(n), c->c_arena);
+}
+
 /* Count the number of 'for' loop in a list comprehension.
 
    Helper for ast_for_listcomp().
@@ -1456,7 +1475,8 @@
 ast_for_expr(struct compiling *c, const node *n)
 {
     /* handle the full range of simple expressions
-       test: and_test ('or' and_test)* | lambdef
+       test: or_test ['if' or_test 'else' test] | lambdef
+       or_test: and_test ('or' and_test)* 
        and_test: not_test ('and' not_test)*
        not_test: 'not' not_test | comparison
        comparison: expr (comp_op expr)*
@@ -1468,6 +1488,15 @@
        term: factor (('*'|'/'|'%'|'//') factor)*
        factor: ('+'|'-'|'~') factor | power
        power: atom trailer* ('**' factor)*
+
+       As well as modified versions that exist for backward compatibility,
+       to explicitly allow:
+       [ x for x in lambda: 0, lambda: 1 ]
+       (which would be ambiguous without these extra rules)
+       
+       old_test: or_test | old_lambdef
+       old_lambdef: 'lambda' [vararglist] ':' old_test
+
     */
 
     asdl_seq *seq;
@@ -1476,9 +1505,14 @@
  loop:
     switch (TYPE(n)) {
         case test:
-            if (TYPE(CHILD(n, 0)) == lambdef)
+        case old_test:
+            if (TYPE(CHILD(n, 0)) == lambdef ||
+                TYPE(CHILD(n, 0)) == old_lambdef)
                 return ast_for_lambdef(c, CHILD(n, 0));
-            /* Fall through to and_test */
+            else if (NCH(n) > 1)
+                return ast_for_ifexpr(c, n);
+	    /* Fallthrough */
+	case or_test:
         case and_test:
             if (NCH(n) == 1) {
                 n = CHILD(n, 0);