[Patches] list comprehensions

Skip Montanaro skip@mojam.com (Skip Montanaro)
Mon, 19 Jun 2000 10:43:13 -0500


In python-dev Guido wrote:

    me> I thought I submitted a 1.6-compatible update of Greg Ewing's mods
    me> awhile ago.  Should I resubmit?  To the patches list?

    guido> It's rather late in the release cycle -- I'm trying to get alpha
    guido> 3 released, and i'm still 1400 messages behind on my email.

    guido> But submitting a patch might be a good idea anyway so we won't
    guido> forget about it (and maybe it's of such baffling simplicity that
    guido> it'll charm its way past the guards :-).

Just so it doesn't get forgotten, the appended patch adds list
comprehensions to Python as developed by Greg Ewing
(greg@cosc.canterbury.ac.nz).  I only tweaked Greg's original changes to
work with 1.6.  That said, you should probably get a disclaimer from Greg as
well.

The patch includes mods to test_grammar.py which pass, though at this point
there are no documentation updates.

    I confirm that, to the best of my knowledge and belief, this
    contribution is free of any claims of third parties under
    copyright, patent or other rights or interests ("claims").  To
    the extent that I have any such claims, I hereby grant to CNRI a
    nonexclusive, irrevocable, royalty-free, worldwide license to
    reproduce, distribute, perform and/or display publicly, prepare
    derivative versions, and otherwise use this contribution as part
    of the Python software and its related documentation, or any
    derivative versions thereof, at no cost to CNRI or its licensed
    users, and to authorize others to do so.

    I acknowledge that CNRI may, at its sole discretion, decide
    whether or not to incorporate this contribution in the Python
    software and its related documentation.  I further grant CNRI
    permission to use my name and other identifying information
    provided to CNRI by me for use in connection with the Python
    software and its related documentation.

-- 
Skip Montanaro, skip@mojam.com, http://www.mojam.com/, http://www.musi-cal.com/
On June 24th at 8AM, live your life for an hour as Ricky Byrdsong always lived
his - run/walk in the Ricky Byrdsong Memorial 5K or just make a donation:
    https://www.SignmeupSports.com/Events/Index_Events.asp?EventID=1395

Index: Grammar/Grammar
===================================================================
RCS file: /cvsroot/python/python/dist/src/Grammar/Grammar,v
retrieving revision 1.35
diff -a -u -r1.35 Grammar
--- Grammar/Grammar	2000/03/28 23:49:00	1.35
+++ Grammar/Grammar	2000/06/19 15:03:26
@@ -74,7 +74,7 @@
 term: factor (('*'|'/'|'%') factor)*
 factor: ('+'|'-'|'~') factor | power
 power: atom trailer* ('**' factor)*
-atom: '(' [testlist] ')' | '[' [testlist] ']' | '{' [dictmaker] '}' | '`' testlist '`' | NAME | NUMBER | STRING+
+atom: '(' [testlist] ')' | '[' [testlist [list_iter]] ']' | '{' [dictmaker] '}' | '`' testlist '`' | NAME | NUMBER | STRING+
 lambdef: 'lambda' [varargslist] ':' test
 trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME
 subscriptlist: subscript (',' subscript)* [',']
@@ -88,3 +88,9 @@
 
 arglist: (argument ',')* (argument [',']| '*' test [',' '**' test] | '**' test)
 argument: [test '='] test	# Really [keyword '='] test
+
+#<LISTCOMP>
+list_iter: list_for | list_if
+list_for: 'for' exprlist 'in' testlist [list_iter]
+list_if: 'if' test [list_iter]
+#</LISTCOMP>
Index: Include/graminit.h
===================================================================
RCS file: /cvsroot/python/python/dist/src/Include/graminit.h,v
retrieving revision 2.13
diff -a -u -r2.13 graminit.h
--- Include/graminit.h	1997/04/02 05:23:10	2.13
+++ Include/graminit.h	2000/06/19 15:03:26
@@ -55,3 +55,6 @@
 #define classdef 310
 #define arglist 311
 #define argument 312
+#define list_iter 313
+#define list_for 314
+#define list_if 315
Index: Lib/test/test_grammar.py
===================================================================
RCS file: /cvsroot/python/python/dist/src/Lib/test/test_grammar.py,v
retrieving revision 1.13
diff -a -u -r1.13 test_grammar.py
--- Lib/test/test_grammar.py	2000/03/28 23:51:13	1.13
+++ Lib/test/test_grammar.py	2000/06/19 15:03:26
@@ -542,3 +542,38 @@
 	def meth1(self): pass
 	def meth2(self, arg): pass
 	def meth3(self, a1, a2): pass
+
+### list comprehensions...
+nums = [1, 2, 3, 4, 5]
+strs = ["Apple", "Banana", "Coconut"]
+spcs = ["  Apple", " Banana ", "Coco  nut  "]
+
+print [s.strip() for s in spcs]
+print [3 * x for x in nums]
+print [x for x in nums if x > 2]
+print [i, s for i in nums for s in strs]
+print [i, s for i in nums for s in [f for f in strs if "n" in f]]
+
+suppliers = [
+  (1, "Boeing"),
+  (2, "Ford"),
+  (3, "Macdonalds")
+]
+
+parts = [
+  (10, "Airliner"),
+  (20, "Engine"),
+  (30, "Cheeseburger")
+]
+
+suppart = [
+  (1, 10), (1, 20), (2, 20), (3, 30)
+]
+
+print [
+  (sname, pname)
+    for (sno, sname) in suppliers
+      for (pno, pname) in parts
+        for (sp_sno, sp_pno) in suppart
+          if sno == sp_sno and pno == sp_pno
+]
Index: Lib/test/output/test_grammar
===================================================================
RCS file: /cvsroot/python/python/dist/src/Lib/test/output/test_grammar,v
retrieving revision 1.3
diff -a -u -r1.3 test_grammar
--- Lib/test/output/test_grammar	2000/03/28 23:53:22	1.3
+++ Lib/test/output/test_grammar	2000/06/19 15:03:26
@@ -45,3 +45,9 @@
 
 atoms
 classdef
+['Apple', 'Banana', 'Coco  nut']
+[3, 6, 9, 12, 15]
+[3, 4, 5]
+[(1, 'Apple'), (1, 'Banana'), (1, 'Coconut'), (2, 'Apple'), (2, 'Banana'), (2, 'Coconut'), (3, 'Apple'), (3, 'Banana'), (3, 'Coconut'), (4, 'Apple'), (4, 'Banana'), (4, 'Coconut'), (5, 'Apple'), (5, 'Banana'), (5, 'Coconut')]
+[(1, 'Banana'), (1, 'Coconut'), (2, 'Banana'), (2, 'Coconut'), (3, 'Banana'), (3, 'Coconut'), (4, 'Banana'), (4, 'Coconut'), (5, 'Banana'), (5, 'Coconut')]
+[('Boeing', 'Airliner'), ('Boeing', 'Engine'), ('Ford', 'Engine'), ('Macdonalds', 'Cheeseburger')]
Index: Python/compile.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Python/compile.c,v
retrieving revision 2.108
diff -a -u -r2.108 compile.c
--- Python/compile.c	2000/05/03 23:44:38	2.108
+++ Python/compile.c	2000/06/19 15:03:27
@@ -329,6 +329,7 @@
 #ifdef PRIVATE_NAME_MANGLING
 	char *c_private;	/* for private name mangling */
 #endif
+	int c_tmpname;		/* temp local name counter */ /*LISTCOMP*/
 };
 
 
