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.
This commit is contained in:
Phillip J. Eby 2005-08-02 00:46:46 +00:00
parent d794666048
commit 0d6615fd29
16 changed files with 862 additions and 242 deletions

View File

@ -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]

View File

@ -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;

View File

@ -76,3 +76,4 @@
#define gen_if 331
#define testlist1 332
#define encoding_decl 333
#define yield_expr 334

View File

@ -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;

View File

@ -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,

View File

@ -88,6 +88,7 @@ gen_for = 330
gen_if = 331
testlist1 = 332
encoding_decl = 333
yield_expr = 334
#--end constants--
sym_name = {}

View File

@ -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.

View File

@ -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

View File

@ -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)")

View File

@ -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))
return op->ob_type->tp_del != NULL;
else
return 0;
return op->ob_type->tp_del != NULL;
}
/* Move the objects in unreachable with __del__ methods into `finalizers`.

View File

@ -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
@ -1506,6 +1507,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)
{
@ -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))
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;

View File

@ -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 *

View File

@ -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);

View File

@ -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)
{
@ -2368,6 +2374,9 @@ com_atom(struct compiling *c, node *n)
com_addoparg(c, BUILD_TUPLE, 0);
com_push(c, 1);
}
else
if (TYPE(CHILD(n, 1)) == yield_expr)
com_yield_expr(c, CHILD(n, 1));
else
com_testlist_gexp(c, CHILD(n, 1));
break;
@ -3436,6 +3445,10 @@ 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:
@ -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);
}
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,10 +6378,16 @@ symtable_node(struct symtable *st, node *n)
/* fall through */
case atom:
if (TYPE(n) == atom && TYPE(CHILD(n, 0)) == NAME) {
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:
/* Walk over every non-token child with a special case
@ -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)),

View File

@ -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__},

View File

@ -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},
{0, 1},
};
static arc arcs_22_2[1] = {
{0, 2},
};
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] = {
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
static arc arcs_78_0[1] = {
{160, 1},
};
static label labels[160] = {
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\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\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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{266, "stmt", 0, 2, states_10,
"\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\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\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"},
{270, "augassign", 0, 2, states_14,
"\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\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\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\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\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\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\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\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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{297, "suite", 0, 5, states_41,
"\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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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"},
{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[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
};