[Python-Dev] list comprehensions again...

Skip Montanaro skip@mojam.com (Skip Montanaro)
Sat, 8 Jul 2000 05:32:40 -0500 (CDT)


--w4MOZK6GnZ
Content-Type: text/plain; charset=us-ascii
Content-Description: message body text
Content-Transfer-Encoding: 7bit


Regarding list comprehensions I recently proposed this as a possible option:

    >> * bundle up another patch for people to examine and comment on

to which Fredrik replied

    /F> I'd vote for [that]

Since Fredrik's voice is the only one I heard, and on the off-chance that
the CNRI/BeOpen discussions and resulting 1.6 release push things out a bit
(allowing a feature thaw) I'll oblige.

The attached patch to add list comprehensions affects the following files:

    Doc/ref/ref5.tex
    Doc/tut/tut.tex
    Grammar/Grammar
    Include/graminit.h
    Lib/test/test_grammar.py
    Lib/test/output/test_grammar
    Python/compile.c
    Python/graminit.c

About half the patch is the change to the (generated) graminit.c.  The rest
is actually fairly simple.

i-really-hate-seeing-those-M's-when-i-cvs-update-ly y'rs,

Skip

--w4MOZK6GnZ
Content-Type: text/plain
Content-Description: list comprehensions patch for Python
Content-Disposition: inline;
	filename="listcomp.patch"
Content-Transfer-Encoding: 7bit

Index: Doc/ref/ref5.tex
===================================================================
RCS file: /cvsroot/python/python/dist/src/Doc/ref/ref5.tex,v
retrieving revision 1.29
diff -c -r1.29 ref5.tex
*** Doc/ref/ref5.tex	2000/04/25 21:09:10	1.29
--- Doc/ref/ref5.tex	2000/07/08 11:55:44
***************
*** 152,164 ****
  square brackets:
  
  \begin{verbatim}
! list_display:   "[" [expression_list] "]"
  \end{verbatim}
  
  A list display yields a new list object.  If it has no expression
  list, the list object has no items.  Otherwise, the elements of the
  expression list are evaluated from left to right and inserted in the
! list object in that order.
  \obindex{list}
  \indexii{empty}{list}
  
--- 152,169 ----
  square brackets:
  
  \begin{verbatim}
! list_display:   "[" [expression_list [list_iter]] "]"
! list_iter:   list_for | list_if
! list_for:    "for" expression_list "in" testlist [list_iter]
! list_if:     "if" test [list_iter]
  \end{verbatim}
  
  A list display yields a new list object.  If it has no expression
  list, the list object has no items.  Otherwise, the elements of the
  expression list are evaluated from left to right and inserted in the
! list object in that order. List comprehensions define conditional
! expressions used to define lists.
! 
  \obindex{list}
  \indexii{empty}{list}
  
Index: Doc/tut/tut.tex
===================================================================
RCS file: /cvsroot/python/python/dist/src/Doc/tut/tut.tex,v
retrieving revision 1.109
diff -c -r1.109 tut.tex
*** Doc/tut/tut.tex	2000/07/08 05:18:54	1.109
--- Doc/tut/tut.tex	2000/07/08 11:55:45
***************
*** 1753,1758 ****
--- 1753,1779 ----
  0
  \end{verbatim}
  
+ \subsection{List Comprehensions}
+ 
+ List comprehensions provide a concise way to create lists without resorting
+ to use of the \func{map()} or \func{filter()} functions.  The resulting
+ construct tends often to be clearer than use of those functions.
+ 
+ \begin{verbatim}
+ >>> spcs = ["  Apple", " Banana ", "Coco  nut  "]
+ >>> print [s.strip() for s in spcs]
+ ['Apple', 'Banana', 'Coco  nut']
+ >>> vec = [2, 4, 6]
+ >>> print [3*x for x in vec]
+ [6, 12, 18]
+ >>> vec1 = [2, 4, 6]
+ >>> vec2 = [4, 3, -9]
+ >>> print [x*y for x in vec1 for y in vec2]
+ [8, 6, -18, 16, 12, -36, 24, 18, -54]
+ >>> print [x+y for x in vec1 for y in vec2]
+ [6, 5, -7, 8, 7, -5, 10, 9, -3]
+ \end{verbatim}
+ 
  \section{The \keyword{del} statement \label{del}}
  
  There is a way to remove an item from a list given its index instead