@@ -412,6 +413,16 @@
 static void com_list Py_PROTO((struct compiling *, node *, int));
 static int com_argdefs Py_PROTO((struct compiling *, node *));
 static int com_newlocal Py_PROTO((struct compiling *, char *));
+/*<LISTCOMP>*/
+static void com_list_for Py_PROTO((struct compiling *, 
+				   node *, node *, char *));
+static void com_list_if Py_PROTO((struct compiling *, 
+				  node *, node *, char *));
+static void com_list_iter Py_PROTO((struct compiling *,
+				    node *, int, node *, char *));
+static void com_list_comprehension Py_PROTO((struct compiling *, node *));
+static void com_assign Py_PROTO((struct compiling *, node *, int));
+/*</LISTCOMP>*/
 static PyCodeObject *icompile Py_PROTO((struct _node *, struct compiling *));
 static PyCodeObject *jcompile Py_PROTO((struct _node *, char *,
 					struct compiling *));
@@ -463,6 +474,7 @@
 	c->c_last_addr = 0;
 	c->c_last_line = 0;
 	c-> c_lnotab_next = 0;
+	c->c_tmpname = 0;
 	return 1;
 	
   fail:
@@ -1025,6 +1037,121 @@
 	return NULL;
 }
 
+/*<LISTCOMP>*/
+
+static void
+com_list_for(c, n, e, t)
+struct compiling *c;
+node *n, *e;
+char *t;
+{
+  PyObject *v;
+  int anchor = 0;
+  int save_begin = c->c_begin;
+
+  /*com_addfwref(c, SETUP_LOOP, &break_anchor);*/
+  /*block_push(c, SETUP_LOOP);*/
+  /* list_iter: for v in expr [list_iter] */
+  com_node(c, CHILD(n, 3)); /* expr */
+  v = PyInt_FromLong(0L);
+  if (v == NULL)
+    c->c_errors++;
+  com_addoparg(c, LOAD_CONST, com_addconst(c, v));
+  com_push(c, 1);
+  Py_XDECREF(v);
+  c->c_begin = c->c_nexti;
+  com_addoparg(c, SET_LINENO, n->n_lineno);
+  com_addfwref(c, FOR_LOOP, &anchor);
+  com_push(c, 1);
+  com_assign(c, CHILD(n, 1), OP_ASSIGN);
+  c->c_loops++;
+  com_list_iter(c, n, 4, e, t);
+  c->c_loops--;
+  com_addoparg(c, JUMP_ABSOLUTE, c->c_begin);
+  c->c_begin = save_begin;
+  com_backpatch(c, anchor);
+  com_pop(c, 2); /* FOR_LOOP has popped these */
+  /*com_addbyte(c, POP_BLOCK);*/
+  /*block_pop(c, SETUP_LOOP);*/
+  /*com_backpatch(c, break_anchor);*/
+}  
+
+static void
+com_list_if(c, n, e, t)
+struct compiling *c;
+node *n, *e;
+char *t;
+{
+  int anchor = 0;
+  int a = 0;
+  /* list_iter: 'if' test [list_iter] */
+  com_addoparg(c, SET_LINENO, n->n_lineno);
+  com_node(c, CHILD(n, 1));
+  com_addfwref(c, JUMP_IF_FALSE, &a);
+  com_addbyte(c, POP_TOP);
+  com_pop(c, 1);
+  com_list_iter(c, n, 2, e, t);
+  com_addfwref(c, JUMP_FORWARD, &anchor);
+  com_backpatch(c, a);
+  /* We jump here with an extra entry which we now pop */
+  com_addbyte(c, POP_TOP);
+  com_backpatch(c, anchor);
+}
+
+static void
+com_list_iter(c, p, i, e, t)
+struct compiling *c;
+node *p; /* parent of list_iter node */
+int i;   /* child no. in p of list_iter node */
+node *e; /* element expression */
+char *t; /* name of result list temp local */
+{
+  if (i < NCH(p)) {
+    node *n = CHILD(p, i);
+    n = CHILD(n, 0);
+    switch (TYPE(n)) {
+    case list_for: 
+      com_list_for(c, n, e, t);
+      break;
+    case list_if:
+      com_list_if(c, n, e, t);
+      break;
+    default:
+      com_error(c, PyExc_SystemError, "invalid list_iter node type");
+    }
+  }
+  else {
+    com_addopnamestr(c, LOAD_NAME, t);
+    com_push(c, 1);
+    com_addopnamestr(c, LOAD_ATTR, "append");
+    com_node(c, e);
+    com_addoparg(c, CALL_FUNCTION, 1);
+    com_addbyte(c, POP_TOP);
+    com_pop(c, 2);
+  }
+}
+
+static void
+com_list_comprehension(c, n)
+struct compiling *c;
+node *n;
+{
+  /* atom: '[' test list_iter ']' */ 
+  char tmpname[8];
+  sprintf(tmpname, "%d", ++c->c_tmpname);
+  com_addoparg(c, BUILD_LIST, 0);
+  com_push(c, 1);
+  com_addopnamestr(c, STORE_NAME, tmpname);
+  com_pop(c, 1);
+  com_list_iter(c, n, 2, CHILD(n, 1), tmpname);
+  com_addopnamestr(c, LOAD_NAME, tmpname);
+  com_push(c, 1);
+  com_addopnamestr(c, DELETE_NAME, tmpname);
+  --c->c_tmpname;
+}
+
+/*</LISTCOMP>*/
+
 static void
 com_list_constructor(c, n)
 	struct compiling *c;
