summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPhillip J. Eby <pje@telecommunity.com>2005-08-02 00:46:46 (GMT)
committerPhillip J. Eby <pje@telecommunity.com>2005-08-02 00:46:46 (GMT)
commit0d6615fd29063bdaccb13e1fbae542fb666d8728 (patch)
tree0f18d41e2cb8831c9d244ab6586f9f8377592c67
parentd794666048510deca0d4987a4c74d0fca85be411 (diff)
downloadcpython-0d6615fd29063bdaccb13e1fbae542fb666d8728.zip
cpython-0d6615fd29063bdaccb13e1fbae542fb666d8728.tar.gz
cpython-0d6615fd29063bdaccb13e1fbae542fb666d8728.tar.bz2
PEP 342 implementation. Per Guido's comments, the generator throw()
method still needs to support string exceptions, and allow None for the third argument. Documentation updates are needed, too.
-rw-r--r--Grammar/Grammar9
-rw-r--r--Include/ceval.h1
-rw-r--r--Include/graminit.h1
-rw-r--r--Include/pyerrors.h1
-rw-r--r--Lib/compiler/transformer.py12
-rwxr-xr-xLib/symbol.py1
-rw-r--r--Lib/test/test_generators.py276
-rw-r--r--Lib/test/test_genexps.py2
-rw-r--r--Lib/test/test_parser.py11
-rw-r--r--Modules/gcmodule.c4
-rw-r--r--Modules/parsermodule.c55
-rw-r--r--Objects/genobject.c239
-rw-r--r--Python/ceval.c18
-rw-r--r--Python/compile.c76
-rw-r--r--Python/exceptions.c5
-rw-r--r--Python/graminit.c239
16 files changed, 785 insertions, 165 deletions
diff --git a/Grammar/Grammar b/Grammar/Grammar
index 7b6acf7..01e4afd 100644
--- a/Grammar/Grammar
+++ b/Grammar/Grammar
@@ -39,7 +39,7 @@ fplist: fpdef (',' fpdef)* [',']
stmt: simple_stmt | compound_stmt
simple_stmt: small_stmt (';' small_stmt)* [';'] NEWLINE
small_stmt: expr_stmt | print_stmt | del_stmt | pass_stmt | flow_stmt | import_stmt | global_stmt | exec_stmt | assert_stmt
-expr_stmt: testlist (augassign testlist | ('=' testlist)*)
+expr_stmt: testlist (augassign (yield_expr|testlist) | ('=' (yield_expr|testlist))*)
augassign: '+=' | '-=' | '*=' | '/=' | '%=' | '&=' | '|=' | '^=' | '<<=' | '>>=' | '**=' | '//='
# For normal assignments, additional restrictions enforced by the interpreter
print_stmt: 'print' ( [ test (',' test)* [','] ] | '>>' test [ (',' test)+ [','] ] )
@@ -49,7 +49,7 @@ flow_stmt: break_stmt | continue_stmt | return_stmt | raise_stmt | yield_stmt
break_stmt: 'break'
continue_stmt: 'continue'
return_stmt: 'return' [testlist]
-yield_stmt: 'yield' testlist
+yield_stmt: yield_expr
raise_stmt: 'raise' [test [',' test [',' test]]]
import_stmt: import_name | import_from
import_name: 'import' dotted_as_names
@@ -86,7 +86,7 @@ arith_expr: term (('+'|'-') term)*
term: factor (('*'|'/'|'%'|'//') factor)*
factor: ('+'|'-'|'~') factor | power
power: atom trailer* ['**' factor]
-atom: '(' [testlist_gexp] ')' | '[' [listmaker] ']' | '{' [dictmaker] '}' | '`' testlist1 '`' | NAME | NUMBER | STRING+
+atom: '(' [yield_expr|testlist_gexp] ')' | '[' [listmaker] ']' | '{' [dictmaker] '}' | '`' testlist1 '`' | NAME | NUMBER | STRING+
listmaker: test ( list_for | (',' test)* [','] )
testlist_gexp: test ( gen_for | (',' test)* [','] )
lambdef: 'lambda' [varargslist] ':' test
@@ -116,3 +116,6 @@ testlist1: test (',' test)*
# not used in grammar, but may appear in "node" passed from Parser to Compiler
encoding_decl: NAME
+
+yield_expr: 'yield' [testlist]
+
diff --git a/Include/ceval.h b/Include/ceval.h
index d9320e0..9481506 100644
--- a/Include/ceval.h
+++ b/Include/ceval.h
@@ -65,6 +65,7 @@ PyAPI_FUNC(char *) PyEval_GetFuncDesc(PyObject *);
PyAPI_FUNC(PyObject *) PyEval_GetCallStats(PyObject *);
PyAPI_FUNC(PyObject *) PyEval_EvalFrame(struct _frame *);
+PyAPI_FUNC(PyObject *) PyEval_EvalFrameEx(struct _frame *f, int exc);
/* this used to be handled on a per-thread basis - now just two globals */
PyAPI_DATA(volatile int) _Py_Ticker;
diff --git a/Include/graminit.h b/Include/graminit.h
index a46cdc9..2c855ea 100644
--- a/Include/graminit.h
+++ b/Include/graminit.h
@@ -76,3 +76,4 @@
#define gen_if 331
#define testlist1 332
#define encoding_decl 333
+#define yield_expr 334
diff --git a/Include/pyerrors.h b/Include/pyerrors.h
index f433cc0..f18e579 100644
--- a/Include/pyerrors.h
+++ b/Include/pyerrors.h
@@ -25,6 +25,7 @@ PyAPI_FUNC(void) PyErr_NormalizeException(PyObject**, PyObject**, PyObject**);
PyAPI_DATA(PyObject *) PyExc_Exception;
PyAPI_DATA(PyObject *) PyExc_StopIteration;
+PyAPI_DATA(PyObject *) PyExc_GeneratorExit;
PyAPI_DATA(PyObject *) PyExc_StandardError;
PyAPI_DATA(PyObject *) PyExc_ArithmeticError;
PyAPI_DATA(PyObject *) PyExc_LookupError;
diff --git a/Lib/compiler/transformer.py b/Lib/compiler/transformer.py
index 5844bb5..4759280 100644
--- a/Lib/compiler/transformer.py
+++ b/Lib/compiler/transformer.py
@@ -403,7 +403,15 @@ class Transformer:
return Return(self.com_node(nodelist[1]), lineno=nodelist[0][2])
def yield_stmt(self, nodelist):
- return Yield(self.com_node(nodelist[1]), lineno=nodelist[0][2])
+ expr = self.com_node(nodelist[0])
+ return Discard(expr, lineno=expr.lineno)
+
+ def yield_expr(self, nodelist):
+ if len(nodelist)>1:
+ value = nodelist[1]
+ else:
+ value = Const(None)
+ return Yield(self.com_node(value), lineno=nodelist[0][2])
def raise_stmt(self, nodelist):
# raise: [test [',' test [',' test]]]
@@ -1402,6 +1410,8 @@ _legal_node_types = [
if hasattr(symbol, 'yield_stmt'):
_legal_node_types.append(symbol.yield_stmt)
+if hasattr(symbol, 'yield_expr'):
+ _legal_node_types.append(symbol.yield_expr)
_assign_types = [
symbol.test,
diff --git a/Lib/symbol.py b/Lib/symbol.py
index eaf5a25..8219008 100755
--- a/Lib/symbol.py
+++ b/Lib/symbol.py
@@ -88,6 +88,7 @@ gen_for = 330
gen_if = 331
testlist1 = 332
encoding_decl = 333
+yield_expr = 334
#--end constants--
sym_name = {}
diff --git a/Lib/test/test_generators.py b/Lib/test/test_generators.py
index 109af73..97cdd2a 100644
--- a/Lib/test/test_generators.py
+++ b/Lib/test/test_generators.py
@@ -382,7 +382,7 @@ From the Iterators list, about the types of these things.
>>> type(i)
<type 'generator'>
>>> [s for s in dir(i) if not s.startswith('_')]
-['gi_frame', 'gi_running', 'next']
+['close', 'gi_frame', 'gi_running', 'next', 'send', 'throw']
>>> print i.next.__doc__
x.next() -> the next value, or raise StopIteration
>>> iter(i) is i
@@ -421,6 +421,7 @@ Subject: Re: PEP 255: Simple Generators
... self.name = name
... self.parent = None
... self.generator = self.generate()
+... self.close = self.generator.close
...
... def generate(self):
... while not self.parent:
@@ -482,6 +483,9 @@ merged F into A
A->A B->G C->A D->G E->G F->A G->G H->G I->A J->G K->A L->A M->G
merged A into G
A->G B->G C->G D->G E->G F->G G->G H->G I->G J->G K->G L->G M->G
+
+>>> for s in sets: s.close() # break cycles
+
"""
# Emacs turd '
@@ -589,6 +593,7 @@ arguments are iterable -- a LazyList is the same as a generator to times().
... def __init__(self, g):
... self.sofar = []
... self.fetch = g.next
+... self.close = g.close
...
... def __getitem__(self, i):
... sofar, fetch = self.sofar, self.fetch
@@ -619,6 +624,7 @@ efficient.
[200, 216, 225, 240, 243, 250, 256, 270, 288, 300, 320, 324, 360, 375, 384]
[400, 405, 432, 450, 480, 486, 500, 512, 540, 576, 600, 625, 640, 648, 675]
+>>> m235.close()
Ye olde Fibonacci generator, LazyList style.
@@ -642,6 +648,7 @@ Ye olde Fibonacci generator, LazyList style.
>>> fib = LazyList(fibgen(1, 2))
>>> firstn(iter(fib), 17)
[1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584]
+>>> fib.close()
"""
# syntax_tests mostly provokes SyntaxErrors. Also fiddling with #if 0
@@ -672,7 +679,7 @@ Traceback (most recent call last):
..
SyntaxError: 'return' with argument inside generator (<doctest test.test_generators.__test__.syntax[2]>, line 3)
-This one is fine:
+These are fine:
>>> def f():
... yield 1
@@ -683,9 +690,6 @@ This one is fine:
... yield 1
... finally:
... pass
-Traceback (most recent call last):
- ..
-SyntaxError: 'yield' not allowed in a 'try' block with a 'finally' clause (<doctest test.test_generators.__test__.syntax[4]>, line 3)
>>> def f():
... try:
@@ -697,11 +701,6 @@ SyntaxError: 'yield' not allowed in a 'try' block with a 'finally' clause (<doct
... pass
... finally:
... pass
-Traceback (most recent call last):
- ...
-SyntaxError: 'yield' not allowed in a 'try' block with a 'finally' clause (<doctest test.test_generators.__test__.syntax[5]>, line 6)
-
-But this is fine:
>>> def f():
... try:
@@ -722,14 +721,16 @@ But this is fine:
>>> def f():
... yield
-Traceback (most recent call last):
-SyntaxError: invalid syntax
+>>> type(f())
+<type 'generator'>
+
>>> def f():
... if 0:
... yield
-Traceback (most recent call last):
-SyntaxError: invalid syntax
+>>> type(f())
+<type 'generator'>
+
>>> def f():
... if 0:
@@ -805,7 +806,7 @@ SyntaxError: invalid syntax
... if 0:
... yield 2 # because it's a generator
Traceback (most recent call last):
-SyntaxError: 'return' with argument inside generator (<doctest test.test_generators.__test__.syntax[22]>, line 8)
+SyntaxError: 'return' with argument inside generator (<doctest test.test_generators.__test__.syntax[24]>, line 8)
This one caused a crash (see SF bug 567538):
@@ -1383,6 +1384,250 @@ True
"""
+coroutine_tests = """\
+Sending a value into a started generator:
+
+>>> def f():
+... print (yield 1)
+... yield 2
+>>> g = f()
+>>> g.next()
+1
+>>> g.send(42)
+42
+2
+
+Sending a value into a new generator produces a TypeError:
+
+>>> f().send("foo")
+Traceback (most recent call last):
+...
+TypeError: can't send non-None value to a just-started generator
+
+
+Yield by itself yields None:
+
+>>> def f(): yield
+>>> list(f())
+[None]
+
+
+
+An obscene abuse of a yield expression within a generator expression:
+
+>>> list((yield 21) for i in range(4))
+[21, None, 21, None, 21, None, 21, None]
+
+And a more sane, but still weird usage:
+
+>>> def f(): list(i for i in [(yield 26)])
+>>> type(f())
+<type 'generator'>
+
+
+Check some syntax errors for yield expressions:
+
+>>> f=lambda: (yield 1),(yield 2)
+Traceback (most recent call last):
+ ...
+SyntaxError: 'yield' outside function (<doctest test.test_generators.__test__.coroutine[10]>, line 1)
+
+>>> def f(): return lambda x=(yield): 1
+Traceback (most recent call last):
+ ...
+SyntaxError: 'return' with argument inside generator (<doctest test.test_generators.__test__.coroutine[11]>, line 1)
+
+>>> def f(): x = yield = y
+Traceback (most recent call last):
+ ...
+SyntaxError: assignment to yield expression not possible (<doctest test.test_generators.__test__.coroutine[12]>, line 1)
+
+
+Now check some throw() conditions:
+
+>>> def f():
+... while True:
+... try:
+... print (yield)
+... except ValueError,v:
+... print "caught ValueError (%s)" % (v),
+>>> import sys
+>>> g = f()
+>>> g.next()
+
+>>> g.throw(ValueError) # type only
+caught ValueError ()
+
+>>> g.throw(ValueError("xyz")) # value only
+caught ValueError (xyz)
+
+>>> g.throw(ValueError, ValueError(1)) # value+matching type
+caught ValueError (1)
+
+>>> g.throw(ValueError, TypeError(1)) # mismatched type, rewrapped
+caught ValueError (1)
+
+>>> g.throw(ValueError(1), "foo") # bad args
+Traceback (most recent call last):
+ ...
+TypeError: instance exception may not have a separate value
+
+>>> g.throw(ValueError, "foo", 23) # bad args
+Traceback (most recent call last):
+ ...
+TypeError: throw() third argument must be a traceback object
+
+>>> def throw(g,exc):
+... try:
+... raise exc
+... except:
+... g.throw(*sys.exc_info())
+>>> throw(g,ValueError) # do it with traceback included
+caught ValueError ()
+
+>>> g.send(1)
+1
+
+>>> throw(g,TypeError) # terminate the generator
+Traceback (most recent call last):
+ ...
+TypeError
+
+>>> print g.gi_frame
+None
+
+>>> g.send(2)
+Traceback (most recent call last):
+ ...
+StopIteration
+
+>>> g.throw(ValueError,6) # throw on closed generator
+Traceback (most recent call last):
+ ...
+ValueError: 6
+
+>>> f().throw(ValueError,7) # throw on just-opened generator
+Traceback (most recent call last):
+ ...
+ValueError: 7
+
+
+Now let's try closing a generator:
+
+>>> def f():
+... try: yield
+... except GeneratorExit:
+... print "exiting"
+
+>>> g = f()
+>>> g.next()
+>>> g.close()
+exiting
+>>> g.close() # should be no-op now
+
+>>> f().close() # close on just-opened generator should be fine
+
+>>> def f(): yield # an even simpler generator
+>>> f().close() # close before opening
+>>> g = f()
+>>> g.next()
+>>> g.close() # close normally
+
+And finalization:
+
+>>> def f():
+... try: yield
+... finally:
+... print "exiting"
+
+>>> g = f()
+>>> g.next()
+>>> del g
+exiting
+
+
+Now let's try some ill-behaved generators:
+
+>>> def f():
+... try: yield
+... except GeneratorExit:
+... yield "foo!"
+>>> g = f()
+>>> g.next()
+>>> g.close()
+Traceback (most recent call last):
+ ...
+RuntimeError: generator ignored GeneratorExit
+>>> g.close()
+
+
+Our ill-behaved code should be invoked during GC:
+
+>>> import sys, StringIO
+>>> old, sys.stderr = sys.stderr, StringIO.StringIO()
+>>> g = f()
+>>> g.next()
+>>> del g
+>>> sys.stderr.getvalue().startswith(
+... "Exception exceptions.RuntimeError: 'generator ignored GeneratorExit' in "
+... )
+True
+>>> sys.stderr = old
+
+
+And errors thrown during closing should propagate:
+
+>>> def f():
+... try: yield
+... except GeneratorExit:
+... raise TypeError("fie!")
+>>> g = f()
+>>> g.next()
+>>> g.close()
+Traceback (most recent call last):
+ ...
+TypeError: fie!
+
+
+Ensure that various yield expression constructs make their
+enclosing function a generator:
+
+>>> def f(): x += yield
+>>> type(f())
+<type 'generator'>
+
+>>> def f(): x = yield
+>>> type(f())
+<type 'generator'>
+
+>>> def f(): lambda x=(yield): 1
+>>> type(f())
+<type 'generator'>
+
+>>> def f(): x=(i for i in (yield) if (yield))
+>>> type(f())
+<type 'generator'>
+
+>>> def f(d): d[(yield "a")] = d[(yield "b")] = 27
+>>> data = [1,2]
+>>> g = f(data)
+>>> type(g)
+<type 'generator'>
+>>> g.send(None)
+'a'
+>>> data
+[1, 2]
+>>> g.send(0)
+'b'
+>>> data
+[27, 2]
+>>> try: g.send(1)
+... except StopIteration: pass
+>>> data
+[27, 27]
+
+"""
+
__test__ = {"tut": tutorial_tests,
"pep": pep_tests,
"email": email_tests,
@@ -1390,6 +1635,7 @@ __test__ = {"tut": tutorial_tests,
"syntax": syntax_tests,
"conjoin": conjoin_tests,
"weakref": weakref_tests,
+ "coroutine": coroutine_tests,
}
# Magic test name that regrtest.py invokes *after* importing this module.
diff --git a/Lib/test/test_genexps.py b/Lib/test/test_genexps.py
index 04694f8..7c6fe4a 100644
--- a/Lib/test/test_genexps.py
+++ b/Lib/test/test_genexps.py
@@ -130,7 +130,7 @@ Verify that syntax error's are raised for genexps used as lvalues
>>> (y for y in (1,2)) += 10
Traceback (most recent call last):
...
- SyntaxError: augmented assign to tuple literal or generator expression not possible
+ SyntaxError: augmented assign to tuple literal, yield, or generator expression not possible
diff --git a/Lib/test/test_parser.py b/Lib/test/test_parser.py
index 205c406..d1ace67 100644
--- a/Lib/test/test_parser.py
+++ b/Lib/test/test_parser.py
@@ -29,11 +29,22 @@ class RoundtripLegalSyntaxTestCase(unittest.TestCase):
def test_yield_statement(self):
self.check_suite("def f(): yield 1")
+ self.check_suite("def f(): yield")
+ self.check_suite("def f(): x += yield")
+ self.check_suite("def f(): x = yield 1")
+ self.check_suite("def f(): x = y = yield 1")
+ self.check_suite("def f(): x = yield")
+ self.check_suite("def f(): x = y = yield")
+ self.check_suite("def f(): 1 + (yield)*2")
+ self.check_suite("def f(): (yield 1)*2")
self.check_suite("def f(): return; yield 1")
self.check_suite("def f(): yield 1; return")
self.check_suite("def f():\n"
" for x in range(30):\n"
" yield x\n")
+ self.check_suite("def f():\n"
+ " if (yield):\n"
+ " yield x\n")
def test_expressions(self):
self.check_expr("foo(1)")
diff --git a/Modules/gcmodule.c b/Modules/gcmodule.c
index 38494ea..db9dd32 100644
--- a/Modules/gcmodule.c
+++ b/Modules/gcmodule.c
@@ -413,10 +413,8 @@ has_finalizer(PyObject *op)
assert(delstr != NULL);
return _PyInstance_Lookup(op, delstr) != NULL;
}
- else if (PyType_HasFeature(op->ob_type, Py_TPFLAGS_HEAPTYPE))
+ else
return op->ob_type->tp_del != NULL;
- else
- return 0;
}
/* Move the objects in unreachable with __del__ methods into `finalizers`.
diff --git a/Modules/parsermodule.c b/Modules/parsermodule.c
index 63b2cd7..12226a4 100644
--- a/Modules/parsermodule.c
+++ b/Modules/parsermodule.c
@@ -859,7 +859,8 @@ VALIDATER(arglist); VALIDATER(argument);
VALIDATER(listmaker); VALIDATER(yield_stmt);
VALIDATER(testlist1); VALIDATER(gen_for);
VALIDATER(gen_iter); VALIDATER(gen_if);
-VALIDATER(testlist_gexp);
+VALIDATER(testlist_gexp); VALIDATER(yield_expr);
+VALIDATER(yield_or_testlist);
#undef VALIDATER
@@ -1507,6 +1508,15 @@ validate_compound_stmt(node *tree)
static int
+validate_yield_or_testlist(node *tree)
+{
+ if (TYPE(tree) == yield_expr)
+ return validate_yield_expr(tree);
+ else
+ return validate_testlist(tree);
+}
+
+static int
validate_expr_stmt(node *tree)
{
int j;
@@ -1517,8 +1527,8 @@ validate_expr_stmt(node *tree)
if (res && nch == 3
&& TYPE(CHILD(tree, 1)) == augassign) {
- res = (validate_numnodes(CHILD(tree, 1), 1, "augassign")
- && validate_testlist(CHILD(tree, 2)));
+ res = validate_numnodes(CHILD(tree, 1), 1, "augassign")
+ && validate_yield_or_testlist(CHILD(tree, 2));
if (res) {
char *s = STR(CHILD(CHILD(tree, 1), 0));
@@ -1541,8 +1551,8 @@ validate_expr_stmt(node *tree)
}
else {
for (j = 1; res && (j < nch); j += 2)
- res = (validate_equal(CHILD(tree, j))
- && validate_testlist(CHILD(tree, j + 1)));
+ res = validate_equal(CHILD(tree, j))
+ && validate_yield_or_testlist(CHILD(tree, j + 1));
}
return (res);
}
@@ -1649,15 +1659,31 @@ validate_raise_stmt(node *tree)
}
-/* yield_stmt: 'yield' testlist
+/* yield_expr: 'yield' [testlist]
+ */
+static int
+validate_yield_expr(node *tree)
+{
+ int nch = NCH(tree);
+ int res = (validate_ntype(tree, yield_expr)
+ && ((nch == 1) || (nch == 2))
+ && validate_name(CHILD(tree, 0), "yield"));
+
+ if (res && (nch == 2))
+ res = validate_testlist(CHILD(tree, 1));
+
+ return (res);
+}
+
+
+/* yield_stmt: yield_expr
*/
static int
validate_yield_stmt(node *tree)
{
return (validate_ntype(tree, yield_stmt)
- && validate_numnodes(tree, 2, "yield_stmt")
- && validate_name(CHILD(tree, 0), "yield")
- && validate_testlist(CHILD(tree, 1)));
+ && validate_numnodes(tree, 1, "yield_stmt")
+ && validate_yield_expr(CHILD(tree, 0)));
}
@@ -2300,8 +2326,12 @@ validate_atom(node *tree)
res = ((nch <= 3)
&& (validate_rparen(CHILD(tree, nch - 1))));
- if (res && (nch == 3))
- res = validate_testlist_gexp(CHILD(tree, 1));
+ if (res && (nch == 3)) {
+ if (TYPE(CHILD(tree, 1))==yield_expr)
+ res = validate_yield_expr(CHILD(tree, 1));
+ else
+ res = validate_testlist_gexp(CHILD(tree, 1));
+ }
break;
case LSQB:
if (nch == 2)
@@ -2914,6 +2944,9 @@ validate_node(node *tree)
case testlist:
res = validate_testlist(tree);
break;
+ case yield_expr:
+ res = validate_yield_expr(tree);
+ break;
case testlist1:
res = validate_testlist1(tree);
break;
diff --git a/Objects/genobject.c b/Objects/genobject.c
index 174c697..d281274 100644
--- a/Objects/genobject.c
+++ b/Objects/genobject.c
@@ -15,15 +15,31 @@ gen_traverse(PyGenObject *gen, visitproc visit, void *arg)
static void
gen_dealloc(PyGenObject *gen)
{
+ PyObject *self = (PyObject *) gen;
+
_PyObject_GC_UNTRACK(gen);
+
if (gen->gi_weakreflist != NULL)
PyObject_ClearWeakRefs((PyObject *) gen);
- Py_DECREF(gen->gi_frame);
+
+
+ _PyObject_GC_TRACK(self);
+
+ if (gen->gi_frame->f_stacktop!=NULL) {
+ /* Generator is paused, so we need to close */
+ gen->ob_type->tp_del(self);
+ if (self->ob_refcnt > 0)
+ return; /* resurrected. :( */
+ }
+
+ _PyObject_GC_UNTRACK(self);
+ Py_XDECREF(gen->gi_frame);
PyObject_GC_Del(gen);
}
+
static PyObject *
-gen_iternext(PyGenObject *gen)
+gen_send_ex(PyGenObject *gen, PyObject *arg, int exc)
{
PyThreadState *tstate = PyThreadState_GET();
PyFrameObject *f = gen->gi_frame;
@@ -34,8 +50,24 @@ gen_iternext(PyGenObject *gen)
"generator already executing");
return NULL;
}
- if (f->f_stacktop == NULL)
+ if ((PyObject *)f == Py_None || f->f_stacktop == NULL) {
+ /* Only set exception if called from send() */
+ if (arg && !exc) PyErr_SetNone(PyExc_StopIteration);
return NULL;
+ }
+
+ if (f->f_lasti == -1) {
+ if (arg && arg != Py_None) {
+ PyErr_SetString(PyExc_TypeError,
+ "can't send non-None value to a just-started generator");
+ return NULL;
+ }
+ } else {
+ /* Push arg onto the frame's value stack */
+ result = arg ? arg : Py_None;
+ Py_INCREF(result);
+ *(f->f_stacktop++) = result;
+ }
/* Generators always return to their most recent caller, not
* necessarily their creator. */
@@ -44,7 +76,7 @@ gen_iternext(PyGenObject *gen)
f->f_back = tstate->frame;
gen->gi_running = 1;
- result = PyEval_EvalFrame(f);
+ result = PyEval_EvalFrameEx(f, exc);
gen->gi_running = 0;
/* Don't keep the reference to f_back any longer than necessary. It
@@ -58,17 +90,199 @@ gen_iternext(PyGenObject *gen)
if (result == Py_None && f->f_stacktop == NULL) {
Py_DECREF(result);
result = NULL;
+ /* Set exception if not called by gen_iternext() */
+ if (arg) PyErr_SetNone(PyExc_StopIteration);
+ }
+
+ if (!result || f->f_stacktop == NULL) {
+ /* generator can't be rerun, so release the frame */
+ Py_DECREF(f);
+ gen->gi_frame = (PyFrameObject *)Py_None;
+ Py_INCREF(Py_None);
}
return result;
}
+PyDoc_STRVAR(send_doc,
+"send(arg) -> send 'arg' into generator, return next yielded value or raise StopIteration.");
+
+static PyObject *
+gen_send(PyGenObject *gen, PyObject *arg)
+{
+ return gen_send_ex(gen, arg, 0);
+}
+
+PyDoc_STRVAR(close_doc,
+"close(arg) -> raise GeneratorExit inside generator.");
+
+static PyObject *
+gen_close(PyGenObject *gen, PyObject *args)
+{
+ PyObject *retval;
+ PyErr_SetNone(PyExc_GeneratorExit);
+ retval = gen_send_ex(gen, Py_None, 1);
+ if (retval) {
+ Py_DECREF(retval);
+ PyErr_SetString(PyExc_RuntimeError,
+ "generator ignored GeneratorExit");
+ return NULL;
+ }
+ if ( PyErr_ExceptionMatches(PyExc_StopIteration)
+ || PyErr_ExceptionMatches(PyExc_GeneratorExit) )
+ {
+ PyErr_Clear(); /* ignore these errors */
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+ return NULL;
+}
+
+static void
+gen_del(PyObject *self)
+{
+ PyObject *res;
+ PyObject *error_type, *error_value, *error_traceback;
+ PyGenObject *gen = (PyGenObject *)self;
+
+ if ((PyObject *)gen->gi_frame == Py_None || gen->gi_frame->f_stacktop==NULL)
+ /* Generator isn't paused, so no need to close */
+ return;
+
+ /* Temporarily resurrect the object. */
+ assert(self->ob_refcnt == 0);
+ self->ob_refcnt = 1;
+
+ /* Save the current exception, if any. */
+ PyErr_Fetch(&error_type, &error_value, &error_traceback);
+
+ res = gen_close((PyGenObject *)self, NULL);
+
+ if (res == NULL)
+ PyErr_WriteUnraisable((PyObject *)self);
+ else
+ Py_DECREF(res);
+
+ /* Restore the saved exception. */
+ PyErr_Restore(error_type, error_value, error_traceback);
+
+ /* Undo the temporary resurrection; can't use DECREF here, it would
+ * cause a recursive call.
+ */
+ assert(self->ob_refcnt > 0);
+ if (--self->ob_refcnt == 0)
+ return; /* this is the normal path out */
+
+ /* close() resurrected it! Make it look like the original Py_DECREF
+ * never happened.
+ */
+ {
+ int refcnt = self->ob_refcnt;
+ _Py_NewReference(self);
+ self->ob_refcnt = refcnt;
+ }
+ assert(!PyType_IS_GC(self->ob_type) ||
+ _Py_AS_GC(self)->gc.gc_refs != _PyGC_REFS_UNTRACKED);
+
+ /* If Py_REF_DEBUG, _Py_NewReference bumped _Py_RefTotal, so
+ * we need to undo that. */
+ _Py_DEC_REFTOTAL;
+ /* If Py_TRACE_REFS, _Py_NewReference re-added self to the object
+ * chain, so no more to do there.
+ * If COUNT_ALLOCS, the original decref bumped tp_frees, and
+ * _Py_NewReference bumped tp_allocs: both of those need to be
+ * undone.
+ */
+#ifdef COUNT_ALLOCS
+ --self->ob_type->tp_frees;
+ --self->ob_type->tp_allocs;
+#endif
+}
+
+
+
+PyDoc_STRVAR(throw_doc,
+"throw(typ[,val[,tb]]) -> raise exception in generator, return next yielded value or raise StopIteration.");
+
+static PyObject *
+gen_throw(PyGenObject *gen, PyObject *args)
+{
+ PyObject *typ;
+ PyObject *tb = NULL;
+ PyObject *val = NULL;
+
+ if (!PyArg_ParseTuple(args, "O|OO:throw", &typ, &val, &tb))
+ return NULL;
+
+ if (tb && !PyTraceBack_Check(tb)) {
+ PyErr_SetString(PyExc_TypeError,
+ "throw() third argument must be a traceback object");
+ return NULL;
+ }
+
+ Py_INCREF(typ);
+ Py_XINCREF(val);
+ Py_XINCREF(tb);
+
+ if (PyClass_Check(typ)) {
+ PyErr_NormalizeException(&typ, &val, &tb);
+ }
+
+ else if (PyInstance_Check(typ)) {
+ /* Raising an instance. The value should be a dummy. */
+ if (val && val != Py_None) {
+ PyErr_SetString(PyExc_TypeError,
+ "instance exception may not have a separate value");
+ goto failed_throw;
+ }
+ else {
+ /* Normalize to raise <class>, <instance> */
+ val = typ;
+ typ = (PyObject*) ((PyInstanceObject*)typ)->in_class;
+ Py_INCREF(typ);
+ }
+ }
+ else {
+ /* Not something you can raise. You get an exception
+ anyway, just not what you specified :-) */
+ PyErr_Format(PyExc_TypeError,
+ "exceptions must be classes, or instances, not %s",
+ typ->ob_type->tp_name);
+ goto failed_throw;
+ }
+
+ PyErr_Restore(typ,val,tb);
+ return gen_send_ex(gen, Py_None, 1);
+
+failed_throw:
+ /* Didn't use our arguments, so restore their original refcounts */
+ Py_DECREF(typ);
+ Py_XDECREF(val);
+ Py_XDECREF(tb);
+ return NULL;
+}
+
+
+static PyObject *
+gen_iternext(PyGenObject *gen)
+{
+ return gen_send_ex(gen, NULL, 0);
+}
+
+
static PyMemberDef gen_memberlist[] = {
{"gi_frame", T_OBJECT, offsetof(PyGenObject, gi_frame), RO},
{"gi_running", T_INT, offsetof(PyGenObject, gi_running), RO},
{NULL} /* Sentinel */
};
+static PyMethodDef gen_methods[] = {
+ {"send",(PyCFunction)gen_send, METH_O, send_doc},
+ {"throw",(PyCFunction)gen_throw, METH_VARARGS, throw_doc},
+ {"close",(PyCFunction)gen_close, METH_NOARGS, close_doc},
+ {NULL, NULL} /* Sentinel */
+};
+
PyTypeObject PyGen_Type = {
PyObject_HEAD_INIT(&PyType_Type)
0, /* ob_size */
@@ -99,11 +313,26 @@ PyTypeObject PyGen_Type = {
offsetof(PyGenObject, gi_weakreflist), /* tp_weaklistoffset */
PyObject_SelfIter, /* tp_iter */
(iternextfunc)gen_iternext, /* tp_iternext */
- 0, /* tp_methods */
+ gen_methods, /* tp_methods */
gen_memberlist, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
+
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+ 0, /* tp_free */
+ 0, /* tp_is_gc */
+ 0, /* tp_bases */
+ 0, /* tp_mro */
+ 0, /* tp_cache */
+ 0, /* tp_subclasses */
+ 0, /* tp_weaklist */
+ gen_del, /* tp_del */
};
PyObject *
diff --git a/Python/ceval.c b/Python/ceval.c
index 1103dfc..d311537 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -499,7 +499,14 @@ PyEval_EvalCode(PyCodeObject *co, PyObject *globals, PyObject *locals)
/* Interpreter main loop */
PyObject *
-PyEval_EvalFrame(PyFrameObject *f)
+PyEval_EvalFrame(PyFrameObject *f) {
+ /* This is for backward compatibility with extension modules that
+ used this API; core interpreter code should call PyEval_EvalFrameEx() */
+ return PyEval_EvalFrameEx(f, 0);
+}
+
+PyObject *
+PyEval_EvalFrameEx(PyFrameObject *f, int throw)
{
#ifdef DXPAIRS
int lastopcode = 0;
@@ -747,6 +754,11 @@ PyEval_EvalFrame(PyFrameObject *f)
x = Py_None; /* Not a reference, just anything non-NULL */
w = NULL;
+ if (throw) { /* support for generator.throw() */
+ why = WHY_EXCEPTION;
+ goto on_error;
+ }
+
for (;;) {
#ifdef WITH_TSC
if (inst1 == 0) {
@@ -2733,7 +2745,7 @@ PyEval_EvalCodeEx(PyCodeObject *co, PyObject *globals, PyObject *locals,
return PyGen_New(f);
}
- retval = PyEval_EvalFrame(f);
+ retval = PyEval_EvalFrameEx(f,0);
fail: /* Jump here from prelude on failure */
@@ -3636,7 +3648,7 @@ fast_function(PyObject *func, PyObject ***pp_stack, int n, int na, int nk)
Py_INCREF(*stack);
fastlocals[i] = *stack++;
}
- retval = PyEval_EvalFrame(f);
+ retval = PyEval_EvalFrameEx(f,0);
assert(tstate != NULL);
++tstate->recursion_depth;
Py_DECREF(f);
diff --git a/Python/compile.c b/Python/compile.c
index 476dbe6..56b3a3e 100644
--- a/Python/compile.c
+++ b/Python/compile.c
@@ -2145,6 +2145,7 @@ com_gen_for(struct compiling *c, node *n, node *t, int is_outmost)
else {
com_test(c, t);
com_addbyte(c, YIELD_VALUE);
+ com_addbyte(c, POP_TOP);
com_pop(c, 1);
}
@@ -2193,6 +2194,7 @@ com_gen_if(struct compiling *c, node *n, node *t)
else {
com_test(c, t);
com_addbyte(c, YIELD_VALUE);
+ com_addbyte(c, POP_TOP);
com_pop(c, 1);
}
com_addfwref(c, JUMP_FORWARD, &anchor);
@@ -2354,6 +2356,10 @@ com_dictmaker(struct compiling *c, node *n)
}
}
+
+/* forward reference */
+static void com_yield_expr(struct compiling *c, node *n);
+
static void
com_atom(struct compiling *c, node *n)
{
@@ -2369,7 +2375,10 @@ com_atom(struct compiling *c, node *n)
com_push(c, 1);
}
else
- com_testlist_gexp(c, CHILD(n, 1));
+ if (TYPE(CHILD(n, 1)) == yield_expr)
+ com_yield_expr(c, CHILD(n, 1));
+ else
+ com_testlist_gexp(c, CHILD(n, 1));
break;
case LSQB: /* '[' [listmaker] ']' */
if (TYPE(CHILD(n, 1)) == RSQB) {
@@ -3436,7 +3445,11 @@ com_assign(struct compiling *c, node *n, int assigning, node *augn)
}
n = CHILD(n, 0);
break;
-
+ case yield_expr:
+ com_error(c, PyExc_SyntaxError,
+ "assignment to yield expression not possible");
+ return;
+
case test:
case and_test:
case not_test:
@@ -3493,7 +3506,7 @@ com_assign(struct compiling *c, node *n, int assigning, node *augn)
}
if (assigning > OP_APPLY) {
com_error(c, PyExc_SyntaxError,
- "augmented assign to tuple literal or generator expression not possible");
+ "augmented assign to tuple literal, yield, or generator expression not possible");
return;
}
break;
@@ -3729,27 +3742,42 @@ com_return_stmt(struct compiling *c, node *n)
}
static void
-com_yield_stmt(struct compiling *c, node *n)
+com_yield_expr(struct compiling *c, node *n)
{
int i;
- REQ(n, yield_stmt); /* 'yield' testlist */
+ REQ(n, yield_expr); /* 'yield' testlist */
if (!c->c_infunction) {
com_error(c, PyExc_SyntaxError, "'yield' outside function");
}
- for (i = 0; i < c->c_nblocks; ++i) {
+ /* for (i = 0; i < c->c_nblocks; ++i) {
if (c->c_block[i] == SETUP_FINALLY) {
com_error(c, PyExc_SyntaxError,
"'yield' not allowed in a 'try' block "
"with a 'finally' clause");
return;
}
+ } */
+
+ if (NCH(n) < 2) {
+ com_addoparg(c, LOAD_CONST, com_addconst(c, Py_None));
+ com_push(c, 1);
}
- com_node(c, CHILD(n, 1));
+ else
+ com_node(c, CHILD(n, 1));
com_addbyte(c, YIELD_VALUE);
+}
+
+static void
+com_yield_stmt(struct compiling *c, node *n)
+{
+ REQ(n, yield_stmt); /* yield_expr */
+ com_node(c, CHILD(n, 0));
+ com_addbyte(c, POP_TOP);
com_pop(c, 1);
}
+
static void
com_raise_stmt(struct compiling *c, node *n)
{
@@ -4768,6 +4796,10 @@ com_node(struct compiling *c, node *n)
/* Expression nodes */
+ case yield_expr:
+ com_yield_expr(c, n);
+ break;
+
case testlist:
case testlist1:
case testlist_safe:
@@ -5027,7 +5059,9 @@ compile_generator_expression(struct compiling *c, node *n)
REQ(CHILD(n, 1), gen_for);
c->c_name = "<generator expression>";
+ c->c_infunction = 1;
com_gen_for(c, CHILD(n, 1), CHILD(n, 0), 1);
+ c->c_infunction = 0;
com_addoparg(c, LOAD_CONST, com_addconst(c, Py_None));
com_push(c, 1);
@@ -6115,7 +6149,7 @@ symtable_add_def_o(struct symtable *st, PyObject *dict,
#define symtable_add_use(ST, NAME) symtable_add_def((ST), (NAME), USE)
-/* Look for a yield stmt under n. Return 1 if found, else 0.
+/* Look for a yield stmt or expr under n. Return 1 if found, else 0.
This hack is used to look inside "if 0:" blocks (which are normally
ignored) in case those are the only places a yield occurs (so that this
function is a generator). */
@@ -6137,6 +6171,7 @@ look_for_yield(node *n)
return 0;
case yield_stmt:
+ case yield_expr:
return GENERATOR;
default:
@@ -6247,8 +6282,10 @@ symtable_node(struct symtable *st, node *n)
case del_stmt:
symtable_assign(st, CHILD(n, 1), 0);
break;
- case yield_stmt:
+ case yield_expr:
st->st_cur->ste_generator = 1;
+ if (NCH(n)==1)
+ break;
n = CHILD(n, 1);
goto loop;
case expr_stmt:
@@ -6341,9 +6378,15 @@ symtable_node(struct symtable *st, node *n)
/* fall through */
case atom:
- if (TYPE(n) == atom && TYPE(CHILD(n, 0)) == NAME) {
- symtable_add_use(st, STR(CHILD(n, 0)));
- break;
+ if (TYPE(n) == atom) {
+ if (TYPE(CHILD(n, 0)) == NAME) {
+ symtable_add_use(st, STR(CHILD(n, 0)));
+ break;
+ }
+ else if (TYPE(CHILD(n,0)) == LPAR) {
+ n = CHILD(n,1);
+ goto loop;
+ }
}
/* fall through */
default:
@@ -6739,6 +6782,15 @@ symtable_assign(struct symtable *st, node *n, int def_flag)
symtable_add_def(st, STR(tmp), DEF_LOCAL | def_flag);
}
return;
+
+ case yield_expr:
+ st->st_cur->ste_generator = 1;
+ if (NCH(n)==2) {
+ n = CHILD(n, 1);
+ goto loop;
+ }
+ return;
+
case dotted_as_name:
if (NCH(n) == 3)
symtable_add_def(st, STR(CHILD(n, 2)),
diff --git a/Python/exceptions.c b/Python/exceptions.c
index 2fd74bc..2e7c820 100644
--- a/Python/exceptions.c
+++ b/Python/exceptions.c
@@ -57,6 +57,7 @@ Exception\n\
|\n\
+-- SystemExit\n\
+-- StopIteration\n\
+ +-- GeneratorExit\n\
+-- StandardError\n\
| |\n\
| +-- KeyboardInterrupt\n\
@@ -394,6 +395,7 @@ PyDoc_STRVAR(StandardError__doc__,
PyDoc_STRVAR(TypeError__doc__, "Inappropriate argument type.");
PyDoc_STRVAR(StopIteration__doc__, "Signal the end from iterator.next().");
+PyDoc_STRVAR(GeneratorExit__doc__, "Request that a generator exit.");
@@ -1583,6 +1585,7 @@ static PyMethodDef functions[] = {
PyObject *PyExc_Exception;
PyObject *PyExc_StopIteration;
+PyObject *PyExc_GeneratorExit;
PyObject *PyExc_StandardError;
PyObject *PyExc_ArithmeticError;
PyObject *PyExc_LookupError;
@@ -1657,6 +1660,8 @@ static struct {
{"Exception", &PyExc_Exception},
{"StopIteration", &PyExc_StopIteration, &PyExc_Exception,
StopIteration__doc__},
+ {"GeneratorExit", &PyExc_GeneratorExit, &PyExc_Exception,
+ GeneratorExit__doc__},
{"StandardError", &PyExc_StandardError, &PyExc_Exception,
StandardError__doc__},
{"TypeError", &PyExc_TypeError, 0, TypeError__doc__},
diff --git a/Python/graminit.c b/Python/graminit.c
index 464f0ae..91d20f2 100644
--- a/Python/graminit.c
+++ b/Python/graminit.c
@@ -279,10 +279,12 @@ static arc arcs_13_1[3] = {
{25, 3},
{0, 1},
};
-static arc arcs_13_2[1] = {
+static arc arcs_13_2[2] = {
+ {43, 4},
{9, 4},
};
-static arc arcs_13_3[1] = {
+static arc arcs_13_3[2] = {
+ {43, 5},
{9, 5},
};
static arc arcs_13_4[1] = {
@@ -295,13 +297,12 @@ static arc arcs_13_5[2] = {
static state states_13[6] = {
{1, arcs_13_0},
{3, arcs_13_1},
- {1, arcs_13_2},
- {1, arcs_13_3},
+ {2, arcs_13_2},
+ {2, arcs_13_3},
{1, arcs_13_4},
{2, arcs_13_5},
};
static arc arcs_14_0[12] = {
- {43, 1},
{44, 1},
{45, 1},
{46, 1},
@@ -313,6 +314,7 @@ static arc arcs_14_0[12] = {
{52, 1},
{53, 1},
{54, 1},
+ {55, 1},
};
static arc arcs_14_1[1] = {
{0, 1},
@@ -322,11 +324,11 @@ static state states_14[2] = {
{1, arcs_14_1},
};
static arc arcs_15_0[1] = {
- {55, 1},
+ {56, 1},
};
static arc arcs_15_1[3] = {
{26, 2},
- {56, 3},
+ {57, 3},
{0, 1},
};
static arc arcs_15_2[2] = {
@@ -367,10 +369,10 @@ static state states_15[9] = {
{2, arcs_15_8},
};
static arc arcs_16_0[1] = {
- {57, 1},
+ {58, 1},
};
static arc arcs_16_1[1] = {
- {58, 2},
+ {59, 2},
};
static arc arcs_16_2[1] = {
{0, 2},
@@ -381,7 +383,7 @@ static state states_16[3] = {
{1, arcs_16_2},
};
static arc arcs_17_0[1] = {
- {59, 1},
+ {60, 1},
};
static arc arcs_17_1[1] = {
{0, 1},
@@ -391,11 +393,11 @@ static state states_17[2] = {
{1, arcs_17_1},
};
static arc arcs_18_0[5] = {
- {60, 1},
{61, 1},
{62, 1},
{63, 1},
{64, 1},
+ {65, 1},
};
static arc arcs_18_1[1] = {
{0, 1},
@@ -405,7 +407,7 @@ static state states_18[2] = {
{1, arcs_18_1},
};
static arc arcs_19_0[1] = {
- {65, 1},
+ {66, 1},
};
static arc arcs_19_1[1] = {
{0, 1},
@@ -415,7 +417,7 @@ static state states_19[2] = {
{1, arcs_19_1},
};
static arc arcs_20_0[1] = {
- {66, 1},
+ {67, 1},
};
static arc arcs_20_1[1] = {
{0, 1},
@@ -425,7 +427,7 @@ static state states_20[2] = {
{1, arcs_20_1},
};
static arc arcs_21_0[1] = {
- {67, 1},
+ {68, 1},
};
static arc arcs_21_1[2] = {
{9, 2},
@@ -440,18 +442,14 @@ static state states_21[3] = {
{1, arcs_21_2},
};
static arc arcs_22_0[1] = {
- {68, 1},
+ {43, 1},
};
static arc arcs_22_1[1] = {
- {9, 2},
-};
-static arc arcs_22_2[1] = {
- {0, 2},
+ {0, 1},
};
-static state states_22[3] = {
+static state states_22[2] = {
{1, arcs_22_0},
{1, arcs_22_1},
- {1, arcs_22_2},
};
static arc arcs_23_0[1] = {
{69, 1},
@@ -779,7 +777,7 @@ static arc arcs_38_0[1] = {
{93, 1},
};
static arc arcs_38_1[1] = {
- {58, 2},
+ {59, 2},
};
static arc arcs_38_2[1] = {
{82, 3},
@@ -1034,7 +1032,7 @@ static arc arcs_50_0[1] = {
};
static arc arcs_50_1[3] = {
{123, 0},
- {56, 0},
+ {57, 0},
{0, 1},
};
static state states_50[2] = {
@@ -1113,7 +1111,8 @@ static arc arcs_55_0[7] = {
{144, 5},
{145, 6},
};
-static arc arcs_55_1[2] = {
+static arc arcs_55_1[3] = {
+ {43, 7},
{135, 7},
{15, 5},
};
@@ -1149,7 +1148,7 @@ static arc arcs_55_10[1] = {
};
static state states_55[11] = {
{7, arcs_55_0},
- {2, arcs_55_1},
+ {3, arcs_55_1},
{2, arcs_55_2},
{2, arcs_55_3},
{1, arcs_55_4},
@@ -1533,7 +1532,7 @@ static arc arcs_71_0[1] = {
{93, 1},
};
static arc arcs_71_1[1] = {
- {58, 2},
+ {59, 2},
};
static arc arcs_71_2[1] = {
{82, 3},
@@ -1590,7 +1589,7 @@ static arc arcs_74_0[1] = {
{93, 1},
};
static arc arcs_74_1[1] = {
- {58, 2},
+ {59, 2},
};
static arc arcs_74_2[1] = {
{82, 3},
@@ -1653,165 +1652,182 @@ static state states_77[2] = {
{1, arcs_77_0},
{1, arcs_77_1},
};
-static dfa dfas[78] = {
+static arc arcs_78_0[1] = {
+ {160, 1},
+};
+static arc arcs_78_1[2] = {
+ {9, 2},
+ {0, 1},
+};
+static arc arcs_78_2[1] = {
+ {0, 2},
+};
+static state states_78[3] = {
+ {1, arcs_78_0},
+ {2, arcs_78_1},
+ {1, arcs_78_2},
+};
+static dfa dfas[79] = {
{256, "single_input", 0, 3, states_0,
- "\004\050\014\000\000\000\200\012\076\205\011\162\000\002\000\140\010\111\023\002"},
+ "\004\050\014\000\000\000\000\025\074\205\011\162\000\002\000\140\010\111\023\002\001"},
{257, "file_input", 0, 2, states_1,
- "\204\050\014\000\000\000\200\012\076\205\011\162\000\002\000\140\010\111\023\002"},
+ "\204\050\014\000\000\000\000\025\074\205\011\162\000\002\000\140\010\111\023\002\001"},
{258, "eval_input", 0, 3, states_2,
- "\000\040\010\000\000\000\000\000\000\000\000\000\000\002\000\140\010\111\023\000"},
+ "\000\040\010\000\000\000\000\000\000\000\000\000\000\002\000\140\010\111\023\000\000"},
{259, "decorator", 0, 7, states_3,
- "\000\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
+ "\000\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
{260, "decorators", 0, 2, states_4,
- "\000\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
+ "\000\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
{261, "funcdef", 0, 7, states_5,
- "\000\010\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
+ "\000\010\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
{262, "parameters", 0, 4, states_6,
- "\000\040\000\000\000\000\000\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\000\000\000\000"},
{263, "varargslist", 0, 10, states_7,
- "\000\040\010\060\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
+ "\000\040\010\060\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
{264, "fpdef", 0, 4, states_8,
- "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
+ "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
{265, "fplist", 0, 3, states_9,
- "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
+ "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
{266, "stmt", 0, 2, states_10,
- "\000\050\014\000\000\000\200\012\076\205\011\162\000\002\000\140\010\111\023\002"},
+ "\000\050\014\000\000\000\000\025\074\205\011\162\000\002\000\140\010\111\023\002\001"},
{267, "simple_stmt", 0, 4, states_11,
- "\000\040\010\000\000\000\200\012\076\205\011\000\000\002\000\140\010\111\023\000"},
+ "\000\040\010\000\000\000\000\025\074\205\011\000\000\002\000\140\010\111\023\000\001"},
{268, "small_stmt", 0, 2, states_12,
- "\000\040\010\000\000\000\200\012\076\205\011\000\000\002\000\140\010\111\023\000"},
+ "\000\040\010\000\000\000\000\025\074\205\011\000\000\002\000\140\010\111\023\000\001"},
{269, "expr_stmt", 0, 6, states_13,
- "\000\040\010\000\000\000\000\000\000\000\000\000\000\002\000\140\010\111\023\000"},
+ "\000\040\010\000\000\000\000\000\000\000\000\000\000\002\000\140\010\111\023\000\000"},
{270, "augassign", 0, 2, states_14,
- "\000\000\000\000\000\370\177\000\000\000\000\000\000\000\000\000\000\000\000\000"},
+ "\000\000\000\000\000\360\377\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
{271, "print_stmt", 0, 9, states_15,
- "\000\000\000\000\000\000\200\000\000\000\000\000\000\000\000\000\000\000\000\000"},
+ "\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000"},
{272, "del_stmt", 0, 3, states_16,
- "\000\000\000\000\000\000\000\002\000\000\000\000\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"},
{273, "pass_stmt", 0, 2, states_17,
- "\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\000\000\000\000\000"},
+ "\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\000\000\000\000\000\000"},
{274, "flow_stmt", 0, 2, states_18,
- "\000\000\000\000\000\000\000\000\076\000\000\000\000\000\000\000\000\000\000\000"},
+ "\000\000\000\000\000\000\000\000\074\000\000\000\000\000\000\000\000\000\000\000\001"},
{275, "break_stmt", 0, 2, states_19,
- "\000\000\000\000\000\000\000\000\002\000\000\000\000\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"},
{276, "continue_stmt", 0, 2, states_20,
- "\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000"},
+ "\000\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\000\000\000\000\000"},
{277, "return_stmt", 0, 3, states_21,
- "\000\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\000\000\000\000"},
- {278, "yield_stmt", 0, 3, states_22,
- "\000\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\000\000\000\000"},
+ "\000\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\000\000\000\000\000"},
+ {278, "yield_stmt", 0, 2, states_22,
+ "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001"},
{279, "raise_stmt", 0, 7, states_23,
- "\000\000\000\000\000\000\000\000\040\000\000\000\000\000\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"},
{280, "import_stmt", 0, 2, states_24,
- "\000\000\000\000\000\000\000\000\000\005\000\000\000\000\000\000\000\000\000\000"},
+ "\000\000\000\000\000\000\000\000\000\005\000\000\000\000\000\000\000\000\000\000\000"},
{281, "import_name", 0, 3, states_25,
- "\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000"},
+ "\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000"},
{282, "import_from", 0, 7, states_26,
- "\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\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000"},
{283, "import_as_name", 0, 4, states_27,
- "\000\000\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
+ "\000\000\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
{284, "dotted_as_name", 0, 4, states_28,
- "\000\000\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
+ "\000\000\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
{285, "import_as_names", 0, 3, states_29,
- "\000\000\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
+ "\000\000\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
{286, "dotted_as_names", 0, 2, states_30,
- "\000\000\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
+ "\000\000\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
{287, "dotted_name", 0, 2, states_31,
- "\000\000\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
+ "\000\000\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
{288, "global_stmt", 0, 3, states_32,
- "\000\000\000\000\000\000\000\000\000\200\000\000\000\000\000\000\000\000\000\000"},
+ "\000\000\000\000\000\000\000\000\000\200\000\000\000\000\000\000\000\000\000\000\000"},
{289, "exec_stmt", 0, 7, states_33,
- "\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000"},
+ "\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000"},
{290, "assert_stmt", 0, 5, states_34,
- "\000\000\000\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\000\000"},
+ "\000\000\000\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\000\000\000"},
{291, "compound_stmt", 0, 2, states_35,
- "\000\010\004\000\000\000\000\000\000\000\000\162\000\000\000\000\000\000\000\002"},
+ "\000\010\004\000\000\000\000\000\000\000\000\162\000\000\000\000\000\000\000\002\000"},
{292, "if_stmt", 0, 8, states_36,
- "\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000"},
+ "\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000"},
{293, "while_stmt", 0, 8, states_37,
- "\000\000\000\000\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\000"},
+ "\000\000\000\000\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\000\000"},
{294, "for_stmt", 0, 10, states_38,
- "\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\000\000\000\000\040\000\000\000\000\000\000\000\000\000"},
{295, "try_stmt", 0, 10, states_39,
- "\000\000\000\000\000\000\000\000\000\000\000\100\000\000\000\000\000\000\000\000"},
+ "\000\000\000\000\000\000\000\000\000\000\000\100\000\000\000\000\000\000\000\000\000"},
{296, "except_clause", 0, 5, states_40,
- "\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000"},
+ "\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000"},
{297, "suite", 0, 5, states_41,
- "\004\040\010\000\000\000\200\012\076\205\011\000\000\002\000\140\010\111\023\000"},
+ "\004\040\010\000\000\000\000\025\074\205\011\000\000\002\000\140\010\111\023\000\001"},
{298, "test", 0, 4, states_42,
- "\000\040\010\000\000\000\000\000\000\000\000\000\000\002\000\140\010\111\023\000"},
+ "\000\040\010\000\000\000\000\000\000\000\000\000\000\002\000\140\010\111\023\000\000"},
{299, "and_test", 0, 2, states_43,
- "\000\040\010\000\000\000\000\000\000\000\000\000\000\002\000\140\010\111\003\000"},
+ "\000\040\010\000\000\000\000\000\000\000\000\000\000\002\000\140\010\111\003\000\000"},
{300, "not_test", 0, 3, states_44,
- "\000\040\010\000\000\000\000\000\000\000\000\000\000\002\000\140\010\111\003\000"},
+ "\000\040\010\000\000\000\000\000\000\000\000\000\000\002\000\140\010\111\003\000\000"},
{301, "comparison", 0, 2, states_45,
- "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\140\010\111\003\000"},
+ "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\140\010\111\003\000\000"},
{302, "comp_op", 0, 4, states_46,
- "\000\000\000\000\000\000\000\000\000\000\004\000\000\362\017\000\000\000\000\000"},
+ "\000\000\000\000\000\000\000\000\000\000\004\000\000\362\017\000\000\000\000\000\000"},
{303, "expr", 0, 2, states_47,
- "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\140\010\111\003\000"},
+ "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\140\010\111\003\000\000"},
{304, "xor_expr", 0, 2, states_48,
- "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\140\010\111\003\000"},
+ "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\140\010\111\003\000\000"},
{305, "and_expr", 0, 2, states_49,
- "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\140\010\111\003\000"},
+ "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\140\010\111\003\000\000"},
{306, "shift_expr", 0, 2, states_50,
- "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\140\010\111\003\000"},
+ "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\140\010\111\003\000\000"},
{307, "arith_expr", 0, 2, states_51,
- "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\140\010\111\003\000"},
+ "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\140\010\111\003\000\000"},
{308, "term", 0, 2, states_52,
- "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\140\010\111\003\000"},
+ "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\140\010\111\003\000\000"},
{309, "factor", 0, 3, states_53,
- "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\140\010\111\003\000"},
+ "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\140\010\111\003\000\000"},
{310, "power", 0, 4, states_54,
- "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\111\003\000"},
+ "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\111\003\000\000"},
{311, "atom", 0, 11, states_55,
- "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\111\003\000"},
+ "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\111\003\000\000"},
{312, "listmaker", 0, 5, states_56,
- "\000\040\010\000\000\000\000\000\000\000\000\000\000\002\000\140\010\111\023\000"},
+ "\000\040\010\000\000\000\000\000\000\000\000\000\000\002\000\140\010\111\023\000\000"},
{313, "testlist_gexp", 0, 5, states_57,
- "\000\040\010\000\000\000\000\000\000\000\000\000\000\002\000\140\010\111\023\000"},
+ "\000\040\010\000\000\000\000\000\000\000\000\000\000\002\000\140\010\111\023\000\000"},
{314, "lambdef", 0, 5, states_58,
- "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\020\000"},
+ "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\020\000\000"},
{315, "trailer", 0, 7, states_59,
- "\000\040\000\000\000\000\000\000\000\100\000\000\000\000\000\000\000\001\000\000"},
+ "\000\040\000\000\000\000\000\000\000\100\000\000\000\000\000\000\000\001\000\000\000"},
{316, "subscriptlist", 0, 3, states_60,
- "\000\040\050\000\000\000\000\000\000\100\000\000\000\002\000\140\010\111\023\000"},
+ "\000\040\050\000\000\000\000\000\000\100\000\000\000\002\000\140\010\111\023\000\000"},
{317, "subscript", 0, 7, states_61,
- "\000\040\050\000\000\000\000\000\000\100\000\000\000\002\000\140\010\111\023\000"},
+ "\000\040\050\000\000\000\000\000\000\100\000\000\000\002\000\140\010\111\023\000\000"},
{318, "sliceop", 0, 3, states_62,
- "\000\000\040\000\000\000\000\000\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\000\000\000"},
{319, "exprlist", 0, 3, states_63,
- "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\140\010\111\003\000"},
+ "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\140\010\111\003\000\000"},
{320, "testlist", 0, 3, states_64,
- "\000\040\010\000\000\000\000\000\000\000\000\000\000\002\000\140\010\111\023\000"},
+ "\000\040\010\000\000\000\000\000\000\000\000\000\000\002\000\140\010\111\023\000\000"},
{321, "testlist_safe", 0, 5, states_65,
- "\000\040\010\000\000\000\000\000\000\000\000\000\000\002\000\140\010\111\023\000"},
+ "\000\040\010\000\000\000\000\000\000\000\000\000\000\002\000\140\010\111\023\000\000"},
{322, "dictmaker", 0, 5, states_66,
- "\000\040\010\000\000\000\000\000\000\000\000\000\000\002\000\140\010\111\023\000"},
+ "\000\040\010\000\000\000\000\000\000\000\000\000\000\002\000\140\010\111\023\000\000"},
{323, "classdef", 0, 8, states_67,
- "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002"},
+ "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000"},
{324, "arglist", 0, 8, states_68,
- "\000\040\010\060\000\000\000\000\000\000\000\000\000\002\000\140\010\111\023\000"},
+ "\000\040\010\060\000\000\000\000\000\000\000\000\000\002\000\140\010\111\023\000\000"},
{325, "argument", 0, 5, states_69,
- "\000\040\010\000\000\000\000\000\000\000\000\000\000\002\000\140\010\111\023\000"},
+ "\000\040\010\000\000\000\000\000\000\000\000\000\000\002\000\140\010\111\023\000\000"},
{326, "list_iter", 0, 2, states_70,
- "\000\000\000\000\000\000\000\000\000\000\000\042\000\000\000\000\000\000\000\000"},
+ "\000\000\000\000\000\000\000\000\000\000\000\042\000\000\000\000\000\000\000\000\000"},
{327, "list_for", 0, 6, states_71,
- "\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\000\000\000\000\040\000\000\000\000\000\000\000\000\000"},
{328, "list_if", 0, 4, states_72,
- "\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000"},
+ "\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000"},
{329, "gen_iter", 0, 2, states_73,
- "\000\000\000\000\000\000\000\000\000\000\000\042\000\000\000\000\000\000\000\000"},
+ "\000\000\000\000\000\000\000\000\000\000\000\042\000\000\000\000\000\000\000\000\000"},
{330, "gen_for", 0, 6, states_74,
- "\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\000\000\000\000\040\000\000\000\000\000\000\000\000\000"},
{331, "gen_if", 0, 4, states_75,
- "\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000"},
+ "\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000"},
{332, "testlist1", 0, 2, states_76,
- "\000\040\010\000\000\000\000\000\000\000\000\000\000\002\000\140\010\111\023\000"},
+ "\000\040\010\000\000\000\000\000\000\000\000\000\000\002\000\140\010\111\023\000\000"},
{333, "encoding_decl", 0, 2, states_77,
- "\000\000\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
+ "\000\000\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
+ {334, "yield_expr", 0, 3, states_78,
+ "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001"},
};
-static label labels[160] = {
+static label labels[161] = {
{0, "EMPTY"},
{256, 0},
{4, 0},
@@ -1855,6 +1871,7 @@ static label labels[160] = {
{289, 0},
{290, 0},
{270, 0},
+ {334, 0},
{37, 0},
{38, 0},
{39, 0},
@@ -1880,7 +1897,6 @@ static label labels[160] = {
{1, "break"},
{1, "continue"},
{1, "return"},
- {1, "yield"},
{1, "raise"},
{281, 0},
{282, 0},
@@ -1972,10 +1988,11 @@ static label labels[160] = {
{329, 0},
{331, 0},
{333, 0},
+ {1, "yield"},
};
grammar _PyParser_Grammar = {
- 78,
+ 79,
dfas,
- {160, labels},
+ {161, labels},
256
};