Index: Grammar/Grammar
===================================================================
RCS file: /cvsroot/python/python/dist/src/Grammar/Grammar,v
retrieving revision 1.35
diff -c -r1.35 Grammar
*** Grammar/Grammar	2000/03/28 23:49:00	1.35
--- Grammar/Grammar	2000/07/08 11:55:45
***************
*** 74,80 ****
  term: factor (('*'|'/'|'%') factor)*
  factor: ('+'|'-'|'~') factor | power
  power: atom trailer* ('**' factor)*
! atom: '(' [testlist] ')' | '[' [testlist] ']' | '{' [dictmaker] '}' | '`' testlist '`' | NAME | NUMBER | STRING+
  lambdef: 'lambda' [varargslist] ':' test
  trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME
  subscriptlist: subscript (',' subscript)* [',']
--- 74,80 ----
  term: factor (('*'|'/'|'%') factor)*
  factor: ('+'|'-'|'~') factor | power
  power: atom trailer* ('**' factor)*
! atom: '(' [testlist] ')' | '[' [testlist [list_iter]] ']' | '{' [dictmaker] '}' | '`' testlist '`' | NAME | NUMBER | STRING+
  lambdef: 'lambda' [varargslist] ':' test
  trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME
  subscriptlist: subscript (',' subscript)* [',']
***************
*** 88,90 ****
--- 88,96 ----
  
  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 -c -r2.13 graminit.h
*** Include/graminit.h	1997/04/02 05:23:10	2.13
--- Include/graminit.h	2000/07/08 11:55:45
***************
*** 55,57 ****
--- 55,60 ----
  #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 -c -r1.13 test_grammar.py
*** Lib/test/test_grammar.py	2000/03/28 23:51:13	1.13
--- Lib/test/test_grammar.py	2000/07/08 11:55:45
***************
*** 542,544 ****
--- 542,579 ----
  	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 -c -r1.3 test_grammar
*** Lib/test/output/test_grammar	2000/03/28 23:53:22	1.3
--- Lib/test/output/test_grammar	2000/07/08 11:55:45
***************
*** 45,47 ****
--- 45,53 ----
  
  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.113
diff -c -r2.113 compile.c
*** Python/compile.c	2000/07/03 21:39:47	2.113
--- Python/compile.c	2000/07/08 11:55:45
***************
*** 311,316 ****
--- 311,317 ----
  #ifdef PRIVATE_NAME_MANGLING
  	char *c_private;	/* for private name mangling */
  #endif
+ 	int c_tmpname;		/* temp local name counter */ /*LISTCOMP*/
  };
  
  
***************
*** 394,399 ****
--- 395,410 ----
  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 *));
***************
*** 445,450 ****
--- 456,462 ----
  	c->c_last_addr = 0;
  	c->c_last_line = 0;
  	c-> c_lnotab_next = 0;
+ 	c->c_tmpname = 0;
  	return 1;
  	
    fail:
***************
*** 1011,1016 ****
--- 1023,1143 ----
  	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;
***************
*** 1023,1029 ****
  	/* 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_addoparg(c, BUILD_LIST, len);
  	com_pop(c, len-1);
  }
--- 1150,1156 ----
  	/* 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_addoparg(c, BUILD_LIST, len);
  	com_pop(c, len-1);
  }
***************
*** 1072,1079 ****
  			com_addoparg(c, BUILD_LIST, 0);
  			com_push(c, 1);
  		}
! 		else
  			com_list_constructor(c, CHILD(n, 1));
  		break;
  	case LBRACE: /* '{' [dictmaker] '}' */
  		com_addoparg(c, BUILD_MAP, 0);
--- 1199,1208 ----
  			com_addoparg(c, BUILD_LIST, 0);
  			com_push(c, 1);
  		}