@@ -1037,7 +1164,7 @@
 	/* exprlist: expr (',' expr)* [',']; likewise for testlist */
 	len = (NCH(n) + 1) / 2;
 	for (i = 0; i < NCH(n); i += 2)
-		com_node(c, CHILD(n, i));
+	  com_node(c, CHILD(n, i));
 	com_addoparg(c, BUILD_LIST, len);
 	com_pop(c, len-1);
 }
@@ -1086,8 +1213,10 @@
 			com_addoparg(c, BUILD_LIST, 0);
 			com_push(c, 1);
 		}
-		else
+		else if (TYPE(CHILD(n, 2)) == RSQB)   /*LISTCOMP*/
 			com_list_constructor(c, CHILD(n, 1));
+		else                                  /*LISTCOMP*/
+			com_list_comprehension(c, n); /*LISTCOMP*/
 		break;
 	case LBRACE: /* '{' [dictmaker] '}' */
 		com_addoparg(c, BUILD_MAP, 0);
Index: Python/graminit.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Python/graminit.c,v
retrieving revision 2.23
diff -a -u -r2.23 graminit.c
--- Python/graminit.c	2000/03/28 23:49:17	2.23
+++ Python/graminit.c	2000/06/19 15:03:27
@@ -896,11 +896,11 @@
 static arc arcs_45_0[7] = {
 	{16, 1},
 	{109, 2},
-	{111, 3},
-	{114, 4},
+	{112, 3},
+	{115, 4},
 	{12, 5},
-	{115, 5},
-	{116, 6},
+	{116, 5},
+	{117, 6},
 };
 static arc arcs_45_1[2] = {
 	{9, 7},
@@ -908,11 +908,11 @@
 };
 static arc arcs_45_2[2] = {
 	{9, 8},
-	{110, 5},
+	{111, 5},
 };
 static arc arcs_45_3[2] = {
-	{112, 9},
-	{113, 5},
+	{113, 9},
+	{114, 5},
 };
 static arc arcs_45_4[1] = {
 	{9, 10},
@@ -921,22 +921,26 @@
 	{0, 5},
 };
 static arc arcs_45_6[2] = {
-	{116, 6},
+	{117, 6},
 	{0, 6},
 };
 static arc arcs_45_7[1] = {
 	{18, 5},
 };