! 		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 -c -r2.23 graminit.c
*** Python/graminit.c	2000/03/28 23:49:17	2.23
--- Python/graminit.c	2000/07/08 11:55:45
***************
*** 896,906 ****
  static arc arcs_45_0[7] = {
  	{16, 1},
  	{109, 2},
! 	{111, 3},
! 	{114, 4},
  	{12, 5},
! 	{115, 5},
! 	{116, 6},
  };
  static arc arcs_45_1[2] = {
  	{9, 7},
--- 896,906 ----
  static arc arcs_45_0[7] = {
  	{16, 1},
  	{109, 2},
! 	{112, 3},
! 	{115, 4},
  	{12, 5},
! 	{116, 5},
! 	{117, 6},
  };
  static arc arcs_45_1[2] = {
  	{9, 7},
***************
*** 908,918 ****
  };
  static arc arcs_45_2[2] = {
  	{9, 8},
! 	{110, 5},
  };
  static arc arcs_45_3[2] = {
! 	{112, 9},
! 	{113, 5},
  };
  static arc arcs_45_4[1] = {
  	{9, 10},
--- 908,918 ----
  };
  static arc arcs_45_2[2] = {
  	{9, 8},
! 	{111, 5},
  };
  static arc arcs_45_3[2] = {
! 	{113, 9},
! 	{114, 5},
  };
  static arc arcs_45_4[1] = {
  	{9, 10},
***************
*** 921,942 ****
  	{0, 5},
  };
  static arc arcs_45_6[2] = {
! 	{116, 6},
  	{0, 6},
  };
  static arc arcs_45_7[1] = {
  	{18, 5},
  };
! static arc arcs_45_8[1] = {
! 	{110, 5},
  };
  static arc arcs_45_9[1] = {
! 	{113, 5},
  };
  static arc arcs_45_10[1] = {
! 	{114, 5},
  };
! static state states_45[11] = {
  	{7, arcs_45_0},
  	{2, arcs_45_1},
  	{2, arcs_45_2},
--- 921,946 ----
  	{0, 5},
  };
  static arc arcs_45_6[2] = {
! 	{117, 6},
  	{0, 6},
  };
  static arc arcs_45_7[1] = {
  	{18, 5},
  };
! static arc arcs_45_8[2] = {
! 	{110, 11},
! 	{111, 5},
  };
  static arc arcs_45_9[1] = {
! 	{114, 5},
  };
  static arc arcs_45_10[1] = {
! 	{115, 5},
  };
! 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,956 ****
  	{1, arcs_45_5},
  	{2, arcs_45_6},
  	{1, arcs_45_7},
! 	{1, arcs_45_8},
  	{1, arcs_45_9},
  	{1, arcs_45_10},
  };
  static arc arcs_46_0[1] = {
! 	{117, 1},
  };
  static arc arcs_46_1[2] = {
  	{17, 2},
--- 949,961 ----
  	{1, arcs_45_5},
  	{2, arcs_45_6},
  	{1, arcs_45_7},
! 	{2, arcs_45_8},
  	{1, arcs_45_9},
  	{1, arcs_45_10},
+ 	{1, arcs_45_11},
  };
  static arc arcs_46_0[1] = {
! 	{118, 1},
  };
  static arc arcs_46_1[2] = {
  	{17, 2},
***************
*** 978,988 ****
  	{52, 3},
  };
  static arc arcs_47_1[2] = {
! 	{118, 4},
  	{18, 5},
  };
  static arc arcs_47_2[1] = {
! 	{119, 6},
  };
  static arc arcs_47_3[1] = {
  	{12, 5},
--- 983,993 ----
  	{52, 3},
  };
  static arc arcs_47_1[2] = {
! 	{119, 4},
  	{18, 5},
  };
  static arc arcs_47_2[1] = {
! 	{120, 6},
  };
  static arc arcs_47_3[1] = {
  	{12, 5},
***************
*** 994,1000 ****
  	{0, 5},
  };
  static arc arcs_47_6[1] = {
! 	{110, 5},
  };
  static state states_47[7] = {
  	{3, arcs_47_0},
--- 999,1005 ----
  	{0, 5},
  };
  static arc arcs_47_6[1] = {
! 	{111, 5},
  };
  static state states_47[7] = {
  	{3, arcs_47_0},
***************
*** 1006,1019 ****
  	{1, arcs_47_6},
  };
  static arc arcs_48_0[1] = {
! 	{120, 1},
  };
  static arc arcs_48_1[2] = {
  	{22, 2},
  	{0, 1},
  };
  static arc arcs_48_2[2] = {
! 	{120, 1},
  	{0, 2},
  };
  static state states_48[3] = {
--- 1011,1024 ----
  	{1, arcs_47_6},
  };
  static arc arcs_48_0[1] = {
! 	{121, 1},
  };
  static arc arcs_48_1[2] = {
  	{22, 2},
  	{0, 1},
  };
  static arc arcs_48_2[2] = {
! 	{121, 1},
  	{0, 2},
  };
  static state states_48[3] = {
***************
*** 1035,1048 ****
  };
  static arc arcs_49_3[3] = {
  	{21, 5},
! 	{121, 6},
  	{0, 3},
  };
  static arc arcs_49_4[1] = {
  	{52, 6},
  };
  static arc arcs_49_5[2] = {
! 	{121, 6},
  	{0, 5},
  };
  static arc arcs_49_6[1] = {
--- 1040,1053 ----
  };
  static arc arcs_49_3[3] = {
  	{21, 5},
! 	{122, 6},
  	{0, 3},
  };
  static arc arcs_49_4[1] = {
  	{52, 6},
  };
  static arc arcs_49_5[2] = {
! 	{122, 6},
  	{0, 5},
  };
  static arc arcs_49_6[1] = {
***************
*** 1129,1135 ****
  	{2, arcs_53_4},
  };
  static arc arcs_54_0[1] = {
! 	{122, 1},
  };
  static arc arcs_54_1[1] = {
  	{12, 2},
--- 1134,1140 ----
  	{2, arcs_53_4},
  };
  static arc arcs_54_0[1] = {
! 	{123, 1},
  };
  static arc arcs_54_1[1] = {
  	{12, 2},
***************
*** 1164,1170 ****
  	{1, arcs_54_7},
  };
  static arc arcs_55_0[3] = {
! 	{123, 1},
  	{23, 2},
  	{24, 3},
  };