-static arc arcs_45_8[1] = {
-	{110, 5},
+static arc arcs_45_8[2] = {
+	{110, 11},
+	{111, 5},
 };
 static arc arcs_45_9[1] = {
-	{113, 5},
+	{114, 5},
 };
 static arc arcs_45_10[1] = {
-	{114, 5},
+	{115, 5},
 };
-static state states_45[11] = {
+static arc arcs_45_11[1] = {
+	{111, 5},
+};
+static state states_45[12] = {
 	{7, arcs_45_0},
 	{2, arcs_45_1},
 	{2, arcs_45_2},
@@ -945,12 +949,13 @@
 	{1, arcs_45_5},
 	{2, arcs_45_6},
 	{1, arcs_45_7},
-	{1, arcs_45_8},
+	{2, arcs_45_8},
 	{1, arcs_45_9},
 	{1, arcs_45_10},
+	{1, arcs_45_11},
 };
 static arc arcs_46_0[1] = {
-	{117, 1},
+	{118, 1},
 };
 static arc arcs_46_1[2] = {
 	{17, 2},
@@ -978,11 +983,11 @@
 	{52, 3},
 };
 static arc arcs_47_1[2] = {
-	{118, 4},
+	{119, 4},
 	{18, 5},
 };
 static arc arcs_47_2[1] = {
-	{119, 6},
+	{120, 6},
 };
 static arc arcs_47_3[1] = {
 	{12, 5},
@@ -994,7 +999,7 @@
 	{0, 5},
 };
 static arc arcs_47_6[1] = {
-	{110, 5},
+	{111, 5},
 };
 static state states_47[7] = {
 	{3, arcs_47_0},
@@ -1006,14 +1011,14 @@
 	{1, arcs_47_6},
 };
 static arc arcs_48_0[1] = {
-	{120, 1},
+	{121, 1},
 };
 static arc arcs_48_1[2] = {
 	{22, 2},
 	{0, 1},
 };
 static arc arcs_48_2[2] = {
-	{120, 1},
+	{121, 1},
 	{0, 2},
 };
 static state states_48[3] = {
@@ -1035,14 +1040,14 @@
 };
 static arc arcs_49_3[3] = {
 	{21, 5},
-	{121, 6},
+	{122, 6},
 	{0, 3},
 };
 static arc arcs_49_4[1] = {
 	{52, 6},
 };
 static arc arcs_49_5[2] = {
-	{121, 6},
+	{122, 6},
 	{0, 5},
 };
 static arc arcs_49_6[1] = {
@@ -1129,7 +1134,7 @@
 	{2, arcs_53_4},
 };
 static arc arcs_54_0[1] = {
-	{122, 1},
+	{123, 1},
 };
 static arc arcs_54_1[1] = {
 	{12, 2},
@@ -1164,7 +1169,7 @@
 	{1, arcs_54_7},
 };
 static arc arcs_55_0[3] = {
-	{123, 1},
+	{124, 1},
 	{23, 2},
 	{24, 3},
 };
@@ -1179,7 +1184,7 @@
 	{21, 6},
 };
 static arc arcs_55_4[4] = {
-	{123, 1},
+	{124, 1},
 	{23, 2},
 	{24, 3},
 	{0, 4},
@@ -1222,14 +1227,71 @@
 	{2, arcs_56_1},
 	{1, arcs_56_2},
 	{1, arcs_56_3},
+};
+static arc arcs_57_0[2] = {
+	{125, 1},
+	{126, 1},
+};
+static arc arcs_57_1[1] = {
+	{0, 1},
+};
+static state states_57[2] = {
+	{2, arcs_57_0},
+	{1, arcs_57_1},
+};
+static arc arcs_58_0[1] = {
+	{67, 1},
+};
+static arc arcs_58_1[1] = {
+	{39, 2},
 };
-static dfa dfas[57] = {
+static arc arcs_58_2[1] = {
+	{56, 3},
+};
+static arc arcs_58_3[1] = {
+	{9, 4},
+};
+static arc arcs_58_4[2] = {
+	{110, 5},
+	{0, 4},
+};
+static arc arcs_58_5[1] = {
+	{0, 5},
+};
+static state states_58[6] = {
+	{1, arcs_58_0},
+	{1, arcs_58_1},
+	{1, arcs_58_2},
+	{1, arcs_58_3},
+	{2, arcs_58_4},
+	{1, arcs_58_5},
+};
+static arc arcs_59_0[1] = {
+	{63, 1},
+};
+static arc arcs_59_1[1] = {
+	{21, 2},
+};
+static arc arcs_59_2[2] = {
+	{110, 3},
+	{0, 2},
+};
+static arc arcs_59_3[1] = {
+	{0, 3},
+};
+static state states_59[4] = {
+	{1, arcs_59_0},
+	{1, arcs_59_1},
+	{2, arcs_59_2},
+	{1, arcs_59_3},
+};
+static dfa dfas[60] = {
 	{256, "single_input", 0, 3, states_0,
-	 "\004\030\001\000\140\341\153\202\034\200\000\000\060\242\074\004"},
+	 "\004\030\001\000\140\341\153\202\034\200\000\000\060\042\171\010"},
 	{257, "file_input", 0, 2, states_1,
-	 "\204\030\001\000\140\341\153\202\034\200\000\000\060\242\074\004"},
+	 "\204\030\001\000\140\341\153\202\034\200\000\000\060\042\171\010"},
 	{258, "eval_input", 0, 3, states_2,
-	 "\000\020\001\000\000\000\000\000\000\200\000\000\060\242\074\000"},
+	 "\000\020\001\000\000\000\000\000\000\200\000\000\060\042\171\000"},
 	{259, "funcdef", 0, 6, states_3,
 	 "\000\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
 	{260, "parameters", 0, 4, states_4,
@@ -1241,13 +1303,13 @@
 	{263, "fplist", 0, 3, states_7,
 	 "\000\020\001\000\000\000\000\000\000\000\000\000\000\000\000\000"},
 	{264, "stmt", 0, 2, states_8,
-	 "\000\030\001\000\140\341\153\202\034\200\000\000\060\242\074\004"},
+	 "\000\030\001\000\140\341\153\202\034\200\000\000\060\042\171\010"},
 	{265, "simple_stmt", 0, 4, states_9,
-	 "\000\020\001\000\140\341\153\002\000\200\000\000\060\242\074\000"},
+	 "\000\020\001\000\140\341\153\002\000\200\000\000\060\042\171\000"},
 	{266, "small_stmt", 0, 2, states_10,
-	 "\000\020\001\000\140\341\153\002\000\200\000\000\060\242\074\000"},
+	 "\000\020\001\000\140\341\153\002\000\200\000\000\060\042\171\000"},
 	{267, "expr_stmt", 0, 2, states_11,
-	 "\000\020\001\000\000\000\000\000\000\200\000\000\060\242\074\000"},
+	 "\000\020\001\000\000\000\000\000\000\200\000\000\060\042\171\000"},
 	{268, "print_stmt", 0, 3, states_12,
 	 "\000\000\000\000\040\000\000\000\000\000\000\000\000\000\000\000"},
 	{269, "del_stmt", 0, 3, states_13,
@@ -1275,7 +1337,7 @@
 	{280, "assert_stmt", 0, 5, states_24,
 	 "\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000"},
 	{281, "compound_stmt", 0, 2, states_25,
-	 "\000\010\000\000\000\000\000\200\034\000\000\000\000\000\000\004"},
+	 "\000\010\000\000\000\000\000\200\034\000\000\000\000\000\000\010"},
 	{282, "if_stmt", 0, 8, states_26,
 	 "\000\000\000\000\000\000\000\200\000\000\000\000\000\000\000\000"},
 	{283, "while_stmt", 0, 8, states_27,
@@ -1287,59 +1349,65 @@
 	{286, "except_clause", 0, 5, states_30,
 	 "\000\000\000\000\000\000\000\000\200\000\000\000\000\000\000\000"},
 	{287, "suite", 0, 5, states_31,
-	 "\004\020\001\000\140\341\153\002\000\200\000\000\060\242\074\000"},
+	 "\004\020\001\000\140\341\153\002\000\200\000\000\060\042\171\000"},
 	{288, "test", 0, 4, states_32,
-	 "\000\020\001\000\000\000\000\000\000\200\000\000\060\242\074\000"},
+	 "\000\020\001\000\000\000\000\000\000\200\000\000\060\042\171\000"},
 	{289, "and_test", 0, 2, states_33,
-	 "\000\020\001\000\000\000\000\000\000\200\000\000\060\242\034\000"},
+	 "\000\020\001\000\000\000\000\000\000\200\000\000\060\042\071\000"},
 	{290, "not_test", 0, 3, states_34,
-	 "\000\020\001\000\000\000\000\000\000\200\000\000\060\242\034\000"},
+	 "\000\020\001\000\000\000\000\000\000\200\000\000\060\042\071\000"},
 	{291, "comparison", 0, 2, states_35,
-	 "\000\020\001\000\000\000\000\000\000\000\000\000\060\242\034\000"},
+	 "\000\020\001\000\000\000\000\000\000\000\000\000\060\042\071\000"},
 	{292, "comp_op", 0, 4, states_36,
 	 "\000\000\000\000\000\000\000\001\000\200\374\003\000\000\000\000"},
 	{293, "expr", 0, 2, states_37,
-	 "\000\020\001\000\000\000\000\000\000\000\000\000\060\242\034\000"},
+	 "\000\020\001\000\000\000\000\000\000\000\000\000\060\042\071\000"},
 	{294, "xor_expr", 0, 2, states_38,
-	 "\000\020\001\000\000\000\000\000\000\000\000\000\060\242\034\000"},
+	 "\000\020\001\000\000\000\000\000\000\000\000\000\060\042\071\000"},
 	{295, "and_expr", 0, 2, states_39,
-	 "\000\020\001\000\000\000\000\000\000\000\000\000\060\242\034\000"},
+	 "\000\020\001\000\000\000\000\000\000\000\000\000\060\042\071\000"},
 	{296, "shift_expr", 0, 2, states_40,
-	 "\000\020\001\000\000\000\000\000\000\000\000\000\060\242\034\000"},
+	 "\000\020\001\000\000\000\000\000\000\000\000\000\060\042\071\000"},
 	{297, "arith_expr", 0, 2, states_41,
-	 "\000\020\001\000\000\000\000\000\000\000\000\000\060\242\034\000"},
+	 "\000\020\001\000\000\000\000\000\000\000\000\000\060\042\071\000"},
 	{298, "term", 0, 2, states_42,
-	 "\000\020\001\000\000\000\000\000\000\000\000\000\060\242\034\000"},
+	 "\000\020\001\000\000\000\000\000\000\000\000\000\060\042\071\000"},
 	{299, "factor", 0, 3, states_43,
-	 "\000\020\001\000\000\000\000\000\000\000\000\000\060\242\034\000"},
+	 "\000\020\001\000\000\000\000\000\000\000\000\000\060\042\071\000"},
 	{300, "power", 0, 4, states_44,
-	 "\000\020\001\000\000\000\000\000\000\000\000\000\000\240\034\000"},
-	{301, "atom", 0, 11, states_45,
-	 "\000\020\001\000\000\000\000\000\000\000\000\000\000\240\034\000"},
+	 "\000\020\001\000\000\000\000\000\000\000\000\000\000\040\071\000"},
+	{301, "atom", 0, 12, states_45,
+	 "\000\020\001\000\000\000\000\000\000\000\000\000\000\040\071\000"},
 	{302, "lambdef", 0, 5, states_46,
-	 "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\040\000"},
+	 "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\100\000"},
 	{303, "trailer", 0, 7, states_47,
 	 "\000\000\001\000\000\000\020\000\000\000\000\000\000\040\000\000"},
 	{304, "subscriptlist", 0, 3, states_48,
-	 "\000\120\001\000\000\000\020\000\000\200\000\000\060\242\074\000"},
+	 "\000\120\001\000\000\000\020\000\000\200\000\000\060\042\171\000"},
 	{305, "subscript", 0, 7, states_49,
-	 "\000\120\001\000\000\000\020\000\000\200\000\000\060\242\074\000"},
+	 "\000\120\001\000\000\000\020\000\000\200\000\000\060\042\171\000"},
 	{306, "sliceop", 0, 3, states_50,
 	 "\000\100\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
 	{307, "exprlist", 0, 3, states_51,
-	 "\000\020\001\000\000\000\000\000\000\000\000\000\060\242\034\000"},
+	 "\000\020\001\000\000\000\000\000\000\000\000\000\060\042\071\000"},
 	{308, "testlist", 0, 3, states_52,
-	 "\000\020\001\000\000\000\000\000\000\200\000\000\060\242\074\000"},
+	 "\000\020\001\000\000\000\000\000\000\200\000\000\060\042\171\000"},
 	{309, "dictmaker", 0, 5, states_53,
-	 "\000\020\001\000\000\000\000\000\000\200\000\000\060\242\074\000"},
+	 "\000\020\001\000\000\000\000\000\000\200\000\000\060\042\171\000"},
 	{310, "classdef", 0, 8, states_54,
-	 "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004"},
+	 "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\010"},
 	{311, "arglist", 0, 8, states_55,
-	 "\000\020\201\001\000\000\000\000\000\200\000\000\060\242\074\000"},
+	 "\000\020\201\001\000\000\000\000\000\200\000\000\060\042\171\000"},
 	{312, "argument", 0, 4, states_56,
-	 "\000\020\001\000\000\000\000\000\000\200\000\000\060\242\074\000"},
+	 "\000\020\001\000\000\000\000\000\000\200\000\000\060\042\171\000"},
+	{313, "list_iter", 0, 2, states_57,
+	 "\000\000\000\000\000\000\000\200\010\000\000\000\000\000\000\000"},
+	{314, "list_for", 0, 6, states_58,
+	 "\000\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000"},
+	{315, "list_if", 0, 4, states_59,
+	 "\000\000\000\000\000\000\000\200\000\000\000\000\000\000\000\000"},
 };
-static label labels[124] = {
+static label labels[127] = {
 	{0, "EMPTY"},
 	{256, 0},
 	{4, 0},
@@ -1450,6 +1518,7 @@
 	{301, 0},
 	{303, 0},
 	{9, 0},
+	{313, 0},
 	{10, 0},
 	{26, 0},
 	{309, 0},
@@ -1464,10 +1533,12 @@
 	{306, 0},
 	{1, "class"},
 	{312, 0},
+	{314, 0},
+	{315, 0},
 };
 grammar _PyParser_Grammar = {
-	57,
+	60,
 	dfas,
-	{124, labels},
+	{127, labels},
 	256
 };