--- 1169,1175 ----
  	{1, arcs_54_7},
  };
  static arc arcs_55_0[3] = {
! 	{124, 1},
  	{23, 2},
  	{24, 3},
  };
***************
*** 1179,1185 ****
  	{21, 6},
  };
  static arc arcs_55_4[4] = {
! 	{123, 1},
  	{23, 2},
  	{24, 3},
  	{0, 4},
--- 1184,1190 ----
  	{21, 6},
  };
  static arc arcs_55_4[4] = {
! 	{124, 1},
  	{23, 2},
  	{24, 3},
  	{0, 4},
***************
*** 1222,1235 ****
  	{2, arcs_56_1},
  	{1, arcs_56_2},
  	{1, arcs_56_3},
  };
! static dfa dfas[57] = {
  	{256, "single_input", 0, 3, states_0,
! 	 "\004\030\001\000\140\341\153\202\034\200\000\000\060\242\074\004"},
  	{257, "file_input", 0, 2, states_1,
! 	 "\204\030\001\000\140\341\153\202\034\200\000\000\060\242\074\004"},
  	{258, "eval_input", 0, 3, states_2,
! 	 "\000\020\001\000\000\000\000\000\000\200\000\000\060\242\074\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,
--- 1227,1297 ----
  	{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 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\042\171\010"},
  	{257, "file_input", 0, 2, states_1,
! 	 "\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\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,1253 ****
  	{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"},
  	{265, "simple_stmt", 0, 4, states_9,
! 	 "\000\020\001\000\140\341\153\002\000\200\000\000\060\242\074\000"},
  	{266, "small_stmt", 0, 2, states_10,
! 	 "\000\020\001\000\140\341\153\002\000\200\000\000\060\242\074\000"},
  	{267, "expr_stmt", 0, 2, states_11,
! 	 "\000\020\001\000\000\000\000\000\000\200\000\000\060\242\074\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,
--- 1303,1315 ----
  	{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\042\171\010"},
  	{265, "simple_stmt", 0, 4, states_9,
! 	 "\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\042\171\000"},
  	{267, "expr_stmt", 0, 2, states_11,
! 	 "\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,1281 ****
  	{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"},
  	{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,
--- 1337,1343 ----
  	{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\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,1345 ****
  	{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"},
  	{288, "test", 0, 4, states_32,
! 	 "\000\020\001\000\000\000\000\000\000\200\000\000\060\242\074\000"},
  	{289, "and_test", 0, 2, states_33,
! 	 "\000\020\001\000\000\000\000\000\000\200\000\000\060\242\034\000"},
  	{290, "not_test", 0, 3, states_34,
! 	 "\000\020\001\000\000\000\000\000\000\200\000\000\060\242\034\000"},
  	{291, "comparison", 0, 2, states_35,
! 	 "\000\020\001\000\000\000\000\000\000\000\000\000\060\242\034\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"},
  	{294, "xor_expr", 0, 2, states_38,
! 	 "\000\020\001\000\000\000\000\000\000\000\000\000\060\242\034\000"},
  	{295, "and_expr", 0, 2, states_39,
! 	 "\000\020\001\000\000\000\000\000\000\000\000\000\060\242\034\000"},
  	{296, "shift_expr", 0, 2, states_40,
! 	 "\000\020\001\000\000\000\000\000\000\000\000\000\060\242\034\000"},
  	{297, "arith_expr", 0, 2, states_41,
! 	 "\000\020\001\000\000\000\000\000\000\000\000\000\060\242\034\000"},
  	{298, "term", 0, 2, states_42,
! 	 "\000\020\001\000\000\000\000\000\000\000\000\000\060\242\034\000"},
  	{299, "factor", 0, 3, states_43,
! 	 "\000\020\001\000\000\000\000\000\000\000\000\000\060\242\034\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"},
  	{302, "lambdef", 0, 5, states_46,
! 	 "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\040\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"},
  	{305, "subscript", 0, 7, states_49,
! 	 "\000\120\001\000\000\000\020\000\000\200\000\000\060\242\074\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"},
  	{308, "testlist", 0, 3, states_52,
! 	 "\000\020\001\000\000\000\000\000\000\200\000\000\060\242\074\000"},
  	{309, "dictmaker", 0, 5, states_53,
! 	 "\000\020\001\000\000\000\000\000\000\200\000\000\060\242\074\000"},
  	{310, "classdef", 0, 8, states_54,
! 	 "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004"},
  	{311, "arglist", 0, 8, states_55,
! 	 "\000\020\201\001\000\000\000\000\000\200\000\000\060\242\074\000"},
  	{312, "argument", 0, 4, states_56,
! 	 "\000\020\001\000\000\000\000\000\000\200\000\000\060\242\074\000"},
  };
! static label labels[124] = {
  	{0, "EMPTY"},
  	{256, 0},
  	{4, 0},
--- 1349,1413 ----
  	{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\042\171\000"},
  	{288, "test", 0, 4, states_32,
! 	 "\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\042\071\000"},
  	{290, "not_test", 0, 3, states_34,
! 	 "\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\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\042\071\000"},
  	{294, "xor_expr", 0, 2, states_38,
! 	 "\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\042\071\000"},
  	{296, "shift_expr", 0, 2, states_40,
! 	 "\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\042\071\000"},
  	{298, "term", 0, 2, states_42,
! 	 "\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\042\071\000"},
  	{300, "power", 0, 4, states_44,
! 	 "\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\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\042\171\000"},
  	{305, "subscript", 0, 7, states_49,
! 	 "\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\042\071\000"},
  	{308, "testlist", 0, 3, states_52,
! 	 "\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\042\171\000"},
  	{310, "classdef", 0, 8, states_54,
! 	 "\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\042\171\000"},
  	{312, "argument", 0, 4, states_56,
! 	 "\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[127] = {
  	{0, "EMPTY"},
  	{256, 0},
  	{4, 0},
***************
*** 1450,1455 ****
--- 1518,1524 ----
  	{301, 0},
  	{303, 0},
  	{9, 0},
+ 	{313, 0},
  	{10, 0},
  	{26, 0},
  	{309, 0},
***************
*** 1464,1473 ****
  	{306, 0},
  	{1, "class"},
  	{312, 0},
  };
  grammar _PyParser_Grammar = {
! 	57,
  	dfas,
! 	{124, labels},
  	256
  };
--- 1533,1544 ----
  	{306, 0},
  	{1, "class"},
  	{312, 0},
+ 	{314, 0},
+ 	{315, 0},
  };
  grammar _PyParser_Grammar = {
! 	60,
  	dfas,
! 	{127, labels},
  	256
  };

--w4MOZK6GnZ--