[med-svn] [python3-typed-ast] 01/02: Imported Upstream version 0.5.5

Michael Crusoe misterc-guest at moszumanska.debian.org
Wed Aug 17 12:06:50 UTC 2016


This is an automated email from the git hooks/post-receive script.

misterc-guest pushed a commit to branch master
in repository python3-typed-ast.

commit f60277b7b9ee61028e2840b4cafb39d28f5c0cbf
Author: Michael R. Crusoe <crusoe at ucdavis.edu>
Date:   Wed Aug 17 04:37:55 2016 -0700

    Imported Upstream version 0.5.5
---
 .gitignore                    |    5 +
 CONTRIBUTING.md               |    1 +
 LICENSE                       |  253 ++
 MANIFEST.in                   |    2 +
 README.md                     |   52 +
 appveyor.yml                  |   47 +
 ast27/Custom/typed_ast.c      |  313 ++
 ast27/Grammar/Grammar         |  151 +
 ast27/Include/Python-ast.h    |  547 +++
 ast27/Include/asdl.h          |   52 +
 ast27/Include/ast.h           |   13 +
 ast27/Include/bitset.h        |   32 +
 ast27/Include/compile.h       |   18 +
 ast27/Include/errcode.h       |   36 +
 ast27/Include/graminit.h      |   90 +
 ast27/Include/grammar.h       |   93 +
 ast27/Include/node.h          |   41 +
 ast27/Include/parsetok.h      |   73 +
 ast27/Include/token.h         |   88 +
 ast27/Parser/Python.asdl      |  122 +
 ast27/Parser/acceler.c        |  125 +
 ast27/Parser/asdl.py          |  413 +++
 ast27/Parser/asdl_c.py        | 1249 +++++++
 ast27/Parser/bitset.c         |   66 +
 ast27/Parser/grammar.c        |  254 ++
 ast27/Parser/grammar1.c       |   57 +
 ast27/Parser/node.c           |  164 +
 ast27/Parser/parser.c         |  436 +++
 ast27/Parser/parser.h         |   42 +
 ast27/Parser/parsetok.c       |  395 +++
 ast27/Parser/spark.py         |  839 +++++
 ast27/Parser/tokenizer.c      | 1827 ++++++++++
 ast27/Parser/tokenizer.h      |   71 +
 ast27/Python/Python-ast.c     | 7030 ++++++++++++++++++++++++++++++++++++
 ast27/Python/ast.c            | 3784 ++++++++++++++++++++
 ast27/Python/graminit.c       | 2337 ++++++++++++
 ast27/Python/mystrtoul.c      |  285 ++
 ast35/Custom/typed_ast.c      |  322 ++
 ast35/Grammar/Grammar         |  162 +
 ast35/Include/Python-ast.h    |  633 ++++
 ast35/Include/asdl.h          |   50 +
 ast35/Include/ast.h           |   22 +
 ast35/Include/bitset.h        |   32 +
 ast35/Include/compile.h       |   11 +
 ast35/Include/errcode.h       |   38 +
 ast35/Include/graminit.h      |   90 +
 ast35/Include/grammar.h       |   93 +
 ast35/Include/node.h          |   44 +
 ast35/Include/parsetok.h      |  108 +
 ast35/Include/token.h         |   92 +
 ast35/Parser/Python.asdl      |  126 +
 ast35/Parser/acceler.c        |  125 +
 ast35/Parser/asdl.py          |  375 ++
 ast35/Parser/asdl_c.py        | 1326 +++++++
 ast35/Parser/bitset.c         |   66 +
 ast35/Parser/grammar.c        |  250 ++
 ast35/Parser/grammar1.c       |   61 +
 ast35/Parser/node.c           |  169 +
 ast35/Parser/parser.c         |  448 +++
 ast35/Parser/parser.h         |   42 +
 ast35/Parser/parsetok.c       |  446 +++
 ast35/Parser/tokenizer.c      | 1952 ++++++++++
 ast35/Parser/tokenizer.h      |   89 +
 ast35/Python/Python-ast.c     | 7815 +++++++++++++++++++++++++++++++++++++++++
 ast35/Python/ast.c            | 4304 +++++++++++++++++++++++
 ast35/Python/graminit.c       | 2390 +++++++++++++
 build.cmd                     |   21 +
 setup.py                      |  100 +
 tools/find_exported_symbols   |    8 +
 tools/update_exported_symbols |   13 +
 tools/update_header_guards    |   12 +
 typed_ast/__init__.py         |    0
 typed_ast/ast27.py            |  311 ++
 typed_ast/ast35.py            |  325 ++
 typed_ast/conversions.py      |  214 ++
 75 files changed, 44088 insertions(+)

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..cc7f758
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,5 @@
+*.o
+*.pyc
+build/
+__pycache__/
+.DS_Store
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000..16aa21f
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1 @@
+To contribute code to this project, you'll need to sign [Dropbox's Contributor License Agreement](https://opensource.dropbox.com/cla/).
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..ee233ec
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,253 @@
+                              Apache License
+                        Version 2.0, January 2004
+                     http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+   "License" shall mean the terms and conditions for use, reproduction,
+   and distribution as defined by Sections 1 through 9 of this document.
+
+   "Licensor" shall mean the copyright owner or entity authorized by
+   the copyright owner that is granting the License.
+
+   "Legal Entity" shall mean the union of the acting entity and all
+   other entities that control, are controlled by, or are under common
+   control with that entity. For the purposes of this definition,
+   "control" means (i) the power, direct or indirect, to cause the
+   direction or management of such entity, whether by contract or
+   otherwise, or (ii) ownership of fifty percent (50%) or more of the
+   outstanding shares, or (iii) beneficial ownership of such entity.
+
+   "You" (or "Your") shall mean an individual or Legal Entity
+   exercising permissions granted by this License.
+
+   "Source" form shall mean the preferred form for making modifications,
+   including but not limited to software source code, documentation
+   source, and configuration files.
+
+   "Object" form shall mean any form resulting from mechanical
+   transformation or translation of a Source form, including but
+   not limited to compiled object code, generated documentation,
+   and conversions to other media types.
+
+   "Work" shall mean the work of authorship, whether in Source or
+   Object form, made available under the License, as indicated by a
+   copyright notice that is included in or attached to the work
+   (an example is provided in the Appendix below).
+
+   "Derivative Works" shall mean any work, whether in Source or Object
+   form, that is based on (or derived from) the Work and for which the
+   editorial revisions, annotations, elaborations, or other modifications
+   represent, as a whole, an original work of authorship. For the purposes
+   of this License, Derivative Works shall not include works that remain
+   separable from, or merely link (or bind by name) to the interfaces of,
+   the Work and Derivative Works thereof.
+
+   "Contribution" shall mean any work of authorship, including
+   the original version of the Work and any modifications or additions
+   to that Work or Derivative Works thereof, that is intentionally
+   submitted to Licensor for inclusion in the Work by the copyright owner
+   or by an individual or Legal Entity authorized to submit on behalf of
+   the copyright owner. For the purposes of this definition, "submitted"
+   means any form of electronic, verbal, or written communication sent
+   to the Licensor or its representatives, including but not limited to
+   communication on electronic mailing lists, source code control systems,
+   and issue tracking systems that are managed by, or on behalf of, the
+   Licensor for the purpose of discussing and improving the Work, but
+   excluding communication that is conspicuously marked or otherwise
+   designated in writing by the copyright owner as "Not a Contribution."
+
+   "Contributor" shall mean Licensor and any individual or Legal Entity
+   on behalf of whom a Contribution has been received by Licensor and
+   subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of
+   this License, each Contributor hereby grants to You a perpetual,
+   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+   copyright license to reproduce, prepare Derivative Works of,
+   publicly display, publicly perform, sublicense, and distribute the
+   Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of
+   this License, each Contributor hereby grants to You a perpetual,
+   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+   (except as stated in this section) patent license to make, have made,
+   use, offer to sell, sell, import, and otherwise transfer the Work,
+   where such license applies only to those patent claims licensable
+   by such Contributor that are necessarily infringed by their
+   Contribution(s) alone or by combination of their Contribution(s)
+   with the Work to which such Contribution(s) was submitted. If You
+   institute patent litigation against any entity (including a
+   cross-claim or counterclaim in a lawsuit) alleging that the Work
+   or a Contribution incorporated within the Work constitutes direct
+   or contributory patent infringement, then any patent licenses
+   granted to You under this License for that Work shall terminate
+   as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the
+   Work or Derivative Works thereof in any medium, with or without
+   modifications, and in Source or Object form, provided that You
+   meet the following conditions:
+
+   (a) You must give any other recipients of the Work or
+       Derivative Works a copy of this License; and
+
+   (b) You must cause any modified files to carry prominent notices
+       stating that You changed the files; and
+
+   (c) You must retain, in the Source form of any Derivative Works
+       that You distribute, all copyright, patent, trademark, and
+       attribution notices from the Source form of the Work,
+       excluding those notices that do not pertain to any part of
+       the Derivative Works; and
+
+   (d) If the Work includes a "NOTICE" text file as part of its
+       distribution, then any Derivative Works that You distribute must
+       include a readable copy of the attribution notices contained
+       within such NOTICE file, excluding those notices that do not
+       pertain to any part of the Derivative Works, in at least one
+       of the following places: within a NOTICE text file distributed
+       as part of the Derivative Works; within the Source form or
+       documentation, if provided along with the Derivative Works; or,
+       within a display generated by the Derivative Works, if and
+       wherever such third-party notices normally appear. The contents
+       of the NOTICE file are for informational purposes only and
+       do not modify the License. You may add Your own attribution
+       notices within Derivative Works that You distribute, alongside
+       or as an addendum to the NOTICE text from the Work, provided
+       that such additional attribution notices cannot be construed
+       as modifying the License.
+
+   You may add Your own copyright statement to Your modifications and
+   may provide additional or different license terms and conditions
+   for use, reproduction, or distribution of Your modifications, or
+   for any such Derivative Works as a whole, provided Your use,
+   reproduction, and distribution of the Work otherwise complies with
+   the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise,
+   any Contribution intentionally submitted for inclusion in the Work
+   by You to the Licensor shall be under the terms and conditions of
+   this License, without any additional terms or conditions.
+   Notwithstanding the above, nothing herein shall supersede or modify
+   the terms of any separate license agreement you may have executed
+   with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade
+   names, trademarks, service marks, or product names of the Licensor,
+   except as required for reasonable and customary use in describing the
+   origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or
+   agreed to in writing, Licensor provides the Work (and each
+   Contributor provides its Contributions) on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+   implied, including, without limitation, any warranties or conditions
+   of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+   PARTICULAR PURPOSE. You are solely responsible for determining the
+   appropriateness of using or redistributing the Work and assume any
+   risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory,
+   whether in tort (including negligence), contract, or otherwise,
+   unless required by applicable law (such as deliberate and grossly
+   negligent acts) or agreed to in writing, shall any Contributor be
+   liable to You for damages, including any direct, indirect, special,
+   incidental, or consequential damages of any character arising as a
+   result of this License or out of the use or inability to use the
+   Work (including but not limited to damages for loss of goodwill,
+   work stoppage, computer failure or malfunction, or any and all
+   other commercial damages or losses), even if such Contributor
+   has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing
+   the Work or Derivative Works thereof, You may choose to offer,
+   and charge a fee for, acceptance of support, warranty, indemnity,
+   or other liability obligations and/or rights consistent with this
+   License. However, in accepting such obligations, You may act only
+   on Your own behalf and on Your sole responsibility, not on behalf
+   of any other Contributor, and only if You agree to indemnify,
+   defend, and hold each Contributor harmless for any liability
+   incurred by, or claims asserted against, such Contributor by reason
+   of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work.
+
+   To apply the Apache License to your work, attach the following
+   boilerplate notice, with the fields enclosed by brackets "[]"
+   replaced with your own identifying information. (Don't include
+   the brackets!)  The text should be enclosed in the appropriate
+   comment syntax for the file format. We also recommend that a
+   file or class name and description of purpose be included on the
+   same "printed page" as the copyright notice for easier
+   identification within third-party archives.
+
+Copyright 2016 Dropbox, Inc.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+--------------
+
+The original CPython source is licensed under the Python Software Foundation License Version 2:
+PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2
+--------------------------------------------
+
+1. This LICENSE AGREEMENT is between the Python Software Foundation
+("PSF"), and the Individual or Organization ("Licensee") accessing and
+otherwise using this software ("Python") in source or binary form and
+its associated documentation.
+
+2. Subject to the terms and conditions of this License Agreement, PSF hereby
+grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce,
+analyze, test, perform and/or display publicly, prepare derivative works,
+distribute, and otherwise use Python alone or in any derivative version,
+provided, however, that PSF's License Agreement and PSF's notice of copyright,
+i.e., "Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
+2011, 2012, 2013, 2014, 2015, 2016 Python Software Foundation; All Rights
+Reserved" are retained in Python alone or in any derivative version prepared by
+Licensee.
+
+3. In the event Licensee prepares a derivative work that is based on
+or incorporates Python or any part thereof, and wants to make
+the derivative work available to others as provided herein, then
+Licensee hereby agrees to include in any such work a brief summary of
+the changes made to Python.
+
+4. PSF is making Python available to Licensee on an "AS IS"
+basis.  PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
+IMPLIED.  BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND
+DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
+FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT
+INFRINGE ANY THIRD PARTY RIGHTS.
+
+5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON
+FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS
+A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON,
+OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
+
+6. This License Agreement will automatically terminate upon a material
+breach of its terms and conditions.
+
+7. Nothing in this License Agreement shall be deemed to create any
+relationship of agency, partnership, or joint venture between PSF and
+Licensee.  This License Agreement does not grant permission to use PSF
+trademarks or trade name in a trademark sense to endorse or promote
+products or services of Licensee, or any third party.
+
+8. By copying, installing or otherwise using Python, Licensee
+agrees to be bound by the terms and conditions of this License
+Agreement.
diff --git a/MANIFEST.in b/MANIFEST.in
new file mode 100644
index 0000000..5faa125
--- /dev/null
+++ b/MANIFEST.in
@@ -0,0 +1,2 @@
+recursive-include ast27 *.h
+recursive-include ast35 *.h
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..2bc27e5
--- /dev/null
+++ b/README.md
@@ -0,0 +1,52 @@
+# Typed AST Package
+This package is a fork of the CPython 2.7 and 3.5 `ast` modules with the ability
+to parse [PEP 484](https://www.python.org/dev/peps/pep-0484/) type comments.
+The primary goals of this package are correctness and speed.  This package is
+compatible with Python 3.3 - 3.5.
+
+### Current Caveats for Use
+- Type comments in invalid locations produce syntax errors.
+- When using per-argument function comment annotations, the type comments must
+  come after the argument-separating comma.
+
+## Development Notes
+### General Notes
+- token names in `Python.asdl` need to match token names both in `tokenizer.c`
+  AND in `pgen`'s copy of `tokenizer.c`.
+
+### Rebuilding Autogenerated Files
+- After changing `Parser/Python.asdl`, you must run:
+ - `python3 Parser/asdl_c.py -h Include/ Parser/Python.asdl`
+ - `python3 Parser/asdl_c.py -c Python/ Parser/Python.asdl`
+- After changing `Grammar/Grammar`, you must run:
+  - `pgen Grammar/Grammar Include/graminit.h Python/graminit.c`
+- To get a working `pgen` binary: (this is hacky and will be changed)
+ - get a clean copy of Python 3.5.1
+ - overwrite `Include/token.h`, `Include/compile.h`, and `Parser/tokenizer.c`
+  - (or instead of copying Parser/tokenizer.h just modify _PyParser_TokenNames at the top and tokenization to RARROW)
+ with the versions from typed\_ast
+ - In the Python directory, run: `./configure && make`
+ - `Parser/pgen` (in the Python directory) can now be used to regenerate
+ typed\_ast's graminit files.
+
+### TODO
+- [x] stop aliasing the official Python headers
+- [x] ensure we're not using duplicate versions of important standard library
+  functions (like object creation)
+- [x] hide most global symbols from being exported to prevent conflicts with other
+  libraries -- *changed to a unique prefix*
+- [x] allow type ignores to be followed by a comment
+- [ ] prevent type comments in incorrect locations from causing syntax errors
+- [ ] find a better way to compile pgen
+- [x] parse Python 2.7 ASTs
+- [x] ast35: ensure compatibility with older Python versions
+ - [x] Python 3.4 (*works on 3.4.4*)
+ - [x] Python 3.3 (*works on 3.3.6*)
+- [x] ast27: ensure compatibility with older Python versions
+ - [x] Python 3.4
+ - [x] Python 3.3
+- [ ] refactor out shared code
+	- [ ] common functions in typed\_ast.c
+	- [ ] type\_ignore array resizing functions in parsetok.c
+	- [ ] type comment parsing code in tokenizer.c
+	- [ ] func\_type\_input parsing in ast.c
diff --git a/appveyor.yml b/appveyor.yml
new file mode 100644
index 0000000..38e45c6
--- /dev/null
+++ b/appveyor.yml
@@ -0,0 +1,47 @@
+environment:
+
+  matrix:
+
+    # For Python versions available on Appveyor, see
+    # http://www.appveyor.com/docs/installed-software#python
+
+    - PYTHON: "C:\\Python33"
+    - PYTHON: "C:\\Python34"
+    - PYTHON: "C:\\Python35"
+    - PYTHON: "C:\\Python33-x64"
+      DISTUTILS_USE_SDK: "1"
+    - PYTHON: "C:\\Python34-x64"
+      DISTUTILS_USE_SDK: "1"
+    - PYTHON: "C:\\Python35-x64"
+
+install:
+  # We need wheel installed to build wheels
+  - "%PYTHON%\\python.exe -m pip install wheel"
+
+build: off
+
+test_script:
+  # Put your test command here.
+  # If you don't need to build C extensions on 64-bit Python 3.3 or 3.4,
+  # you can remove "build.cmd" from the front of the command, as it's
+  # only needed to support those cases.
+  # Note that you must use the environment variable %PYTHON% to refer to
+  # the interpreter you're using - Appveyor does not do anything special
+  # to put the Python evrsion you want to use on PATH.
+  - "build.cmd %PYTHON%\\python.exe setup.py test"
+
+after_test:
+  # This step builds your wheels.
+  # Again, you only need build.cmd if you're building C extensions for
+  # 64-bit Python 3.3/3.4. And you need to use %PYTHON% to get the correct
+  # interpreter
+  - "build.cmd %PYTHON%\\python.exe setup.py bdist_wheel"
+
+artifacts:
+  # bdist_wheel puts your built wheel in the dist directory
+  - path: dist\*
+
+#on_success:
+#  You can use this step to upload your artifacts to a public website.
+#  See Appveyor's documentation for more details. Or you can simply
+#  access your wheels from the Appveyor "artifacts" tab for your build.
diff --git a/ast27/Custom/typed_ast.c b/ast27/Custom/typed_ast.c
new file mode 100644
index 0000000..df130ff
--- /dev/null
+++ b/ast27/Custom/typed_ast.c
@@ -0,0 +1,313 @@
+#include "Python.h"
+#include "Python-ast.h"
+#include "compile.h"
+#include "node.h"
+#include "grammar.h"
+#include "token.h"
+#include "ast.h"
+#include "parsetok.h"
+#include "errcode.h"
+
+extern grammar _Ta27Parser_Grammar; /* from graminit.c */
+
+// from Python/bltinmodule.c
+static const char *
+source_as_string(PyObject *cmd, const char *funcname, const char *what, PyCompilerFlags *cf, PyObject **cmd_copy)
+{
+    const char *str;
+    Py_ssize_t size;
+    Py_buffer view;
+
+    *cmd_copy = NULL;
+    if (PyUnicode_Check(cmd)) {
+        cf->cf_flags |= PyCF_IGNORE_COOKIE;
+        str = PyUnicode_AsUTF8AndSize(cmd, &size);
+        if (str == NULL)
+            return NULL;
+    }
+    else if (PyBytes_Check(cmd)) {
+        str = PyBytes_AS_STRING(cmd);
+        size = PyBytes_GET_SIZE(cmd);
+    }
+    else if (PyByteArray_Check(cmd)) {
+        str = PyByteArray_AS_STRING(cmd);
+        size = PyByteArray_GET_SIZE(cmd);
+    }
+    else if (PyObject_GetBuffer(cmd, &view, PyBUF_SIMPLE) == 0) {
+        /* Copy to NUL-terminated buffer. */
+        *cmd_copy = PyBytes_FromStringAndSize(
+            (const char *)view.buf, view.len);
+        PyBuffer_Release(&view);
+        if (*cmd_copy == NULL) {
+            return NULL;
+        }
+        str = PyBytes_AS_STRING(*cmd_copy);
+        size = PyBytes_GET_SIZE(*cmd_copy);
+    }
+    else {
+        PyErr_Format(PyExc_TypeError,
+          "%s() arg 1 must be a %s object",
+          funcname, what);
+        return NULL;
+    }
+
+    if (strlen(str) != (size_t)size) {
+        PyErr_SetString(PyExc_ValueError,
+                        "source code string cannot contain null bytes");
+        Py_CLEAR(*cmd_copy);
+        return NULL;
+    }
+    return str;
+}
+
+// from Python/pythonrun.c
+/* compute parser flags based on compiler flags */
+static int PARSER_FLAGS(PyCompilerFlags *flags)
+{
+    int parser_flags = 0;
+    if (!flags)
+        return 0;
+    if (flags->cf_flags & PyCF_DONT_IMPLY_DEDENT)
+        parser_flags |= PyPARSE_DONT_IMPLY_DEDENT;
+    if (flags->cf_flags & PyCF_IGNORE_COOKIE)
+        parser_flags |= PyPARSE_IGNORE_COOKIE;
+    return parser_flags;
+}
+
+// from Python/pythonrun.c
+/* Set the error appropriate to the given input error code (see errcode.h) */
+static void
+err_input(perrdetail *err)
+{
+    PyObject *v, *w, *errtype, *errtext;
+    PyObject *msg_obj = NULL;
+    char *msg = NULL;
+    int offset = err->offset;
+
+    errtype = PyExc_SyntaxError;
+    switch (err->error) {
+    case E_ERROR:
+        return;
+    case E_SYNTAX:
+        errtype = PyExc_IndentationError;
+        if (err->expected == INDENT)
+            msg = "expected an indented block";
+        else if (err->token == INDENT)
+            msg = "unexpected indent";
+        else if (err->token == DEDENT)
+            msg = "unexpected unindent";
+        else {
+            errtype = PyExc_SyntaxError;
+            if (err->token == TYPE_COMMENT)
+              msg = "misplaced type annotation";
+            else
+              msg = "invalid syntax";
+        }
+        break;
+    case E_TOKEN:
+        msg = "invalid token";
+        break;
+    case E_EOFS:
+        msg = "EOF while scanning triple-quoted string literal";
+        break;
+    case E_EOLS:
+        msg = "EOL while scanning string literal";
+        break;
+    case E_INTR:
+        if (!PyErr_Occurred())
+            PyErr_SetNone(PyExc_KeyboardInterrupt);
+        goto cleanup;
+    case E_NOMEM:
+        PyErr_NoMemory();
+        goto cleanup;
+    case E_EOF:
+        msg = "unexpected EOF while parsing";
+        break;
+    case E_TABSPACE:
+        errtype = PyExc_TabError;
+        msg = "inconsistent use of tabs and spaces in indentation";
+        break;
+    case E_OVERFLOW:
+        msg = "expression too long";
+        break;
+    case E_DEDENT:
+        errtype = PyExc_IndentationError;
+        msg = "unindent does not match any outer indentation level";
+        break;
+    case E_TOODEEP:
+        errtype = PyExc_IndentationError;
+        msg = "too many levels of indentation";
+        break;
+    case E_DECODE: {
+        PyObject *type, *value, *tb;
+        PyErr_Fetch(&type, &value, &tb);
+        msg = "unknown decode error";
+        if (value != NULL)
+            msg_obj = PyObject_Str(value);
+        Py_XDECREF(type);
+        Py_XDECREF(value);
+        Py_XDECREF(tb);
+        break;
+    }
+    case E_LINECONT:
+        msg = "unexpected character after line continuation character";
+        break;
+    default:
+        fprintf(stderr, "error=%d\n", err->error);
+        msg = "unknown parsing error";
+        break;
+    }
+    /* err->text may not be UTF-8 in case of decoding errors.
+       Explicitly convert to an object. */
+    if (!err->text) {
+        errtext = Py_None;
+        Py_INCREF(Py_None);
+    } else {
+        errtext = PyUnicode_DecodeUTF8(err->text, err->offset,
+                                       "replace");
+        if (errtext != NULL) {
+            Py_ssize_t len = strlen(err->text);
+            offset = (int)PyUnicode_GET_LENGTH(errtext);
+            if (len != err->offset) {
+                Py_DECREF(errtext);
+                errtext = PyUnicode_DecodeUTF8(err->text, len,
+                                               "replace");
+            }
+        }
+    }
+    v = Py_BuildValue("(OiiN)", err->filename,
+                      err->lineno, offset, errtext);
+    if (v != NULL) {
+        if (msg_obj)
+            w = Py_BuildValue("(OO)", msg_obj, v);
+        else
+            w = Py_BuildValue("(sO)", msg, v);
+    } else
+        w = NULL;
+    Py_XDECREF(v);
+    PyErr_SetObject(errtype, w);
+    Py_XDECREF(w);
+cleanup:
+    Py_XDECREF(msg_obj);
+    if (err->text != NULL) {
+        PyObject_FREE(err->text);
+        err->text = NULL;
+    }
+}
+
+// from Python/pythonrun.c
+static void
+err_free(perrdetail *err)
+{
+    Py_CLEAR(err->filename);
+}
+
+// copy of PyParser_ASTFromStringObject in Python/pythonrun.c
+/* Preferred access to parser is through AST. */
+static mod_ty
+string_object_to_c_ast(const char *s, PyObject *filename, int start,
+                             PyCompilerFlags *flags, PyArena *arena)
+{
+    mod_ty mod;
+    PyCompilerFlags localflags;
+    perrdetail err;
+    int iflags = PARSER_FLAGS(flags);
+
+    node *n = Ta27Parser_ParseStringObject(s, filename,
+                                         &_Ta27Parser_Grammar, start, &err,
+                                         &iflags);
+    if (flags == NULL) {
+        localflags.cf_flags = 0;
+        flags = &localflags;
+    }
+    if (n) {
+        flags->cf_flags |= iflags & PyCF_MASK;
+        mod = Ta27AST_FromNode(n, flags, PyUnicode_AsUTF8(filename), arena);
+        Ta27Node_Free(n);
+    }
+    else {
+        err_input(&err);
+        mod = NULL;
+    }
+    err_free(&err);
+    return mod;
+}
+
+// adapted from Py_CompileStringObject in Python/pythonrun.c
+static PyObject *
+string_object_to_py_ast(const char *str, PyObject *filename, int start,
+                       PyCompilerFlags *flags)
+{
+    mod_ty mod;
+    PyArena *arena = PyArena_New();
+    if (arena == NULL)
+        return NULL;
+
+    mod = string_object_to_c_ast(str, filename, start, flags, arena);
+    if (mod == NULL) {
+        PyArena_Free(arena);
+        return NULL;
+    }
+
+    PyObject *result = Ta27AST_mod2obj(mod);
+    PyArena_Free(arena);
+    return result;
+}
+
+// adapted from builtin_compile_impl in Python/bltinmodule.c
+static PyObject *
+ast27_parse_impl(PyObject *source,
+                 PyObject *filename, const char *mode)
+{
+    PyObject *source_copy;
+    const char *str;
+    int compile_mode = -1;
+    PyCompilerFlags cf;
+    int start[] = {Py_file_input, Py_eval_input, Py_single_input /*, Py_func_type_input */};
+    PyObject *result;
+
+    cf.cf_flags = PyCF_ONLY_AST | PyCF_SOURCE_IS_UTF8;
+
+    if (strcmp(mode, "exec") == 0)
+        compile_mode = 0;
+    else if (strcmp(mode, "eval") == 0)
+        compile_mode = 1;
+    else if (strcmp(mode, "single") == 0)
+        compile_mode = 2;
+    else if (strcmp(mode, "func_type") == 0)
+        compile_mode = 3;
+    else {
+        PyErr_SetString(PyExc_ValueError,
+                        "parse() mode must be 'exec', 'eval', 'single', for 'func_type'");
+        goto error;
+    }
+
+    str = source_as_string(source, "parse", "string or bytes", &cf, &source_copy);
+    if (str == NULL)
+        goto error;
+
+    result = string_object_to_py_ast(str, filename, start[compile_mode], &cf);
+    Py_XDECREF(source_copy);
+    goto finally;
+
+error:
+    result = NULL;
+finally:
+    Py_DECREF(filename);
+    return result;
+}
+
+// adapted from builtin_compile in Python/clinic/bltinmodule.c.h
+PyObject *
+ast27_parse(PyObject *self, PyObject *args)
+{
+    PyObject *return_value = NULL;
+    PyObject *source;
+    PyObject *filename;
+    const char *mode;
+
+    if (PyArg_ParseTuple(args, "OO&s:parse", &source, PyUnicode_FSDecoder, &filename, &mode))
+        return_value = ast27_parse_impl(source, filename, mode);
+
+    return return_value;
+}
diff --git a/ast27/Grammar/Grammar b/ast27/Grammar/Grammar
new file mode 100644
index 0000000..60dbf50
--- /dev/null
+++ b/ast27/Grammar/Grammar
@@ -0,0 +1,151 @@
+# Grammar for Python
+
+# Note:  Changing the grammar specified in this file will most likely
+#        require corresponding changes in the parser module
+#        (../Modules/parsermodule.c).  If you can't make the changes to
+#        that module yourself, please co-ordinate the required changes
+#        with someone who can; ask around on python-dev for help.  Fred
+#        Drake <fdrake at acm.org> will probably be listening there.
+
+# NOTE WELL: You should also follow all the steps listed in PEP 306,
+# "How to Change Python's Grammar"
+
+# Start symbols for the grammar:
+#       single_input is a single interactive statement;
+#       file_input is a module or sequence of commands read from an input file;
+#       eval_input is the input for the eval() and input() functions.
+#       func_type_input is a PEP 484 Python 2 function type comment
+# NB: compound_stmt in single_input is followed by extra NEWLINE!
+single_input: NEWLINE | simple_stmt | compound_stmt NEWLINE
+file_input: (NEWLINE | stmt)* ENDMARKER
+eval_input: testlist NEWLINE* ENDMARKER
+
+decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE
+decorators: decorator+
+decorated: decorators (classdef | funcdef)
+funcdef: 'def' NAME parameters ':' [TYPE_COMMENT] suite
+parameters: '(' [varargslist] ')'
+varargslist: ((fpdef ['=' test] ',' [TYPE_COMMENT])*
+              ('*' NAME [',' [TYPE_COMMENT]  '**' NAME] [TYPE_COMMENT] | '**' NAME [TYPE_COMMENT]) |
+              fpdef ['=' test] (',' [TYPE_COMMENT] fpdef ['=' test])* [','] [TYPE_COMMENT])
+fpdef: NAME | '(' fplist ')'
+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 (yield_expr|testlist) |
+                     ('=' (yield_expr|testlist))* [TYPE_COMMENT])
+augassign: ('+=' | '-=' | '*=' | '/=' | '%=' | '&=' | '|=' | '^=' |
+            '<<=' | '>>=' | '**=' | '//=')
+# For normal assignments, additional restrictions enforced by the interpreter
+print_stmt: 'print' ( [ test (',' test)* [','] ] |
+                      '>>' test [ (',' test)+ [','] ] )
+del_stmt: 'del' exprlist
+pass_stmt: 'pass'
+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_expr
+raise_stmt: 'raise' [test [',' test [',' test]]]
+import_stmt: import_name | import_from
+import_name: 'import' dotted_as_names
+import_from: ('from' ('.'* dotted_name | '.'+)
+              'import' ('*' | '(' import_as_names ')' | import_as_names))
+import_as_name: NAME ['as' NAME]
+dotted_as_name: dotted_name ['as' NAME]
+import_as_names: import_as_name (',' import_as_name)* [',']
+dotted_as_names: dotted_as_name (',' dotted_as_name)*
+dotted_name: NAME ('.' NAME)*
+global_stmt: 'global' NAME (',' NAME)*
+exec_stmt: 'exec' expr ['in' test [',' test]]
+assert_stmt: 'assert' test [',' test]
+
+compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt | with_stmt | funcdef | classdef | decorated
+if_stmt: 'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite]
+while_stmt: 'while' test ':' suite ['else' ':' suite]
+for_stmt: 'for' exprlist 'in' testlist ':' [TYPE_COMMENT] suite ['else' ':' suite]
+try_stmt: ('try' ':' suite
+           ((except_clause ':' suite)+
+            ['else' ':' suite]
+            ['finally' ':' suite] |
+           'finally' ':' suite))
+with_stmt: 'with' with_item (',' with_item)*  ':' [TYPE_COMMENT] suite
+with_item: test ['as' expr]
+# NB compile.c makes sure that the default except clause is last
+except_clause: 'except' [test [('as' | ',') test]]
+# the TYPE_COMMENT in suites is only parsed for funcdefs, but can't go elsewhere due to ambiguity
+suite: simple_stmt | NEWLINE [TYPE_COMMENT NEWLINE] INDENT stmt+ DEDENT
+
+# Backward compatibility cruft to support:
+# [ x for x in lambda: True, lambda: False if x() ]
+# even while also allowing:
+# lambda x: 5 if x else 2
+# (But not a mix of the two)
+testlist_safe: old_test [(',' old_test)+ [',']]
+old_test: or_test | old_lambdef
+old_lambdef: 'lambda' [varargslist] ':' old_test
+
+test: or_test ['if' or_test 'else' test] | lambdef
+or_test: and_test ('or' and_test)*
+and_test: not_test ('and' not_test)*
+not_test: 'not' not_test | comparison
+comparison: expr (comp_op expr)*
+comp_op: '<'|'>'|'=='|'>='|'<='|'<>'|'!='|'in'|'not' 'in'|'is'|'is' 'not'
+expr: xor_expr ('|' xor_expr)*
+xor_expr: and_expr ('^' and_expr)*
+and_expr: shift_expr ('&' shift_expr)*
+shift_expr: arith_expr (('<<'|'>>') arith_expr)*
+arith_expr: term (('+'|'-') term)*
+term: factor (('*'|'/'|'%'|'//') factor)*
+factor: ('+'|'-'|'~') factor | power
+power: atom trailer* ['**' factor]
+atom: ('(' [yield_expr|testlist_comp] ')' |
+       '[' [listmaker] ']' |
+       '{' [dictorsetmaker] '}' |
+       '`' testlist1 '`' |
+       NAME | NUMBER | STRING+)
+listmaker: test ( list_for | (',' test)* [','] )
+testlist_comp: test ( comp_for | (',' test)* [','] )
+lambdef: 'lambda' [varargslist] ':' test
+trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME
+subscriptlist: subscript (',' subscript)* [',']
+subscript: '.' '.' '.' | test | [test] ':' [test] [sliceop]
+sliceop: ':' [test]
+exprlist: expr (',' expr)* [',']
+testlist: test (',' test)* [',']
+dictorsetmaker: ( (test ':' test (comp_for | (',' test ':' test)* [','])) |
+                  (test (comp_for | (',' test)* [','])) )
+
+classdef: 'class' NAME ['(' [testlist] ')'] ':' suite
+
+arglist: (argument ',')* (argument [',']
+                         |'*' test (',' argument)* [',' '**' test] 
+                         |'**' test)
+# The reason that keywords are test nodes instead of NAME is that using NAME
+# results in an ambiguity. ast.c makes sure it's a NAME.
+argument: test [comp_for] | test '=' test
+
+list_iter: list_for | list_if
+list_for: 'for' exprlist 'in' testlist_safe [list_iter]
+list_if: 'if' old_test [list_iter]
+
+comp_iter: comp_for | comp_if
+comp_for: 'for' exprlist 'in' or_test [comp_iter]
+comp_if: 'if' old_test [comp_iter]
+
+testlist1: test (',' test)*
+
+# not used in grammar, but may appear in "node" passed from Parser to Compiler
+encoding_decl: NAME
+
+yield_expr: 'yield' [testlist]
+
+func_type_input: func_type NEWLINE* ENDMARKER
+func_type: '(' [typelist] ')' '->' test
+# typelist is a modified typedargslist (see above)
+typelist: (test (',' test)* [','
+       ['*' [test] (',' test)* [',' '**' test] | '**' test]]
+     |  '*' [test] (',' test)* [',' '**' test] | '**' test)
diff --git a/ast27/Include/Python-ast.h b/ast27/Include/Python-ast.h
new file mode 100644
index 0000000..9ff258e
--- /dev/null
+++ b/ast27/Include/Python-ast.h
@@ -0,0 +1,547 @@
+/* File automatically generated by Parser/asdl_c.py. */
+
+#include "asdl.h"
+
+typedef struct _mod *mod_ty;
+
+typedef struct _stmt *stmt_ty;
+
+typedef struct _expr *expr_ty;
+
+typedef enum _expr_context { Load=1, Store=2, Del=3, AugLoad=4, AugStore=5, Param=6 }
+                             expr_context_ty;
+
+typedef struct _slice *slice_ty;
+
+typedef enum _boolop { And=1, Or=2 } boolop_ty;
+
+typedef enum _operator { Add=1, Sub=2, Mult=3, Div=4, Mod=5, Pow=6, LShift=7, RShift=8, BitOr=9,
+                         BitXor=10, BitAnd=11, FloorDiv=12 } operator_ty;
+
+typedef enum _unaryop { Invert=1, Not=2, UAdd=3, USub=4 } unaryop_ty;
+
+typedef enum _cmpop { Eq=1, NotEq=2, Lt=3, LtE=4, Gt=5, GtE=6, Is=7, IsNot=8, In=9, NotIn=10 }
+                      cmpop_ty;
+
+typedef struct _comprehension *comprehension_ty;
+
+typedef struct _excepthandler *excepthandler_ty;
+
+typedef struct _arguments *arguments_ty;
+
+typedef struct _keyword *keyword_ty;
+
+typedef struct _alias *alias_ty;
+
+typedef struct _type_ignore *type_ignore_ty;
+
+
+enum _mod_kind {Module_kind=1, Interactive_kind=2, Expression_kind=3, FunctionType_kind=4,
+                 Suite_kind=5};
+struct _mod {
+        enum _mod_kind kind;
+        union {
+                struct {
+                        asdl_seq *body;
+                        asdl_seq *type_ignores;
+                } Module;
+                
+                struct {
+                        asdl_seq *body;
+                } Interactive;
+                
+                struct {
+                        expr_ty body;
+                } Expression;
+                
+                struct {
+                        asdl_seq *argtypes;
+                        expr_ty returns;
+                } FunctionType;
+                
+                struct {
+                        asdl_seq *body;
+                } Suite;
+                
+        } v;
+};
+
+enum _stmt_kind {FunctionDef_kind=1, ClassDef_kind=2, Return_kind=3, Delete_kind=4, Assign_kind=5,
+                  AugAssign_kind=6, Print_kind=7, For_kind=8, While_kind=9, If_kind=10,
+                  With_kind=11, Raise_kind=12, TryExcept_kind=13, TryFinally_kind=14,
+                  Assert_kind=15, Import_kind=16, ImportFrom_kind=17, Exec_kind=18, Global_kind=19,
+                  Expr_kind=20, Pass_kind=21, Break_kind=22, Continue_kind=23};
+struct _stmt {
+        enum _stmt_kind kind;
+        union {
+                struct {
+                        identifier name;
+                        arguments_ty args;
+                        asdl_seq *body;
+                        asdl_seq *decorator_list;
+                        string type_comment;
+                } FunctionDef;
+                
+                struct {
+                        identifier name;
+                        asdl_seq *bases;
+                        asdl_seq *body;
+                        asdl_seq *decorator_list;
+                } ClassDef;
+                
+                struct {
+                        expr_ty value;
+                } Return;
+                
+                struct {
+                        asdl_seq *targets;
+                } Delete;
+                
+                struct {
+                        asdl_seq *targets;
+                        expr_ty value;
+                        string type_comment;
+                } Assign;
+                
+                struct {
+                        expr_ty target;
+                        operator_ty op;
+                        expr_ty value;
+                } AugAssign;
+                
+                struct {
+                        expr_ty dest;
+                        asdl_seq *values;
+                        bool nl;
+                } Print;
+                
+                struct {
+                        expr_ty target;
+                        expr_ty iter;
+                        asdl_seq *body;
+                        asdl_seq *orelse;
+                        string type_comment;
+                } For;
+                
+                struct {
+                        expr_ty test;
+                        asdl_seq *body;
+                        asdl_seq *orelse;
+                } While;
+                
+                struct {
+                        expr_ty test;
+                        asdl_seq *body;
+                        asdl_seq *orelse;
+                } If;
+                
+                struct {
+                        expr_ty context_expr;
+                        expr_ty optional_vars;
+                        asdl_seq *body;
+                        string type_comment;
+                } With;
+                
+                struct {
+                        expr_ty type;
+                        expr_ty inst;
+                        expr_ty tback;
+                } Raise;
+                
+                struct {
+                        asdl_seq *body;
+                        asdl_seq *handlers;
+                        asdl_seq *orelse;
+                } TryExcept;
+                
+                struct {
+                        asdl_seq *body;
+                        asdl_seq *finalbody;
+                } TryFinally;
+                
+                struct {
+                        expr_ty test;
+                        expr_ty msg;
+                } Assert;
+                
+                struct {
+                        asdl_seq *names;
+                } Import;
+                
+                struct {
+                        identifier module;
+                        asdl_seq *names;
+                        int level;
+                } ImportFrom;
+                
+                struct {
+                        expr_ty body;
+                        expr_ty globals;
+                        expr_ty locals;
+                } Exec;
+                
+                struct {
+                        asdl_seq *names;
+                } Global;
+                
+                struct {
+                        expr_ty value;
+                } Expr;
+                
+        } v;
+        int lineno;
+        int col_offset;
+};
+
+enum _expr_kind {BoolOp_kind=1, BinOp_kind=2, UnaryOp_kind=3, Lambda_kind=4, IfExp_kind=5,
+                  Dict_kind=6, Set_kind=7, ListComp_kind=8, SetComp_kind=9, DictComp_kind=10,
+                  GeneratorExp_kind=11, Yield_kind=12, Compare_kind=13, Call_kind=14, Repr_kind=15,
+                  Num_kind=16, Str_kind=17, Attribute_kind=18, Subscript_kind=19, Name_kind=20,
+                  List_kind=21, Tuple_kind=22};
+struct _expr {
+        enum _expr_kind kind;
+        union {
+                struct {
+                        boolop_ty op;
+                        asdl_seq *values;
+                } BoolOp;
+                
+                struct {
+                        expr_ty left;
+                        operator_ty op;
+                        expr_ty right;
+                } BinOp;
+                
+                struct {
+                        unaryop_ty op;
+                        expr_ty operand;
+                } UnaryOp;
+                
+                struct {
+                        arguments_ty args;
+                        expr_ty body;
+                } Lambda;
+                
+                struct {
+                        expr_ty test;
+                        expr_ty body;
+                        expr_ty orelse;
+                } IfExp;
+                
+                struct {
+                        asdl_seq *keys;
+                        asdl_seq *values;
+                } Dict;
+                
+                struct {
+                        asdl_seq *elts;
+                } Set;
+                
+                struct {
+                        expr_ty elt;
+                        asdl_seq *generators;
+                } ListComp;
+                
+                struct {
+                        expr_ty elt;
+                        asdl_seq *generators;
+                } SetComp;
+                
+                struct {
+                        expr_ty key;
+                        expr_ty value;
+                        asdl_seq *generators;
+                } DictComp;
+                
+                struct {
+                        expr_ty elt;
+                        asdl_seq *generators;
+                } GeneratorExp;
+                
+                struct {
+                        expr_ty value;
+                } Yield;
+                
+                struct {
+                        expr_ty left;
+                        asdl_int_seq *ops;
+                        asdl_seq *comparators;
+                } Compare;
+                
+                struct {
+                        expr_ty func;
+                        asdl_seq *args;
+                        asdl_seq *keywords;
+                        expr_ty starargs;
+                        expr_ty kwargs;
+                } Call;
+                
+                struct {
+                        expr_ty value;
+                } Repr;
+                
+                struct {
+                        object n;
+                } Num;
+                
+                struct {
+                        string s;
+                } Str;
+                
+                struct {
+                        expr_ty value;
+                        identifier attr;
+                        expr_context_ty ctx;
+                } Attribute;
+                
+                struct {
+                        expr_ty value;
+                        slice_ty slice;
+                        expr_context_ty ctx;
+                } Subscript;
+                
+                struct {
+                        identifier id;
+                        expr_context_ty ctx;
+                } Name;
+                
+                struct {
+                        asdl_seq *elts;
+                        expr_context_ty ctx;
+                } List;
+                
+                struct {
+                        asdl_seq *elts;
+                        expr_context_ty ctx;
+                } Tuple;
+                
+        } v;
+        int lineno;
+        int col_offset;
+};
+
+enum _slice_kind {Ellipsis_kind=1, Slice_kind=2, ExtSlice_kind=3, Index_kind=4};
+struct _slice {
+        enum _slice_kind kind;
+        union {
+                struct {
+                        expr_ty lower;
+                        expr_ty upper;
+                        expr_ty step;
+                } Slice;
+                
+                struct {
+                        asdl_seq *dims;
+                } ExtSlice;
+                
+                struct {
+                        expr_ty value;
+                } Index;
+                
+        } v;
+};
+
+struct _comprehension {
+        expr_ty target;
+        expr_ty iter;
+        asdl_seq *ifs;
+};
+
+enum _excepthandler_kind {ExceptHandler_kind=1};
+struct _excepthandler {
+        enum _excepthandler_kind kind;
+        union {
+                struct {
+                        expr_ty type;
+                        expr_ty name;
+                        asdl_seq *body;
+                } ExceptHandler;
+                
+        } v;
+        int lineno;
+        int col_offset;
+};
+
+struct _arguments {
+        asdl_seq *args;
+        identifier vararg;
+        identifier kwarg;
+        asdl_seq *defaults;
+        asdl_seq *type_comments;
+};
+
+struct _keyword {
+        identifier arg;
+        expr_ty value;
+};
+
+struct _alias {
+        identifier name;
+        identifier asname;
+};
+
+enum _type_ignore_kind {TypeIgnore_kind=1};
+struct _type_ignore {
+        enum _type_ignore_kind kind;
+        union {
+                struct {
+                        int lineno;
+                } TypeIgnore;
+                
+        } v;
+};
+
+
+#define Module(a0, a1, a2) _Ta27_Module(a0, a1, a2)
+mod_ty _Ta27_Module(asdl_seq * body, asdl_seq * type_ignores, PyArena *arena);
+#define Interactive(a0, a1) _Ta27_Interactive(a0, a1)
+mod_ty _Ta27_Interactive(asdl_seq * body, PyArena *arena);
+#define Expression(a0, a1) _Ta27_Expression(a0, a1)
+mod_ty _Ta27_Expression(expr_ty body, PyArena *arena);
+#define FunctionType(a0, a1, a2) _Ta27_FunctionType(a0, a1, a2)
+mod_ty _Ta27_FunctionType(asdl_seq * argtypes, expr_ty returns, PyArena *arena);
+#define Suite(a0, a1) _Ta27_Suite(a0, a1)
+mod_ty _Ta27_Suite(asdl_seq * body, PyArena *arena);
+#define FunctionDef(a0, a1, a2, a3, a4, a5, a6, a7) _Ta27_FunctionDef(a0, a1, a2, a3, a4, a5, a6, a7)
+stmt_ty _Ta27_FunctionDef(identifier name, arguments_ty args, asdl_seq * body, asdl_seq *
+                          decorator_list, string type_comment, int lineno, int col_offset, PyArena
+                          *arena);
+#define ClassDef(a0, a1, a2, a3, a4, a5, a6) _Ta27_ClassDef(a0, a1, a2, a3, a4, a5, a6)
+stmt_ty _Ta27_ClassDef(identifier name, asdl_seq * bases, asdl_seq * body, asdl_seq *
+                       decorator_list, int lineno, int col_offset, PyArena *arena);
+#define Return(a0, a1, a2, a3) _Ta27_Return(a0, a1, a2, a3)
+stmt_ty _Ta27_Return(expr_ty value, int lineno, int col_offset, PyArena *arena);
+#define Delete(a0, a1, a2, a3) _Ta27_Delete(a0, a1, a2, a3)
+stmt_ty _Ta27_Delete(asdl_seq * targets, int lineno, int col_offset, PyArena *arena);
+#define Assign(a0, a1, a2, a3, a4, a5) _Ta27_Assign(a0, a1, a2, a3, a4, a5)
+stmt_ty _Ta27_Assign(asdl_seq * targets, expr_ty value, string type_comment, int lineno, int
+                     col_offset, PyArena *arena);
+#define AugAssign(a0, a1, a2, a3, a4, a5) _Ta27_AugAssign(a0, a1, a2, a3, a4, a5)
+stmt_ty _Ta27_AugAssign(expr_ty target, operator_ty op, expr_ty value, int lineno, int col_offset,
+                        PyArena *arena);
+#define Print(a0, a1, a2, a3, a4, a5) _Ta27_Print(a0, a1, a2, a3, a4, a5)
+stmt_ty _Ta27_Print(expr_ty dest, asdl_seq * values, bool nl, int lineno, int col_offset, PyArena
+                    *arena);
+#define For(a0, a1, a2, a3, a4, a5, a6, a7) _Ta27_For(a0, a1, a2, a3, a4, a5, a6, a7)
+stmt_ty _Ta27_For(expr_ty target, expr_ty iter, asdl_seq * body, asdl_seq * orelse, string
+                  type_comment, int lineno, int col_offset, PyArena *arena);
+#define While(a0, a1, a2, a3, a4, a5) _Ta27_While(a0, a1, a2, a3, a4, a5)
+stmt_ty _Ta27_While(expr_ty test, asdl_seq * body, asdl_seq * orelse, int lineno, int col_offset,
+                    PyArena *arena);
+#define If(a0, a1, a2, a3, a4, a5) _Ta27_If(a0, a1, a2, a3, a4, a5)
+stmt_ty _Ta27_If(expr_ty test, asdl_seq * body, asdl_seq * orelse, int lineno, int col_offset,
+                 PyArena *arena);
+#define With(a0, a1, a2, a3, a4, a5, a6) _Ta27_With(a0, a1, a2, a3, a4, a5, a6)
+stmt_ty _Ta27_With(expr_ty context_expr, expr_ty optional_vars, asdl_seq * body, string
+                   type_comment, int lineno, int col_offset, PyArena *arena);
+#define Raise(a0, a1, a2, a3, a4, a5) _Ta27_Raise(a0, a1, a2, a3, a4, a5)
+stmt_ty _Ta27_Raise(expr_ty type, expr_ty inst, expr_ty tback, int lineno, int col_offset, PyArena
+                    *arena);
+#define TryExcept(a0, a1, a2, a3, a4, a5) _Ta27_TryExcept(a0, a1, a2, a3, a4, a5)
+stmt_ty _Ta27_TryExcept(asdl_seq * body, asdl_seq * handlers, asdl_seq * orelse, int lineno, int
+                        col_offset, PyArena *arena);
+#define TryFinally(a0, a1, a2, a3, a4) _Ta27_TryFinally(a0, a1, a2, a3, a4)
+stmt_ty _Ta27_TryFinally(asdl_seq * body, asdl_seq * finalbody, int lineno, int col_offset, PyArena
+                         *arena);
+#define Assert(a0, a1, a2, a3, a4) _Ta27_Assert(a0, a1, a2, a3, a4)
+stmt_ty _Ta27_Assert(expr_ty test, expr_ty msg, int lineno, int col_offset, PyArena *arena);
+#define Import(a0, a1, a2, a3) _Ta27_Import(a0, a1, a2, a3)
+stmt_ty _Ta27_Import(asdl_seq * names, int lineno, int col_offset, PyArena *arena);
+#define ImportFrom(a0, a1, a2, a3, a4, a5) _Ta27_ImportFrom(a0, a1, a2, a3, a4, a5)
+stmt_ty _Ta27_ImportFrom(identifier module, asdl_seq * names, int level, int lineno, int
+                         col_offset, PyArena *arena);
+#define Exec(a0, a1, a2, a3, a4, a5) _Ta27_Exec(a0, a1, a2, a3, a4, a5)
+stmt_ty _Ta27_Exec(expr_ty body, expr_ty globals, expr_ty locals, int lineno, int col_offset,
+                   PyArena *arena);
+#define Global(a0, a1, a2, a3) _Ta27_Global(a0, a1, a2, a3)
+stmt_ty _Ta27_Global(asdl_seq * names, int lineno, int col_offset, PyArena *arena);
+#define Expr(a0, a1, a2, a3) _Ta27_Expr(a0, a1, a2, a3)
+stmt_ty _Ta27_Expr(expr_ty value, int lineno, int col_offset, PyArena *arena);
+#define Pass(a0, a1, a2) _Ta27_Pass(a0, a1, a2)
+stmt_ty _Ta27_Pass(int lineno, int col_offset, PyArena *arena);
+#define Break(a0, a1, a2) _Ta27_Break(a0, a1, a2)
+stmt_ty _Ta27_Break(int lineno, int col_offset, PyArena *arena);
+#define Continue(a0, a1, a2) _Ta27_Continue(a0, a1, a2)
+stmt_ty _Ta27_Continue(int lineno, int col_offset, PyArena *arena);
+#define BoolOp(a0, a1, a2, a3, a4) _Ta27_BoolOp(a0, a1, a2, a3, a4)
+expr_ty _Ta27_BoolOp(boolop_ty op, asdl_seq * values, int lineno, int col_offset, PyArena *arena);
+#define BinOp(a0, a1, a2, a3, a4, a5) _Ta27_BinOp(a0, a1, a2, a3, a4, a5)
+expr_ty _Ta27_BinOp(expr_ty left, operator_ty op, expr_ty right, int lineno, int col_offset,
+                    PyArena *arena);
+#define UnaryOp(a0, a1, a2, a3, a4) _Ta27_UnaryOp(a0, a1, a2, a3, a4)
+expr_ty _Ta27_UnaryOp(unaryop_ty op, expr_ty operand, int lineno, int col_offset, PyArena *arena);
+#define Lambda(a0, a1, a2, a3, a4) _Ta27_Lambda(a0, a1, a2, a3, a4)
+expr_ty _Ta27_Lambda(arguments_ty args, expr_ty body, int lineno, int col_offset, PyArena *arena);
+#define IfExp(a0, a1, a2, a3, a4, a5) _Ta27_IfExp(a0, a1, a2, a3, a4, a5)
+expr_ty _Ta27_IfExp(expr_ty test, expr_ty body, expr_ty orelse, int lineno, int col_offset, PyArena
+                    *arena);
+#define Dict(a0, a1, a2, a3, a4) _Ta27_Dict(a0, a1, a2, a3, a4)
+expr_ty _Ta27_Dict(asdl_seq * keys, asdl_seq * values, int lineno, int col_offset, PyArena *arena);
+#define Set(a0, a1, a2, a3) _Ta27_Set(a0, a1, a2, a3)
+expr_ty _Ta27_Set(asdl_seq * elts, int lineno, int col_offset, PyArena *arena);
+#define ListComp(a0, a1, a2, a3, a4) _Ta27_ListComp(a0, a1, a2, a3, a4)
+expr_ty _Ta27_ListComp(expr_ty elt, asdl_seq * generators, int lineno, int col_offset, PyArena
+                       *arena);
+#define SetComp(a0, a1, a2, a3, a4) _Ta27_SetComp(a0, a1, a2, a3, a4)
+expr_ty _Ta27_SetComp(expr_ty elt, asdl_seq * generators, int lineno, int col_offset, PyArena
+                      *arena);
+#define DictComp(a0, a1, a2, a3, a4, a5) _Ta27_DictComp(a0, a1, a2, a3, a4, a5)
+expr_ty _Ta27_DictComp(expr_ty key, expr_ty value, asdl_seq * generators, int lineno, int
+                       col_offset, PyArena *arena);
+#define GeneratorExp(a0, a1, a2, a3, a4) _Ta27_GeneratorExp(a0, a1, a2, a3, a4)
+expr_ty _Ta27_GeneratorExp(expr_ty elt, asdl_seq * generators, int lineno, int col_offset, PyArena
+                           *arena);
+#define Yield(a0, a1, a2, a3) _Ta27_Yield(a0, a1, a2, a3)
+expr_ty _Ta27_Yield(expr_ty value, int lineno, int col_offset, PyArena *arena);
+#define Compare(a0, a1, a2, a3, a4, a5) _Ta27_Compare(a0, a1, a2, a3, a4, a5)
+expr_ty _Ta27_Compare(expr_ty left, asdl_int_seq * ops, asdl_seq * comparators, int lineno, int
+                      col_offset, PyArena *arena);
+#define Call(a0, a1, a2, a3, a4, a5, a6, a7) _Ta27_Call(a0, a1, a2, a3, a4, a5, a6, a7)
+expr_ty _Ta27_Call(expr_ty func, asdl_seq * args, asdl_seq * keywords, expr_ty starargs, expr_ty
+                   kwargs, int lineno, int col_offset, PyArena *arena);
+#define Repr(a0, a1, a2, a3) _Ta27_Repr(a0, a1, a2, a3)
+expr_ty _Ta27_Repr(expr_ty value, int lineno, int col_offset, PyArena *arena);
+#define Num(a0, a1, a2, a3) _Ta27_Num(a0, a1, a2, a3)
+expr_ty _Ta27_Num(object n, int lineno, int col_offset, PyArena *arena);
+#define Str(a0, a1, a2, a3) _Ta27_Str(a0, a1, a2, a3)
+expr_ty _Ta27_Str(string s, int lineno, int col_offset, PyArena *arena);
+#define Attribute(a0, a1, a2, a3, a4, a5) _Ta27_Attribute(a0, a1, a2, a3, a4, a5)
+expr_ty _Ta27_Attribute(expr_ty value, identifier attr, expr_context_ty ctx, int lineno, int
+                        col_offset, PyArena *arena);
+#define Subscript(a0, a1, a2, a3, a4, a5) _Ta27_Subscript(a0, a1, a2, a3, a4, a5)
+expr_ty _Ta27_Subscript(expr_ty value, slice_ty slice, expr_context_ty ctx, int lineno, int
+                        col_offset, PyArena *arena);
+#define Name(a0, a1, a2, a3, a4) _Ta27_Name(a0, a1, a2, a3, a4)
+expr_ty _Ta27_Name(identifier id, expr_context_ty ctx, int lineno, int col_offset, PyArena *arena);
+#define List(a0, a1, a2, a3, a4) _Ta27_List(a0, a1, a2, a3, a4)
+expr_ty _Ta27_List(asdl_seq * elts, expr_context_ty ctx, int lineno, int col_offset, PyArena
+                   *arena);
+#define Tuple(a0, a1, a2, a3, a4) _Ta27_Tuple(a0, a1, a2, a3, a4)
+expr_ty _Ta27_Tuple(asdl_seq * elts, expr_context_ty ctx, int lineno, int col_offset, PyArena
+                    *arena);
+#define Ellipsis(a0) _Ta27_Ellipsis(a0)
+slice_ty _Ta27_Ellipsis(PyArena *arena);
+#define Slice(a0, a1, a2, a3) _Ta27_Slice(a0, a1, a2, a3)
+slice_ty _Ta27_Slice(expr_ty lower, expr_ty upper, expr_ty step, PyArena *arena);
+#define ExtSlice(a0, a1) _Ta27_ExtSlice(a0, a1)
+slice_ty _Ta27_ExtSlice(asdl_seq * dims, PyArena *arena);
+#define Index(a0, a1) _Ta27_Index(a0, a1)
+slice_ty _Ta27_Index(expr_ty value, PyArena *arena);
+#define comprehension(a0, a1, a2, a3) _Ta27_comprehension(a0, a1, a2, a3)
+comprehension_ty _Ta27_comprehension(expr_ty target, expr_ty iter, asdl_seq * ifs, PyArena *arena);
+#define ExceptHandler(a0, a1, a2, a3, a4, a5) _Ta27_ExceptHandler(a0, a1, a2, a3, a4, a5)
+excepthandler_ty _Ta27_ExceptHandler(expr_ty type, expr_ty name, asdl_seq * body, int lineno, int
+                                     col_offset, PyArena *arena);
+#define arguments(a0, a1, a2, a3, a4, a5) _Ta27_arguments(a0, a1, a2, a3, a4, a5)
+arguments_ty _Ta27_arguments(asdl_seq * args, identifier vararg, identifier kwarg, asdl_seq *
+                             defaults, asdl_seq * type_comments, PyArena *arena);
+#define keyword(a0, a1, a2) _Ta27_keyword(a0, a1, a2)
+keyword_ty _Ta27_keyword(identifier arg, expr_ty value, PyArena *arena);
+#define alias(a0, a1, a2) _Ta27_alias(a0, a1, a2)
+alias_ty _Ta27_alias(identifier name, identifier asname, PyArena *arena);
+#define TypeIgnore(a0, a1) _Ta27_TypeIgnore(a0, a1)
+type_ignore_ty _Ta27_TypeIgnore(int lineno, PyArena *arena);
+
+PyObject* Ta27AST_mod2obj(mod_ty t);
+mod_ty Ta27AST_obj2mod(PyObject* ast, PyArena* arena, int mode);
+int Ta27AST_Check(PyObject* obj);
diff --git a/ast27/Include/asdl.h b/ast27/Include/asdl.h
new file mode 100644
index 0000000..7b9cf3f
--- /dev/null
+++ b/ast27/Include/asdl.h
@@ -0,0 +1,52 @@
+#ifndef Ta27_ASDL_H
+#define Ta27_ASDL_H
+
+typedef PyObject * identifier;
+typedef PyObject * string;
+typedef PyObject * object;
+
+#ifndef __cplusplus
+typedef enum {false, true} bool;
+#endif
+
+/* It would be nice if the code generated by asdl_c.py was completely
+   independent of Python, but it is a goal the requires too much work
+   at this stage.  So, for example, I'll represent identifiers as
+   interned Python strings.
+*/
+
+/* XXX A sequence should be typed so that its use can be typechecked. */
+
+typedef struct {
+    int size;
+    void *elements[1];
+} asdl_seq;
+
+typedef struct {
+    int size;
+    int elements[1];
+} asdl_int_seq;
+
+#if PY_MINOR_VERSION > 3
+#define asdl_seq_new _Py_asdl_seq_new
+#define asdl_int_seq_new _Py_asdl_int_seq_new
+#else
+#define _Py_asdl_seq_new asdl_seq_new
+#define _Py_asdl_int_seq_new asdl_int_seq_new
+#endif
+asdl_seq *asdl_seq_new(int size, PyArena *arena);
+asdl_int_seq *asdl_int_seq_new(int size, PyArena *arena);
+
+#define asdl_seq_GET(S, I) (S)->elements[(I)]
+#define asdl_seq_LEN(S) ((S) == NULL ? 0 : (S)->size)
+#ifdef Py_DEBUG
+#define asdl_seq_SET(S, I, V) { \
+        int _asdl_i = (I); \
+        assert((S) && _asdl_i < (S)->size); \
+        (S)->elements[_asdl_i] = (V); \
+}
+#else
+#define asdl_seq_SET(S, I, V) (S)->elements[I] = (V)
+#endif
+
+#endif /* !Ta27_ASDL_H */
diff --git a/ast27/Include/ast.h b/ast27/Include/ast.h
new file mode 100644
index 0000000..2db1a2b
--- /dev/null
+++ b/ast27/Include/ast.h
@@ -0,0 +1,13 @@
+#ifndef Ta27_AST_H
+#define Ta27_AST_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+PyAPI_FUNC(mod_ty) Ta27AST_FromNode(const node *, PyCompilerFlags *flags,
+				  const char *, PyArena *);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* !Ta27_AST_H */
diff --git a/ast27/Include/bitset.h b/ast27/Include/bitset.h
new file mode 100644
index 0000000..22e2b71
--- /dev/null
+++ b/ast27/Include/bitset.h
@@ -0,0 +1,32 @@
+
+#ifndef Ta27_BITSET_H
+#define Ta27_BITSET_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Bitset interface */
+
+#define BYTE		char
+
+typedef BYTE *bitset;
+
+bitset newbitset(int nbits);
+void delbitset(bitset bs);
+#define testbit(ss, ibit) (((ss)[BIT2BYTE(ibit)] & BIT2MASK(ibit)) != 0)
+int addbit(bitset bs, int ibit); /* Returns 0 if already set */
+int samebitset(bitset bs1, bitset bs2, int nbits);
+void mergebitset(bitset bs1, bitset bs2, int nbits);
+
+#define BITSPERBYTE	(8*sizeof(BYTE))
+#define NBYTES(nbits)	(((nbits) + BITSPERBYTE - 1) / BITSPERBYTE)
+
+#define BIT2BYTE(ibit)	((ibit) / BITSPERBYTE)
+#define BIT2SHIFT(ibit)	((ibit) % BITSPERBYTE)
+#define BIT2MASK(ibit)	(1 << BIT2SHIFT(ibit))
+#define BYTE2BIT(ibyte)	((ibyte) * BITSPERBYTE)
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* !Ta27_BITSET_H */
diff --git a/ast27/Include/compile.h b/ast27/Include/compile.h
new file mode 100644
index 0000000..bb304b7
--- /dev/null
+++ b/ast27/Include/compile.h
@@ -0,0 +1,18 @@
+
+#ifndef Ta27_COMPILE_H
+#define Ta27_COMPILE_H
+
+#include "code.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Public interface */
+PyAPI_FUNC(PyFutureFeatures *) PyFuture_FromAST(struct _mod *, const char *);
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* !Ta27_COMPILE_H */
diff --git a/ast27/Include/errcode.h b/ast27/Include/errcode.h
new file mode 100644
index 0000000..eaa695c
--- /dev/null
+++ b/ast27/Include/errcode.h
@@ -0,0 +1,36 @@
+#ifndef Ta27_ERRCODE_H
+#define Ta27_ERRCODE_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* Error codes passed around between file input, tokenizer, parser and
+   interpreter.  This is necessary so we can turn them into Python
+   exceptions at a higher level.  Note that some errors have a
+   slightly different meaning when passed from the tokenizer to the
+   parser than when passed from the parser to the interpreter; e.g.
+   the parser only returns E_EOF when it hits EOF immediately, and it
+   never returns E_OK. */
+
+#define E_OK		10	/* No error */
+#define E_EOF		11	/* End Of File */
+#define E_INTR		12	/* Interrupted */
+#define E_TOKEN		13	/* Bad token */
+#define E_SYNTAX	14	/* Syntax error */
+#define E_NOMEM		15	/* Ran out of memory */
+#define E_DONE		16	/* Parsing complete */
+#define E_ERROR		17	/* Execution error */
+#define E_TABSPACE	18	/* Inconsistent mixing of tabs and spaces */
+#define E_OVERFLOW      19	/* Node had too many children */
+#define E_TOODEEP	20	/* Too many indentation levels */
+#define E_DEDENT	21	/* No matching outer block for dedent */
+#define E_DECODE	22	/* Error in decoding into Unicode */
+#define E_EOFS		23	/* EOF in triple-quoted string */
+#define E_EOLS		24	/* EOL in single-quoted string */
+#define E_LINECONT	25	/* Unexpected characters after a line continuation */
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* !Ta27_ERRCODE_H */
diff --git a/ast27/Include/graminit.h b/ast27/Include/graminit.h
new file mode 100644
index 0000000..4fbd368
--- /dev/null
+++ b/ast27/Include/graminit.h
@@ -0,0 +1,90 @@
+/* Generated by Parser/pgen */
+
+#define single_input 256
+#define file_input 257
+#define eval_input 258
+#define decorator 259
+#define decorators 260
+#define decorated 261
+#define funcdef 262
+#define parameters 263
+#define varargslist 264
+#define fpdef 265
+#define fplist 266
+#define stmt 267
+#define simple_stmt 268
+#define small_stmt 269
+#define expr_stmt 270
+#define augassign 271
+#define print_stmt 272
+#define del_stmt 273
+#define pass_stmt 274
+#define flow_stmt 275
+#define break_stmt 276
+#define continue_stmt 277
+#define return_stmt 278
+#define yield_stmt 279
+#define raise_stmt 280
+#define import_stmt 281
+#define import_name 282
+#define import_from 283
+#define import_as_name 284
+#define dotted_as_name 285
+#define import_as_names 286
+#define dotted_as_names 287
+#define dotted_name 288
+#define global_stmt 289
+#define exec_stmt 290
+#define assert_stmt 291
+#define compound_stmt 292
+#define if_stmt 293
+#define while_stmt 294
+#define for_stmt 295
+#define try_stmt 296
+#define with_stmt 297
+#define with_item 298
+#define except_clause 299
+#define suite 300
+#define testlist_safe 301
+#define old_test 302
+#define old_lambdef 303
+#define test 304
+#define or_test 305
+#define and_test 306
+#define not_test 307
+#define comparison 308
+#define comp_op 309
+#define expr 310
+#define xor_expr 311
+#define and_expr 312
+#define shift_expr 313
+#define arith_expr 314
+#define term 315
+#define factor 316
+#define power 317
+#define atom 318
+#define listmaker 319
+#define testlist_comp 320
+#define lambdef 321
+#define trailer 322
+#define subscriptlist 323
+#define subscript 324
+#define sliceop 325
+#define exprlist 326
+#define testlist 327
+#define dictorsetmaker 328
+#define classdef 329
+#define arglist 330
+#define argument 331
+#define list_iter 332
+#define list_for 333
+#define list_if 334
+#define comp_iter 335
+#define comp_for 336
+#define comp_if 337
+#define testlist1 338
+#define encoding_decl 339
+#define yield_expr 340
+#define func_type_input 341
+#define func_type 342
+#define typelist 343
diff --git a/ast27/Include/grammar.h b/ast27/Include/grammar.h
new file mode 100644
index 0000000..801571b
--- /dev/null
+++ b/ast27/Include/grammar.h
@@ -0,0 +1,93 @@
+
+/* Grammar interface */
+
+#ifndef Ta27_GRAMMAR_H
+#define Ta27_GRAMMAR_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "bitset.h" /* Sigh... */
+
+/* A label of an arc */
+
+typedef struct {
+    int		 lb_type;
+    char	*lb_str;
+} label;
+
+#define EMPTY 0		/* Label number 0 is by definition the empty label */
+
+/* A list of labels */
+
+typedef struct {
+    int		 ll_nlabels;
+    label	*ll_label;
+} labellist;
+
+/* An arc from one state to another */
+
+typedef struct {
+    short	a_lbl;		/* Label of this arc */
+    short	a_arrow;	/* State where this arc goes to */
+} arc;
+
+/* A state in a DFA */
+
+typedef struct {
+    int		 s_narcs;
+    arc		*s_arc;		/* Array of arcs */
+	
+    /* Optional accelerators */
+    int		 s_lower;	/* Lowest label index */
+    int		 s_upper;	/* Highest label index */
+    int		*s_accel;	/* Accelerator */
+    int		 s_accept;	/* Nonzero for accepting state */
+} state;
+
+/* A DFA */
+
+typedef struct {
+    int		 d_type;	/* Non-terminal this represents */
+    char	*d_name;	/* For printing */
+    int		 d_initial;	/* Initial state */
+    int		 d_nstates;
+    state	*d_state;	/* Array of states */
+    bitset	 d_first;
+} dfa;
+
+/* A grammar */
+
+typedef struct {
+    int		 g_ndfas;
+    dfa		*g_dfa;		/* Array of DFAs */
+    labellist	 g_ll;
+    int		 g_start;	/* Start symbol of the grammar */
+    int		 g_accel;	/* Set if accelerators present */
+} grammar;
+
+/* FUNCTIONS */
+
+grammar *newgrammar(int start);
+dfa *adddfa(grammar *g, int type, char *name);
+int addstate(dfa *d);
+void addarc(dfa *d, int from, int to, int lbl);
+dfa *Ta27Grammar_FindDFA(grammar *g, int type);
+
+int addlabel(labellist *ll, int type, char *str);
+int findlabel(labellist *ll, int type, char *str);
+char *Ta27Grammar_LabelRepr(label *lb);
+void translatelabels(grammar *g);
+
+void addfirstsets(grammar *g);
+
+void Ta27Grammar_AddAccelerators(grammar *g);
+void Ta27Grammar_RemoveAccelerators(grammar *);
+
+void printgrammar(grammar *g, FILE *fp);
+void printnonterminals(grammar *g, FILE *fp);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* !Ta27_GRAMMAR_H */
diff --git a/ast27/Include/node.h b/ast27/Include/node.h
new file mode 100644
index 0000000..32ced76
--- /dev/null
+++ b/ast27/Include/node.h
@@ -0,0 +1,41 @@
+
+/* Parse tree node interface */
+
+#ifndef Ta27_NODE_H
+#define Ta27_NODE_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct _node {
+    short		n_type;
+    char		*n_str;
+    int			n_lineno;
+    int			n_col_offset;
+    int			n_nchildren;
+    struct _node	*n_child;
+} node;
+
+PyAPI_FUNC(node *) Ta27Node_New(int type);
+PyAPI_FUNC(int) Ta27Node_AddChild(node *n, int type,
+                                      char *str, int lineno, int col_offset);
+PyAPI_FUNC(void) Ta27Node_Free(node *n);
+PyAPI_FUNC(Py_ssize_t) _Ta27Node_SizeOf(node *n);
+
+/* Node access functions */
+#define NCH(n)		((n)->n_nchildren)
+	
+#define CHILD(n, i)	(&(n)->n_child[i])
+#define RCHILD(n, i)	(CHILD(n, NCH(n) + i))
+#define TYPE(n)		((n)->n_type)
+#define STR(n)		((n)->n_str)
+
+/* Assert that the type of a node is what we expect */
+#define REQ(n, type) assert(TYPE(n) == (type))
+
+PyAPI_FUNC(void) PyNode_ListTree(node *);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* !Ta27_NODE_H */
diff --git a/ast27/Include/parsetok.h b/ast27/Include/parsetok.h
new file mode 100644
index 0000000..ca652b8
--- /dev/null
+++ b/ast27/Include/parsetok.h
@@ -0,0 +1,73 @@
+
+/* Parser-tokenizer link interface */
+
+#ifndef Ta27_PARSETOK_H
+#define Ta27_PARSETOK_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct {
+    int error;
+    PyObject *filename;
+    int lineno;
+    int offset;
+    char *text;
+    int token;
+    int expected;
+} perrdetail;
+
+#if 0
+#define PyPARSE_YIELD_IS_KEYWORD	0x0001
+#endif
+
+#define PyPARSE_DONT_IMPLY_DEDENT	0x0002
+
+#if 0
+#define PyPARSE_WITH_IS_KEYWORD		0x0003
+#endif
+
+#define PyPARSE_PRINT_IS_FUNCTION       0x0004
+#define PyPARSE_UNICODE_LITERALS        0x0008
+
+#define PyPARSE_IGNORE_COOKIE 0x0010
+
+
+PyAPI_FUNC(node *) Ta27Parser_ParseString(const char *, grammar *, int,
+                                              perrdetail *);
+PyAPI_FUNC(node *) Ta27Parser_ParseFile (FILE *, const char *, grammar *, int,
+                                             char *, char *, perrdetail *);
+
+PyAPI_FUNC(node *) Ta27Parser_ParseStringFlags(const char *, grammar *, int,
+                                              perrdetail *, int);
+PyAPI_FUNC(node *) Ta27Parser_ParseFileFlags(FILE *, const char *, grammar *,
+						 int, char *, char *,
+						 perrdetail *, int);
+PyAPI_FUNC(node *) Ta27Parser_ParseFileFlagsEx(FILE *, const char *, grammar *,
+						 int, char *, char *,
+						 perrdetail *, int *);
+
+PyAPI_FUNC(node *) Ta27Parser_ParseStringFlagsFilename(const char *,
+					      const char *,
+					      grammar *, int,
+                                              perrdetail *, int);
+PyAPI_FUNC(node *) Ta27Parser_ParseStringFlagsFilenameEx(const char *,
+					      const char *,
+					      grammar *, int,
+                                              perrdetail *, int *);
+
+PyAPI_FUNC(node *) Ta27Parser_ParseStringObject(
+    const char *s,
+    PyObject *filename,
+    grammar *g,
+    int start,
+    perrdetail *err_ret,
+    int *flags);
+
+/* Note that he following function is defined in pythonrun.c not parsetok.c. */
+PyAPI_FUNC(void) PyParser_SetError(perrdetail *);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* !Ta27_PARSETOK_H */
diff --git a/ast27/Include/token.h b/ast27/Include/token.h
new file mode 100644
index 0000000..21578e1
--- /dev/null
+++ b/ast27/Include/token.h
@@ -0,0 +1,88 @@
+
+/* Token types */
+
+#ifndef Ta27_TOKEN_H
+#define Ta27_TOKEN_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#undef TILDE   /* Prevent clash of our definition with system macro. Ex AIX, ioctl.h */
+
+#define ENDMARKER	0
+#define NAME		1
+#define NUMBER		2
+#define STRING		3
+#define NEWLINE		4
+#define INDENT		5
+#define DEDENT		6
+#define LPAR		7
+#define RPAR		8
+#define LSQB		9
+#define RSQB		10
+#define COLON		11
+#define COMMA		12
+#define SEMI		13
+#define PLUS		14
+#define MINUS		15
+#define STAR		16
+#define SLASH		17
+#define VBAR		18
+#define AMPER		19
+#define LESS		20
+#define GREATER		21
+#define EQUAL		22
+#define DOT		23
+#define PERCENT		24
+#define BACKQUOTE	25
+#define LBRACE		26
+#define RBRACE		27
+#define EQEQUAL		28
+#define NOTEQUAL	29
+#define LESSEQUAL	30
+#define GREATEREQUAL	31
+#define TILDE		32
+#define CIRCUMFLEX	33
+#define LEFTSHIFT	34
+#define RIGHTSHIFT	35
+#define DOUBLESTAR	36
+#define PLUSEQUAL	37
+#define MINEQUAL	38
+#define STAREQUAL	39
+#define SLASHEQUAL	40
+#define PERCENTEQUAL	41
+#define AMPEREQUAL	42
+#define VBAREQUAL	43
+#define CIRCUMFLEXEQUAL	44
+#define LEFTSHIFTEQUAL	45
+#define RIGHTSHIFTEQUAL	46
+#define DOUBLESTAREQUAL	47
+#define DOUBLESLASH	48
+#define DOUBLESLASHEQUAL 49
+#define AT              50	
+/* Don't forget to update the table _Ta27Parser_TokenNames in tokenizer.c! */
+#define OP		51
+#define RARROW          52
+#define TYPE_IGNORE	53
+#define TYPE_COMMENT	54
+#define ERRORTOKEN	55
+#define N_TOKENS	56
+
+/* Special definitions for cooperation with parser */
+
+#define NT_OFFSET		256
+
+#define ISTERMINAL(x)		((x) < NT_OFFSET)
+#define ISNONTERMINAL(x)	((x) >= NT_OFFSET)
+#define ISEOF(x)		((x) == ENDMARKER)
+
+
+PyAPI_DATA(char *) _Ta27Parser_TokenNames[]; /* Token names */
+PyAPI_FUNC(int) Ta27Token_OneChar(int);
+PyAPI_FUNC(int) Ta27Token_TwoChars(int, int);
+PyAPI_FUNC(int) Ta27Token_ThreeChars(int, int, int);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* !Ta27_TOKEN_H */
diff --git a/ast27/Parser/Python.asdl b/ast27/Parser/Python.asdl
new file mode 100644
index 0000000..1864bc9
--- /dev/null
+++ b/ast27/Parser/Python.asdl
@@ -0,0 +1,122 @@
+-- ASDL's five builtin types are identifier, int, string, object, bool
+
+module Python version "$Revision$"
+{
+	mod = Module(stmt* body, type_ignore *type_ignores)
+	    | Interactive(stmt* body)
+	    | Expression(expr body)
+      | FunctionType(expr* argtypes, expr returns)
+
+	    -- not really an actual node but useful in Jython's typesystem.
+	    | Suite(stmt* body)
+
+	stmt = FunctionDef(identifier name, arguments args, 
+                            stmt* body, expr* decorator_list, string? type_comment)
+	      | ClassDef(identifier name, expr* bases, stmt* body, expr* decorator_list)
+	      | Return(expr? value)
+
+	      | Delete(expr* targets)
+	      | Assign(expr* targets, expr value, string? type_comment)
+	      | AugAssign(expr target, operator op, expr value)
+
+	      -- not sure if bool is allowed, can always use int
+ 	      | Print(expr? dest, expr* values, bool nl)
+
+	      -- use 'orelse' because else is a keyword in target languages
+	      | For(expr target, expr iter, stmt* body, stmt* orelse, string? type_comment)
+	      | While(expr test, stmt* body, stmt* orelse)
+	      | If(expr test, stmt* body, stmt* orelse)
+	      | With(expr context_expr, expr? optional_vars, stmt* body, string? type_comment)
+
+	      -- 'type' is a bad name
+	      | Raise(expr? type, expr? inst, expr? tback)
+	      | TryExcept(stmt* body, excepthandler* handlers, stmt* orelse)
+	      | TryFinally(stmt* body, stmt* finalbody)
+	      | Assert(expr test, expr? msg)
+
+	      | Import(alias* names)
+	      | ImportFrom(identifier? module, alias* names, int? level)
+
+	      -- Doesn't capture requirement that locals must be
+	      -- defined if globals is
+	      -- still supports use as a function!
+	      | Exec(expr body, expr? globals, expr? locals)
+
+	      | Global(identifier* names)
+	      | Expr(expr value)
+	      | Pass | Break | Continue
+
+	      -- XXX Jython will be different
+	      -- col_offset is the byte offset in the utf8 string the parser uses
+	      attributes (int lineno, int col_offset)
+
+	      -- BoolOp() can use left & right?
+	expr = BoolOp(boolop op, expr* values)
+	     | BinOp(expr left, operator op, expr right)
+	     | UnaryOp(unaryop op, expr operand)
+	     | Lambda(arguments args, expr body)
+	     | IfExp(expr test, expr body, expr orelse)
+	     | Dict(expr* keys, expr* values)
+	     | Set(expr* elts)
+	     | ListComp(expr elt, comprehension* generators)
+	     | SetComp(expr elt, comprehension* generators)
+	     | DictComp(expr key, expr value, comprehension* generators)
+	     | GeneratorExp(expr elt, comprehension* generators)
+	     -- the grammar constrains where yield expressions can occur
+	     | Yield(expr? value)
+	     -- need sequences for compare to distinguish between
+	     -- x < 4 < 3 and (x < 4) < 3
+	     | Compare(expr left, cmpop* ops, expr* comparators)
+	     | Call(expr func, expr* args, keyword* keywords,
+			 expr? starargs, expr? kwargs)
+	     | Repr(expr value)
+	     | Num(object n) -- a number as a PyObject.
+	     | Str(string s) -- need to specify raw, unicode, etc?
+	     -- other literals? bools?
+
+	     -- the following expression can appear in assignment context
+	     | Attribute(expr value, identifier attr, expr_context ctx)
+	     | Subscript(expr value, slice slice, expr_context ctx)
+	     | Name(identifier id, expr_context ctx)
+	     | List(expr* elts, expr_context ctx) 
+	     | Tuple(expr* elts, expr_context ctx)
+
+	      -- col_offset is the byte offset in the utf8 string the parser uses
+	      attributes (int lineno, int col_offset)
+
+	expr_context = Load | Store | Del | AugLoad | AugStore | Param
+
+	slice = Ellipsis | Slice(expr? lower, expr? upper, expr? step) 
+	      | ExtSlice(slice* dims) 
+	      | Index(expr value) 
+
+	boolop = And | Or 
+
+	operator = Add | Sub | Mult | Div | Mod | Pow | LShift 
+                 | RShift | BitOr | BitXor | BitAnd | FloorDiv
+
+	unaryop = Invert | Not | UAdd | USub
+
+	cmpop = Eq | NotEq | Lt | LtE | Gt | GtE | Is | IsNot | In | NotIn
+
+	comprehension = (expr target, expr iter, expr* ifs)
+
+	-- not sure what to call the first argument for raise and except
+	excepthandler = ExceptHandler(expr? type, expr? name, stmt* body)
+	                attributes (int lineno, int col_offset)
+
+	-- type_comments is used to support the per-argument type comment syntax.
+	-- It is either an empty list or a list with length equal to the number of
+	-- args (including varargs and kwargs, if present) and with members set to the
+	-- string of each arg's type comment, if present, or None otherwise.
+	arguments = (expr* args, identifier? vararg, 
+		     identifier? kwarg, expr* defaults, string* type_comments)
+
+        -- keyword arguments supplied to call
+        keyword = (identifier arg, expr value)
+
+        -- import name with optional 'as' alias.
+        alias = (identifier name, identifier? asname)
+
+  type_ignore = TypeIgnore(int lineno)
+}
diff --git a/ast27/Parser/acceler.c b/ast27/Parser/acceler.c
new file mode 100644
index 0000000..df92385
--- /dev/null
+++ b/ast27/Parser/acceler.c
@@ -0,0 +1,125 @@
+
+/* Parser accelerator module */
+
+/* The parser as originally conceived had disappointing performance.
+   This module does some precomputation that speeds up the selection
+   of a DFA based upon a token, turning a search through an array
+   into a simple indexing operation.  The parser now cannot work
+   without the accelerators installed.  Note that the accelerators
+   are installed dynamically when the parser is initialized, they
+   are not part of the static data structure written on graminit.[ch]
+   by the parser generator. */
+
+#include "pgenheaders.h"
+#include "grammar.h"
+#include "node.h"
+#include "token.h"
+#include "parser.h"
+
+/* Forward references */
+static void fixdfa(grammar *, dfa *);
+static void fixstate(grammar *, state *);
+
+void
+Ta27Grammar_AddAccelerators(grammar *g)
+{
+    dfa *d;
+    int i;
+    d = g->g_dfa;
+    for (i = g->g_ndfas; --i >= 0; d++)
+        fixdfa(g, d);
+    g->g_accel = 1;
+}
+
+void
+Ta27Grammar_RemoveAccelerators(grammar *g)
+{
+    dfa *d;
+    int i;
+    g->g_accel = 0;
+    d = g->g_dfa;
+    for (i = g->g_ndfas; --i >= 0; d++) {
+        state *s;
+        int j;
+        s = d->d_state;
+        for (j = 0; j < d->d_nstates; j++, s++) {
+            if (s->s_accel)
+                PyObject_FREE(s->s_accel);
+            s->s_accel = NULL;
+        }
+    }
+}
+
+static void
+fixdfa(grammar *g, dfa *d)
+{
+    state *s;
+    int j;
+    s = d->d_state;
+    for (j = 0; j < d->d_nstates; j++, s++)
+        fixstate(g, s);
+}
+
+static void
+fixstate(grammar *g, state *s)
+{
+    arc *a;
+    int k;
+    int *accel;
+    int nl = g->g_ll.ll_nlabels;
+    s->s_accept = 0;
+    accel = (int *) PyObject_MALLOC(nl * sizeof(int));
+    if (accel == NULL) {
+        fprintf(stderr, "no mem to build parser accelerators\n");
+        exit(1);
+    }
+    for (k = 0; k < nl; k++)
+        accel[k] = -1;
+    a = s->s_arc;
+    for (k = s->s_narcs; --k >= 0; a++) {
+        int lbl = a->a_lbl;
+        label *l = &g->g_ll.ll_label[lbl];
+        int type = l->lb_type;
+        if (a->a_arrow >= (1 << 7)) {
+            printf("XXX too many states!\n");
+            continue;
+        }
+        if (ISNONTERMINAL(type)) {
+            dfa *d1 = Ta27Grammar_FindDFA(g, type);
+            int ibit;
+            if (type - NT_OFFSET >= (1 << 7)) {
+                printf("XXX too high nonterminal number!\n");
+                continue;
+            }
+            for (ibit = 0; ibit < g->g_ll.ll_nlabels; ibit++) {
+                if (testbit(d1->d_first, ibit)) {
+                    if (accel[ibit] != -1)
+                        printf("XXX ambiguity!\n");
+                    accel[ibit] = a->a_arrow | (1 << 7) |
+                        ((type - NT_OFFSET) << 8);
+                }
+            }
+        }
+        else if (lbl == EMPTY)
+            s->s_accept = 1;
+        else if (lbl >= 0 && lbl < nl)
+            accel[lbl] = a->a_arrow;
+    }
+    while (nl > 0 && accel[nl-1] == -1)
+        nl--;
+    for (k = 0; k < nl && accel[k] == -1;)
+        k++;
+    if (k < nl) {
+        int i;
+        s->s_accel = (int *) PyObject_MALLOC((nl-k) * sizeof(int));
+        if (s->s_accel == NULL) {
+            fprintf(stderr, "no mem to add parser accelerators\n");
+            exit(1);
+        }
+        s->s_lower = k;
+        s->s_upper = nl;
+        for (i = 0; k < nl; i++, k++)
+            s->s_accel[i] = accel[k];
+    }
+    PyObject_FREE(accel);
+}
diff --git a/ast27/Parser/asdl.py b/ast27/Parser/asdl.py
new file mode 100644
index 0000000..7f5856b
--- /dev/null
+++ b/ast27/Parser/asdl.py
@@ -0,0 +1,413 @@
+"""An implementation of the Zephyr Abstract Syntax Definition Language.
+
+See http://asdl.sourceforge.net/ and
+http://www.cs.princeton.edu/research/techreps/TR-554-97
+
+Only supports top level module decl, not view.  I'm guessing that view
+is intended to support the browser and I'm not interested in the
+browser.
+
+Changes for Python: Add support for module versions
+"""
+
+import os
+import traceback
+
+import spark
+
+class Token(object):
+    # spark seems to dispatch in the parser based on a token's
+    # type attribute
+    def __init__(self, type, lineno):
+        self.type = type
+        self.lineno = lineno
+
+    def __str__(self):
+        return self.type
+
+    def __repr__(self):
+        return str(self)
+
+class Id(Token):
+    def __init__(self, value, lineno):
+        self.type = 'Id'
+        self.value = value
+        self.lineno = lineno
+
+    def __str__(self):
+        return self.value
+
+class String(Token):
+    def __init__(self, value, lineno):
+        self.type = 'String'
+        self.value = value
+        self.lineno = lineno
+
+class ASDLSyntaxError(Exception):
+
+    def __init__(self, lineno, token=None, msg=None):
+        self.lineno = lineno
+        self.token = token
+        self.msg = msg
+
+    def __str__(self):
+        if self.msg is None:
+            return "Error at '%s', line %d" % (self.token, self.lineno)
+        else:
+            return "%s, line %d" % (self.msg, self.lineno)
+
+class ASDLScanner(spark.GenericScanner, object):
+
+    def tokenize(self, input):
+        self.rv = []
+        self.lineno = 1
+        super(ASDLScanner, self).tokenize(input)
+        return self.rv
+
+    def t_id(self, s):
+        r"[\w\.]+"
+        # XXX doesn't distinguish upper vs. lower, which is
+        # significant for ASDL.
+        self.rv.append(Id(s, self.lineno))
+
+    def t_string(self, s):
+        r'"[^"]*"'
+        self.rv.append(String(s, self.lineno))
+
+    def t_xxx(self, s): # not sure what this production means
+        r"<="
+        self.rv.append(Token(s, self.lineno))
+
+    def t_punctuation(self, s):
+        r"[\{\}\*\=\|\(\)\,\?\:]"
+        self.rv.append(Token(s, self.lineno))
+
+    def t_comment(self, s):
+        r"\-\-[^\n]*"
+        pass
+
+    def t_newline(self, s):
+        r"\n"
+        self.lineno += 1
+
+    def t_whitespace(self, s):
+        r"[ \t]+"
+        pass
+
+    def t_default(self, s):
+        r" . +"
+        raise ValueError, "unmatched input: %s" % `s`
+
+class ASDLParser(spark.GenericParser, object):
+    def __init__(self):
+        super(ASDLParser, self).__init__("module")
+
+    def typestring(self, tok):
+        return tok.type
+
+    def error(self, tok):
+        raise ASDLSyntaxError(tok.lineno, tok)
+
+    def p_module_0(self, (module, name, version, _0, _1)):
+        " module ::= Id Id version { } "
+        if module.value != "module":
+            raise ASDLSyntaxError(module.lineno,
+                                  msg="expected 'module', found %s" % module)
+        return Module(name, None, version)
+
+    def p_module(self, (module, name, version, _0, definitions, _1)):
+        " module ::= Id Id version { definitions } "
+        if module.value != "module":
+            raise ASDLSyntaxError(module.lineno,
+                                  msg="expected 'module', found %s" % module)
+        return Module(name, definitions, version)
+
+    def p_version(self, (version, V)):
+        "version ::= Id String"
+        if version.value != "version":
+            raise ASDLSyntaxError(version.lineno,
+                                msg="expected 'version', found %" % version)
+        return V
+
+    def p_definition_0(self, (definition,)):
+        " definitions ::= definition "
+        return definition
+
+    def p_definition_1(self, (definitions, definition)):
+        " definitions ::= definition definitions "
+        return definitions + definition
+
+    def p_definition(self, (id, _, type)):
+        " definition ::= Id = type "
+        return [Type(id, type)]
+
+    def p_type_0(self, (product,)):
+        " type ::= product "
+        return product
+
+    def p_type_1(self, (sum,)):
+        " type ::= sum "
+        return Sum(sum)
+
+    def p_type_2(self, (sum, id, _0, attributes, _1)):
+        " type ::= sum Id ( fields ) "
+        if id.value != "attributes":
+            raise ASDLSyntaxError(id.lineno,
+                                  msg="expected attributes, found %s" % id)
+        if attributes:
+            attributes.reverse()
+        return Sum(sum, attributes)
+
+    def p_product(self, (_0, fields, _1)):
+        " product ::= ( fields ) "
+        # XXX can't I just construct things in the right order?
+        fields.reverse()
+        return Product(fields)
+
+    def p_sum_0(self, (constructor,)):
+        " sum ::= constructor "
+        return [constructor]
+
+    def p_sum_1(self, (constructor, _, sum)):
+        " sum ::= constructor | sum "
+        return [constructor] + sum
+
+    def p_sum_2(self, (constructor, _, sum)):
+        " sum ::= constructor | sum "
+        return [constructor] + sum
+
+    def p_constructor_0(self, (id,)):
+        " constructor ::= Id "
+        return Constructor(id)
+
+    def p_constructor_1(self, (id, _0, fields, _1)):
+        " constructor ::= Id ( fields ) "
+        # XXX can't I just construct things in the right order?
+        fields.reverse()
+        return Constructor(id, fields)
+
+    def p_fields_0(self, (field,)):
+        " fields ::= field "
+        return [field]
+
+    def p_fields_1(self, (field, _, fields)):
+        " fields ::= field , fields "
+        return fields + [field]
+
+    def p_field_0(self, (type,)):
+        " field ::= Id "
+        return Field(type)
+
+    def p_field_1(self, (type, name)):
+        " field ::= Id Id "
+        return Field(type, name)
+
+    def p_field_2(self, (type, _, name)):
+        " field ::= Id * Id "
+        return Field(type, name, seq=True)
+
+    def p_field_3(self, (type, _, name)):
+        " field ::= Id ? Id "
+        return Field(type, name, opt=True)
+
+    def p_field_4(self, (type, _)):
+        " field ::= Id * "
+        return Field(type, seq=True)
+
+    def p_field_5(self, (type, _)):
+        " field ::= Id ? "
+        return Field(type, opt=True)
+
+builtin_types = ("identifier", "string", "int", "bool", "object")
+
+# below is a collection of classes to capture the AST of an AST :-)
+# not sure if any of the methods are useful yet, but I'm adding them
+# piecemeal as they seem helpful
+
+class AST(object):
+    pass # a marker class
+
+class Module(AST):
+    def __init__(self, name, dfns, version):
+        self.name = name
+        self.dfns = dfns
+        self.version = version
+        self.types = {} # maps type name to value (from dfns)
+        for type in dfns:
+            self.types[type.name.value] = type.value
+
+    def __repr__(self):
+        return "Module(%s, %s)" % (self.name, self.dfns)
+
+class Type(AST):
+    def __init__(self, name, value):
+        self.name = name
+        self.value = value
+
+    def __repr__(self):
+        return "Type(%s, %s)" % (self.name, self.value)
+
+class Constructor(AST):
+    def __init__(self, name, fields=None):
+        self.name = name
+        self.fields = fields or []
+
+    def __repr__(self):
+        return "Constructor(%s, %s)" % (self.name, self.fields)
+
+class Field(AST):
+    def __init__(self, type, name=None, seq=False, opt=False):
+        self.type = type
+        self.name = name
+        self.seq = seq
+        self.opt = opt
+
+    def __repr__(self):
+        if self.seq:
+            extra = ", seq=True"
+        elif self.opt:
+            extra = ", opt=True"
+        else:
+            extra = ""
+        if self.name is None:
+            return "Field(%s%s)" % (self.type, extra)
+        else:
+            return "Field(%s, %s%s)" % (self.type, self.name, extra)
+
+class Sum(AST):
+    def __init__(self, types, attributes=None):
+        self.types = types
+        self.attributes = attributes or []
+
+    def __repr__(self):
+        if self.attributes is None:
+            return "Sum(%s)" % self.types
+        else:
+            return "Sum(%s, %s)" % (self.types, self.attributes)
+
+class Product(AST):
+    def __init__(self, fields):
+        self.fields = fields
+
+    def __repr__(self):
+        return "Product(%s)" % self.fields
+
+class VisitorBase(object):
+
+    def __init__(self, skip=False):
+        self.cache = {}
+        self.skip = skip
+
+    def visit(self, object, *args):
+        meth = self._dispatch(object)
+        if meth is None:
+            return
+        try:
+            meth(object, *args)
+        except Exception, err:
+            print "Error visiting", repr(object)
+            print err
+            traceback.print_exc()
+            # XXX hack
+            if hasattr(self, 'file'):
+                self.file.flush()
+            os._exit(1)
+
+    def _dispatch(self, object):
+        assert isinstance(object, AST), repr(object)
+        klass = object.__class__
+        meth = self.cache.get(klass)
+        if meth is None:
+            methname = "visit" + klass.__name__
+            if self.skip:
+                meth = getattr(self, methname, None)
+            else:
+                meth = getattr(self, methname)
+            self.cache[klass] = meth
+        return meth
+
+class Check(VisitorBase):
+
+    def __init__(self):
+        super(Check, self).__init__(skip=True)
+        self.cons = {}
+        self.errors = 0
+        self.types = {}
+
+    def visitModule(self, mod):
+        for dfn in mod.dfns:
+            self.visit(dfn)
+
+    def visitType(self, type):
+        self.visit(type.value, str(type.name))
+
+    def visitSum(self, sum, name):
+        for t in sum.types:
+            self.visit(t, name)
+
+    def visitConstructor(self, cons, name):
+        key = str(cons.name)
+        conflict = self.cons.get(key)
+        if conflict is None:
+            self.cons[key] = name
+        else:
+            print "Redefinition of constructor %s" % key
+            print "Defined in %s and %s" % (conflict, name)
+            self.errors += 1
+        for f in cons.fields:
+            self.visit(f, key)
+
+    def visitField(self, field, name):
+        key = str(field.type)
+        l = self.types.setdefault(key, [])
+        l.append(name)
+
+    def visitProduct(self, prod, name):
+        for f in prod.fields:
+            self.visit(f, name)
+
+def check(mod):
+    v = Check()
+    v.visit(mod)
+
+    for t in v.types:
+        if t not in mod.types and not t in builtin_types:
+            v.errors += 1
+            uses = ", ".join(v.types[t])
+            print "Undefined type %s, used in %s" % (t, uses)
+
+    return not v.errors
+
+def parse(file):
+    scanner = ASDLScanner()
+    parser = ASDLParser()
+
+    buf = open(file).read()
+    tokens = scanner.tokenize(buf)
+    try:
+        return parser.parse(tokens)
+    except ASDLSyntaxError, err:
+        print err
+        lines = buf.split("\n")
+        print lines[err.lineno - 1] # lines starts at 0, files at 1
+
+if __name__ == "__main__":
+    import glob
+    import sys
+
+    if len(sys.argv) > 1:
+        files = sys.argv[1:]
+    else:
+        testdir = "tests"
+        files = glob.glob(testdir + "/*.asdl")
+
+    for file in files:
+        print file
+        mod = parse(file)
+        print "module", mod.name
+        print len(mod.dfns), "definitions"
+        if not check(mod):
+            print "Check failed"
+        else:
+            for dfn in mod.dfns:
+                print dfn.type
diff --git a/ast27/Parser/asdl_c.py b/ast27/Parser/asdl_c.py
new file mode 100755
index 0000000..145f7f7
--- /dev/null
+++ b/ast27/Parser/asdl_c.py
@@ -0,0 +1,1249 @@
+#! /usr/bin/env python
+"""Generate C code from an ASDL description."""
+
+# TO DO
+# handle fields that have a type but no name
+
+import os, sys
+
+import asdl
+
+TABSIZE = 8
+MAX_COL = 100
+
+def get_c_type(name):
+    """Return a string for the C name of the type.
+
+    This function special cases the default types provided by asdl:
+    identifier, string, int, bool.
+    """
+    # XXX ack!  need to figure out where Id is useful and where string
+    if isinstance(name, asdl.Id):
+        name = name.value
+    if name in asdl.builtin_types:
+        return name
+    else:
+        return "%s_ty" % name
+
+def reflow_lines(s, depth):
+    """Reflow the line s indented depth tabs.
+
+    Return a sequence of lines where no line extends beyond MAX_COL
+    when properly indented.  The first line is properly indented based
+    exclusively on depth * TABSIZE.  All following lines -- these are
+    the reflowed lines generated by this function -- start at the same
+    column as the first character beyond the opening { in the first
+    line.
+    """
+    size = MAX_COL - depth * TABSIZE
+    if len(s) < size:
+        return [s]
+
+    lines = []
+    cur = s
+    padding = ""
+    while len(cur) > size:
+        i = cur.rfind(' ', 0, size)
+        # XXX this should be fixed for real
+        if i == -1 and 'GeneratorExp' in cur:
+            i = size + 3
+        assert i != -1, "Impossible line %d to reflow: %r" % (size, s)
+        lines.append(padding + cur[:i])
+        if len(lines) == 1:
+            # find new size based on brace
+            j = cur.find('{', 0, i)
+            if j >= 0:
+                j += 2 # account for the brace and the space after it
+                size -= j
+                padding = " " * j
+            else:
+                j = cur.find('(', 0, i)
+                if j >= 0:
+                    j += 1 # account for the paren (no space after it)
+                    size -= j
+                    padding = " " * j
+        cur = cur[i+1:]
+    else:
+        lines.append(padding + cur)
+    return lines
+
+def is_simple(sum):
+    """Return True if a sum is a simple.
+
+    A sum is simple if its types have no fields, e.g.
+    unaryop = Invert | Not | UAdd | USub
+    """
+    for t in sum.types:
+        if t.fields:
+            return False
+    return True
+
+
+class EmitVisitor(asdl.VisitorBase):
+    """Visit that emits lines"""
+
+    def __init__(self, file):
+        self.file = file
+        super(EmitVisitor, self).__init__()
+
+    def emit(self, s, depth, reflow=True):
+        # XXX reflow long lines?
+        if reflow:
+            lines = reflow_lines(s, depth)
+        else:
+            lines = [s]
+        for line in lines:
+            line = (" " * TABSIZE * depth) + line + "\n"
+            self.file.write(line)
+
+
+class TypeDefVisitor(EmitVisitor):
+    def visitModule(self, mod):
+        for dfn in mod.dfns:
+            self.visit(dfn)
+
+    def visitType(self, type, depth=0):
+        self.visit(type.value, type.name, depth)
+
+    def visitSum(self, sum, name, depth):
+        if is_simple(sum):
+            self.simple_sum(sum, name, depth)
+        else:
+            self.sum_with_constructors(sum, name, depth)
+
+    def simple_sum(self, sum, name, depth):
+        enum = []
+        for i in range(len(sum.types)):
+            type = sum.types[i]
+            enum.append("%s=%d" % (type.name, i + 1))
+        enums = ", ".join(enum)
+        ctype = get_c_type(name)
+        s = "typedef enum _%s { %s } %s;" % (name, enums, ctype)
+        self.emit(s, depth)
+        self.emit("", depth)
+
+    def sum_with_constructors(self, sum, name, depth):
+        ctype = get_c_type(name)
+        s = "typedef struct _%(name)s *%(ctype)s;" % locals()
+        self.emit(s, depth)
+        self.emit("", depth)
+
+    def visitProduct(self, product, name, depth):
+        ctype = get_c_type(name)
+        s = "typedef struct _%(name)s *%(ctype)s;" % locals()
+        self.emit(s, depth)
+        self.emit("", depth)
+
+
+class StructVisitor(EmitVisitor):
+    """Visitor to generate typdefs for AST."""
+
+    def visitModule(self, mod):
+        for dfn in mod.dfns:
+            self.visit(dfn)
+
+    def visitType(self, type, depth=0):
+        self.visit(type.value, type.name, depth)
+
+    def visitSum(self, sum, name, depth):
+        if not is_simple(sum):
+            self.sum_with_constructors(sum, name, depth)
+
+    def sum_with_constructors(self, sum, name, depth):
+        def emit(s, depth=depth):
+            self.emit(s % sys._getframe(1).f_locals, depth)
+        enum = []
+        for i in range(len(sum.types)):
+            type = sum.types[i]
+            enum.append("%s_kind=%d" % (type.name, i + 1))
+
+        emit("enum _%(name)s_kind {" + ", ".join(enum) + "};")
+
+        emit("struct _%(name)s {")
+        emit("enum _%(name)s_kind kind;", depth + 1)
+        emit("union {", depth + 1)
+        for t in sum.types:
+            self.visit(t, depth + 2)
+        emit("} v;", depth + 1)
+        for field in sum.attributes:
+            # rudimentary attribute handling
+            type = str(field.type)
+            assert type in asdl.builtin_types, type
+            emit("%s %s;" % (type, field.name), depth + 1);
+        emit("};")
+        emit("")
+
+    def visitConstructor(self, cons, depth):
+        if cons.fields:
+            self.emit("struct {", depth)
+            for f in cons.fields:
+                self.visit(f, depth + 1)
+            self.emit("} %s;" % cons.name, depth)
+            self.emit("", depth)
+        else:
+            # XXX not sure what I want here, nothing is probably fine
+            pass
+
+    def visitField(self, field, depth):
+        # XXX need to lookup field.type, because it might be something
+        # like a builtin...
+        ctype = get_c_type(field.type)
+        name = field.name
+        if field.seq:
+            if field.type.value in ('cmpop',):
+                self.emit("asdl_int_seq *%(name)s;" % locals(), depth)
+            else:
+                self.emit("asdl_seq *%(name)s;" % locals(), depth)
+        else:
+            self.emit("%(ctype)s %(name)s;" % locals(), depth)
+
+    def visitProduct(self, product, name, depth):
+        self.emit("struct _%(name)s {" % locals(), depth)
+        for f in product.fields:
+            self.visit(f, depth + 1)
+        self.emit("};", depth)
+        self.emit("", depth)
+
+
+class PrototypeVisitor(EmitVisitor):
+    """Generate function prototypes for the .h file"""
+
+    def visitModule(self, mod):
+        for dfn in mod.dfns:
+            self.visit(dfn)
+
+    def visitType(self, type):
+        self.visit(type.value, type.name)
+
+    def visitSum(self, sum, name):
+        if is_simple(sum):
+            pass # XXX
+        else:
+            for t in sum.types:
+                self.visit(t, name, sum.attributes)
+
+    def get_args(self, fields):
+        """Return list of C argument into, one for each field.
+
+        Argument info is 3-tuple of a C type, variable name, and flag
+        that is true if type can be NULL.
+        """
+        args = []
+        unnamed = {}
+        for f in fields:
+            if f.name is None:
+                name = f.type
+                c = unnamed[name] = unnamed.get(name, 0) + 1
+                if c > 1:
+                    name = "name%d" % (c - 1)
+            else:
+                name = f.name
+            # XXX should extend get_c_type() to handle this
+            if f.seq:
+                if f.type.value in ('cmpop',):
+                    ctype = "asdl_int_seq *"
+                else:
+                    ctype = "asdl_seq *"
+            else:
+                ctype = get_c_type(f.type)
+            args.append((ctype, name, f.opt or f.seq))
+        return args
+
+    def visitConstructor(self, cons, type, attrs):
+        args = self.get_args(cons.fields)
+        attrs = self.get_args(attrs)
+        ctype = get_c_type(type)
+        self.emit_function(cons.name, ctype, args, attrs)
+
+    def emit_function(self, name, ctype, args, attrs, union=True):
+        args = args + attrs
+        if args:
+            argstr = ", ".join(["%s %s" % (atype, aname)
+                                for atype, aname, opt in args])
+            argstr += ", PyArena *arena"
+        else:
+            argstr = "PyArena *arena"
+        margs = "a0"
+        for i in range(1, len(args)+1):
+            margs += ", a%d" % i
+        self.emit("#define %s(%s) _Ta27_%s(%s)" % (name, margs, name, margs), 0,
+                reflow=False)
+        self.emit("%s _Ta27_%s(%s);" % (ctype, name, argstr), False)
+
+    def visitProduct(self, prod, name):
+        self.emit_function(name, get_c_type(name),
+                           self.get_args(prod.fields), [], union=False)
+
+
+class FunctionVisitor(PrototypeVisitor):
+    """Visitor to generate constructor functions for AST."""
+
+    def emit_function(self, name, ctype, args, attrs, union=True):
+        def emit(s, depth=0, reflow=True):
+            self.emit(s, depth, reflow)
+        argstr = ", ".join(["%s %s" % (atype, aname)
+                            for atype, aname, opt in args + attrs])
+        if argstr:
+            argstr += ", PyArena *arena"
+        else:
+            argstr = "PyArena *arena"
+        self.emit("%s" % ctype, 0)
+        emit("%s(%s)" % (name, argstr))
+        emit("{")
+        emit("%s p;" % ctype, 1)
+        for argtype, argname, opt in args:
+            # XXX hack alert: false is allowed for a bool
+            if not opt and not (argtype == "bool" or argtype == "int"):
+                emit("if (!%s) {" % argname, 1)
+                emit("PyErr_SetString(PyExc_ValueError,", 2)
+                msg = "field %s is required for %s" % (argname, name)
+                emit('                "%s");' % msg,
+                     2, reflow=False)
+                emit('return NULL;', 2)
+                emit('}', 1)
+
+        emit("p = (%s)PyArena_Malloc(arena, sizeof(*p));" % ctype, 1);
+        emit("if (!p)", 1)
+        emit("return NULL;", 2)
+        if union:
+            self.emit_body_union(name, args, attrs)
+        else:
+            self.emit_body_struct(name, args, attrs)
+        emit("return p;", 1)
+        emit("}")
+        emit("")
+
+    def emit_body_union(self, name, args, attrs):
+        def emit(s, depth=0, reflow=True):
+            self.emit(s, depth, reflow)
+        emit("p->kind = %s_kind;" % name, 1)
+        for argtype, argname, opt in args:
+            emit("p->v.%s.%s = %s;" % (name, argname, argname), 1)
+        for argtype, argname, opt in attrs:
+            emit("p->%s = %s;" % (argname, argname), 1)
+
+    def emit_body_struct(self, name, args, attrs):
+        def emit(s, depth=0, reflow=True):
+            self.emit(s, depth, reflow)
+        for argtype, argname, opt in args:
+            emit("p->%s = %s;" % (argname, argname), 1)
+        assert not attrs
+
+
+class PickleVisitor(EmitVisitor):
+
+    def visitModule(self, mod):
+        for dfn in mod.dfns:
+            self.visit(dfn)
+
+    def visitType(self, type):
+        self.visit(type.value, type.name)
+
+    def visitSum(self, sum, name):
+        pass
+
+    def visitProduct(self, sum, name):
+        pass
+
+    def visitConstructor(self, cons, name):
+        pass
+
+    def visitField(self, sum):
+        pass
+
+
+class Obj2ModPrototypeVisitor(PickleVisitor):
+    def visitProduct(self, prod, name):
+        code = "static int obj2ast_%s(PyObject* obj, %s* out, PyArena* arena);"
+        self.emit(code % (name, get_c_type(name)), 0)
+
+    visitSum = visitProduct
+
+
+class Obj2ModVisitor(PickleVisitor):
+    def funcHeader(self, name):
+        ctype = get_c_type(name)
+        self.emit("int", 0)
+        self.emit("obj2ast_%s(PyObject* obj, %s* out, PyArena* arena)" % (name, ctype), 0)
+        self.emit("{", 0)
+        self.emit("PyObject* tmp = NULL;", 1)
+        self.emit("int isinstance;", 1)
+        self.emit("", 0)
+
+    def sumTrailer(self, name):
+        self.emit("", 0)
+        self.emit("tmp = PyObject_Repr(obj);", 1)
+        # there's really nothing more we can do if this fails ...
+        self.emit("if (tmp == NULL) goto failed;", 1)
+        error = "expected some sort of %s, but got %%.400s" % name
+        format = "PyErr_Format(PyExc_TypeError, \"%s\", _PyUnicode_AsString(tmp));"
+        self.emit(format % error, 1, reflow=False)
+        self.emit("failed:", 0)
+        self.emit("Py_XDECREF(tmp);", 1)
+        self.emit("return 1;", 1)
+        self.emit("}", 0)
+        self.emit("", 0)
+
+    def simpleSum(self, sum, name):
+        self.funcHeader(name)
+        for t in sum.types:
+            line = ("isinstance = PyObject_IsInstance(obj, "
+                    "(PyObject *)%s_type);")
+            self.emit(line % (t.name,), 1)
+            self.emit("if (isinstance == -1) {", 1)
+            self.emit("return 1;", 2)
+            self.emit("}", 1)
+            self.emit("if (isinstance) {", 1)
+            self.emit("*out = %s;" % t.name, 2)
+            self.emit("return 0;", 2)
+            self.emit("}", 1)
+        self.sumTrailer(name)
+
+    def buildArgs(self, fields):
+        return ", ".join(fields + ["arena"])
+
+    def complexSum(self, sum, name):
+        self.funcHeader(name)
+        for a in sum.attributes:
+            self.visitAttributeDeclaration(a, name, sum=sum)
+        self.emit("", 0)
+        # XXX: should we only do this for 'expr'?
+        self.emit("if (obj == Py_None) {", 1)
+        self.emit("*out = NULL;", 2)
+        self.emit("return 0;", 2)
+        self.emit("}", 1)
+        for a in sum.attributes:
+            self.visitField(a, name, sum=sum, depth=1)
+        for t in sum.types:
+            line = "isinstance = PyObject_IsInstance(obj, (PyObject*)%s_type);"
+            self.emit(line % (t.name,), 1)
+            self.emit("if (isinstance == -1) {", 1)
+            self.emit("return 1;", 2)
+            self.emit("}", 1)
+            self.emit("if (isinstance) {", 1)
+            for f in t.fields:
+                self.visitFieldDeclaration(f, t.name, sum=sum, depth=2)
+            self.emit("", 0)
+            for f in t.fields:
+                self.visitField(f, t.name, sum=sum, depth=2)
+            args = [f.name.value for f in t.fields] + [a.name.value for a in sum.attributes]
+            self.emit("*out = %s(%s);" % (t.name, self.buildArgs(args)), 2)
+            self.emit("if (*out == NULL) goto failed;", 2)
+            self.emit("return 0;", 2)
+            self.emit("}", 1)
+        self.sumTrailer(name)
+
+    def visitAttributeDeclaration(self, a, name, sum=sum):
+        ctype = get_c_type(a.type)
+        self.emit("%s %s;" % (ctype, a.name), 1)
+
+    def visitSum(self, sum, name):
+        if is_simple(sum):
+            self.simpleSum(sum, name)
+        else:
+            self.complexSum(sum, name)
+
+    def visitProduct(self, prod, name):
+        ctype = get_c_type(name)
+        self.emit("int", 0)
+        self.emit("obj2ast_%s(PyObject* obj, %s* out, PyArena* arena)" % (name, ctype), 0)
+        self.emit("{", 0)
+        self.emit("PyObject* tmp = NULL;", 1)
+        for f in prod.fields:
+            self.visitFieldDeclaration(f, name, prod=prod, depth=1)
+        self.emit("", 0)
+        for f in prod.fields:
+            self.visitField(f, name, prod=prod, depth=1)
+        args = [f.name.value for f in prod.fields]
+        self.emit("*out = %s(%s);" % (name, self.buildArgs(args)), 1)
+        self.emit("return 0;", 1)
+        self.emit("failed:", 0)
+        self.emit("Py_XDECREF(tmp);", 1)
+        self.emit("return 1;", 1)
+        self.emit("}", 0)
+        self.emit("", 0)
+
+    def visitFieldDeclaration(self, field, name, sum=None, prod=None, depth=0):
+        ctype = get_c_type(field.type)
+        if field.seq:
+            if self.isSimpleType(field):
+                self.emit("asdl_int_seq* %s;" % field.name, depth)
+            else:
+                self.emit("asdl_seq* %s;" % field.name, depth)
+        else:
+            ctype = get_c_type(field.type)
+            self.emit("%s %s;" % (ctype, field.name), depth)
+
+    def isSimpleSum(self, field):
+        # XXX can the members of this list be determined automatically?
+        return field.type.value in ('expr_context', 'boolop', 'operator',
+                                    'unaryop', 'cmpop')
+
+    def isNumeric(self, field):
+        return get_c_type(field.type) in ("int", "bool")
+
+    def isSimpleType(self, field):
+        return self.isSimpleSum(field) or self.isNumeric(field)
+
+    def visitField(self, field, name, sum=None, prod=None, depth=0):
+        ctype = get_c_type(field.type)
+        self.emit("if (PyObject_HasAttrString(obj, \"%s\")) {" % field.name, depth)
+        self.emit("int res;", depth+1)
+        if field.seq:
+            self.emit("Py_ssize_t len;", depth+1)
+            self.emit("Py_ssize_t i;", depth+1)
+        self.emit("tmp = PyObject_GetAttrString(obj, \"%s\");" % field.name, depth+1)
+        self.emit("if (tmp == NULL) goto failed;", depth+1)
+        if field.seq:
+            self.emit("if (!PyList_Check(tmp)) {", depth+1)
+            self.emit("PyErr_Format(PyExc_TypeError, \"%s field \\\"%s\\\" must "
+                      "be a list, not a %%.200s\", tmp->ob_type->tp_name);" %
+                      (name, field.name),
+                      depth+2, reflow=False)
+            self.emit("goto failed;", depth+2)
+            self.emit("}", depth+1)
+            self.emit("len = PyList_GET_SIZE(tmp);", depth+1)
+            if self.isSimpleType(field):
+                self.emit("%s = asdl_int_seq_new(len, arena);" % field.name, depth+1)
+            else:
+                self.emit("%s = asdl_seq_new(len, arena);" % field.name, depth+1)
+            self.emit("if (%s == NULL) goto failed;" % field.name, depth+1)
+            self.emit("for (i = 0; i < len; i++) {", depth+1)
+            self.emit("%s value;" % ctype, depth+2)
+            self.emit("res = obj2ast_%s(PyList_GET_ITEM(tmp, i), &value, arena);" %
+                      field.type, depth+2, reflow=False)
+            self.emit("if (res != 0) goto failed;", depth+2)
+            self.emit("asdl_seq_SET(%s, i, value);" % field.name, depth+2)
+            self.emit("}", depth+1)
+        else:
+            self.emit("res = obj2ast_%s(tmp, &%s, arena);" %
+                      (field.type, field.name), depth+1)
+            self.emit("if (res != 0) goto failed;", depth+1)
+
+        self.emit("Py_XDECREF(tmp);", depth+1)
+        self.emit("tmp = NULL;", depth+1)
+        self.emit("} else {", depth)
+        if not field.opt:
+            message = "required field \\\"%s\\\" missing from %s" % (field.name, name)
+            format = "PyErr_SetString(PyExc_TypeError, \"%s\");"
+            self.emit(format % message, depth+1, reflow=False)
+            self.emit("return 1;", depth+1)
+        else:
+            if self.isNumeric(field):
+                self.emit("%s = 0;" % field.name, depth+1)
+            elif not self.isSimpleType(field):
+                self.emit("%s = NULL;" % field.name, depth+1)
+            else:
+                raise TypeError("could not determine the default value for %s" % field.name)
+        self.emit("}", depth)
+
+
+class MarshalPrototypeVisitor(PickleVisitor):
+
+    def prototype(self, sum, name):
+        ctype = get_c_type(name)
+        self.emit("static int marshal_write_%s(PyObject **, int *, %s);"
+                  % (name, ctype), 0)
+
+    visitProduct = visitSum = prototype
+
+
+class PyTypesDeclareVisitor(PickleVisitor):
+
+    def visitProduct(self, prod, name):
+        self.emit("static PyTypeObject *%s_type;" % name, 0)
+        self.emit("static PyObject* ast2obj_%s(void*);" % name, 0)
+        if prod.fields:
+            self.emit("static char *%s_fields[]={" % name,0)
+            for f in prod.fields:
+                self.emit('"%s",' % f.name, 1)
+            self.emit("};", 0)
+
+    def visitSum(self, sum, name):
+        self.emit("static PyTypeObject *%s_type;" % name, 0)
+        if sum.attributes:
+            self.emit("static char *%s_attributes[] = {" % name, 0)
+            for a in sum.attributes:
+                self.emit('"%s",' % a.name, 1)
+            self.emit("};", 0)
+        ptype = "void*"
+        if is_simple(sum):
+            ptype = get_c_type(name)
+            tnames = []
+            for t in sum.types:
+                tnames.append(str(t.name)+"_singleton")
+            tnames = ", *".join(tnames)
+            self.emit("static PyObject *%s;" % tnames, 0)
+        self.emit("static PyObject* ast2obj_%s(%s);" % (name, ptype), 0)
+        for t in sum.types:
+            self.visitConstructor(t, name)
+
+    def visitConstructor(self, cons, name):
+        self.emit("static PyTypeObject *%s_type;" % cons.name, 0)
+        if cons.fields:
+            self.emit("static char *%s_fields[]={" % cons.name, 0)
+            for t in cons.fields:
+                self.emit('"%s",' % t.name, 1)
+            self.emit("};",0)
+
+class PyTypesVisitor(PickleVisitor):
+
+    def visitModule(self, mod):
+        self.emit("""
+static int
+ast_type_init(PyObject *self, PyObject *args, PyObject *kw)
+{
+    Py_ssize_t i, numfields = 0;
+    int res = -1;
+    PyObject *key, *value, *fields;
+    fields = PyObject_GetAttrString((PyObject*)Py_TYPE(self), "_fields");
+    if (!fields)
+        PyErr_Clear();
+    if (fields) {
+        numfields = PySequence_Size(fields);
+        if (numfields == -1)
+            goto cleanup;
+    }
+    res = 0; /* if no error occurs, this stays 0 to the end */
+    if (PyTuple_GET_SIZE(args) > 0) {
+        if (numfields != PyTuple_GET_SIZE(args)) {
+            PyErr_Format(PyExc_TypeError, "%.400s constructor takes %s"
+                         "%zd positional argument%s",
+                         Py_TYPE(self)->tp_name,
+                         numfields == 0 ? "" : "either 0 or ",
+                         numfields, numfields == 1 ? "" : "s");
+            res = -1;
+            goto cleanup;
+        }
+        for (i = 0; i < PyTuple_GET_SIZE(args); i++) {
+            /* cannot be reached when fields is NULL */
+            PyObject *name = PySequence_GetItem(fields, i);
+            if (!name) {
+                res = -1;
+                goto cleanup;
+            }
+            res = PyObject_SetAttr(self, name, PyTuple_GET_ITEM(args, i));
+            Py_DECREF(name);
+            if (res < 0)
+                goto cleanup;
+        }
+    }
+    if (kw) {
+        i = 0;  /* needed by PyDict_Next */
+        while (PyDict_Next(kw, &i, &key, &value)) {
+            res = PyObject_SetAttr(self, key, value);
+            if (res < 0)
+                goto cleanup;
+        }
+    }
+  cleanup:
+    Py_XDECREF(fields);
+    return res;
+}
+
+/* Pickling support */
+static PyObject *
+ast_type_reduce(PyObject *self, PyObject *unused)
+{
+    PyObject *res;
+    PyObject *dict = PyObject_GetAttrString(self, "__dict__");
+    if (dict == NULL) {
+        if (PyErr_ExceptionMatches(PyExc_AttributeError))
+            PyErr_Clear();
+        else
+            return NULL;
+    }
+    if (dict) {
+        res = Py_BuildValue("O()O", Py_TYPE(self), dict);
+        Py_DECREF(dict);
+        return res;
+    }
+    return Py_BuildValue("O()", Py_TYPE(self));
+}
+
+static PyMethodDef ast_type_methods[] = {
+    {"__reduce__", ast_type_reduce, METH_NOARGS, NULL},
+    {NULL}
+};
+
+static PyTypeObject AST_type = {
+    PyVarObject_HEAD_INIT(&PyType_Type, 0)
+    "_ast27.AST",
+    sizeof(PyObject),
+    0,
+    0,                       /* tp_dealloc */
+    0,                       /* tp_print */
+    0,                       /* tp_getattr */
+    0,                       /* tp_setattr */
+    0,                       /* tp_compare */
+    0,                       /* tp_repr */
+    0,                       /* tp_as_number */
+    0,                       /* tp_as_sequence */
+    0,                       /* tp_as_mapping */
+    0,                       /* tp_hash */
+    0,                       /* tp_call */
+    0,                       /* tp_str */
+    PyObject_GenericGetAttr, /* tp_getattro */
+    PyObject_GenericSetAttr, /* tp_setattro */
+    0,                       /* tp_as_buffer */
+    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+    0,                       /* tp_doc */
+    0,                       /* tp_traverse */
+    0,                       /* tp_clear */
+    0,                       /* tp_richcompare */
+    0,                       /* tp_weaklistoffset */
+    0,                       /* tp_iter */
+    0,                       /* tp_iternext */
+    ast_type_methods,        /* tp_methods */
+    0,                       /* tp_members */
+    0,                       /* tp_getset */
+    0,                       /* tp_base */
+    0,                       /* tp_dict */
+    0,                       /* tp_descr_get */
+    0,                       /* tp_descr_set */
+    0,                       /* tp_dictoffset */
+    (initproc)ast_type_init, /* tp_init */
+    PyType_GenericAlloc,     /* tp_alloc */
+    PyType_GenericNew,       /* tp_new */
+    PyObject_Del,            /* tp_free */
+};
+
+
+static PyTypeObject* make_type(char *type, PyTypeObject* base, char**fields, int num_fields)
+{
+    PyObject *fnames, *result;
+    int i;
+    fnames = PyTuple_New(num_fields);
+    if (!fnames) return NULL;
+    for (i = 0; i < num_fields; i++) {
+        PyObject *field = PyUnicode_FromString(fields[i]);
+        if (!field) {
+            Py_DECREF(fnames);
+            return NULL;
+        }
+        PyTuple_SET_ITEM(fnames, i, field);
+    }
+    result = PyObject_CallFunction((PyObject*)&PyType_Type, "s(O){sOss}",
+                    type, base, "_fields", fnames, "__module__", "_ast27");
+    Py_DECREF(fnames);
+    return (PyTypeObject*)result;
+}
+
+static int add_attributes(PyTypeObject* type, char**attrs, int num_fields)
+{
+    int i, result;
+    PyObject *s, *l = PyTuple_New(num_fields);
+    if (!l)
+        return 0;
+    for (i = 0; i < num_fields; i++) {
+        s = PyUnicode_FromString(attrs[i]);
+        if (!s) {
+            Py_DECREF(l);
+            return 0;
+        }
+        PyTuple_SET_ITEM(l, i, s);
+    }
+    result = PyObject_SetAttrString((PyObject*)type, "_attributes", l) >= 0;
+    Py_DECREF(l);
+    return result;
+}
+
+/* Conversion AST -> Python */
+
+static PyObject* ast2obj_list(asdl_seq *seq, PyObject* (*func)(void*))
+{
+    int i, n = asdl_seq_LEN(seq);
+    PyObject *result = PyList_New(n);
+    PyObject *value;
+    if (!result)
+        return NULL;
+    for (i = 0; i < n; i++) {
+        value = func(asdl_seq_GET(seq, i));
+        if (!value) {
+            Py_DECREF(result);
+            return NULL;
+        }
+        PyList_SET_ITEM(result, i, value);
+    }
+    return result;
+}
+
+static PyObject* ast2obj_object(void *o)
+{
+    if (!o)
+        o = Py_None;
+    Py_INCREF((PyObject*)o);
+    return (PyObject*)o;
+}
+#define ast2obj_identifier ast2obj_object
+#define ast2obj_string ast2obj_object
+static PyObject* ast2obj_bool(bool b)
+{
+    return PyBool_FromLong(b);
+}
+
+static PyObject* ast2obj_int(long b)
+{
+    return PyLong_FromLong(b);
+}
+
+/* Conversion Python -> AST */
+
+static int obj2ast_object(PyObject* obj, PyObject** out, PyArena* arena)
+{
+    if (obj == Py_None)
+        obj = NULL;
+    if (obj)
+        PyArena_AddPyObject(arena, obj);
+    Py_XINCREF(obj);
+    *out = obj;
+    return 0;
+}
+
+static int obj2ast_identifier(PyObject* obj, PyObject** out, PyArena* arena)
+{
+    if (!PyUnicode_CheckExact(obj) && obj != Py_None) {
+        PyErr_Format(PyExc_TypeError,
+                    "AST identifier must be of type str");
+        return 1;
+    }
+    return obj2ast_object(obj, out, arena);
+}
+
+static int obj2ast_string(PyObject* obj, PyObject** out, PyArena* arena)
+{
+    if (!PyUnicode_CheckExact(obj) && !PyUnicode_CheckExact(obj)) {
+        PyErr_SetString(PyExc_TypeError,
+                       "AST string must be of type str or unicode");
+        return 1;
+    }
+    return obj2ast_object(obj, out, arena);
+}
+
+static int obj2ast_int(PyObject* obj, int* out, PyArena* arena)
+{
+    int i;
+    if (!PyLong_Check(obj) && !PyLong_Check(obj)) {
+        PyObject *s = PyObject_Repr(obj);
+        if (s == NULL) return 1;
+        PyErr_Format(PyExc_ValueError, "invalid integer value: %.400s",
+                     _PyUnicode_AsString(s));
+        Py_DECREF(s);
+        return 1;
+    }
+
+    i = (int)PyLong_AsLong(obj);
+    if (i == -1 && PyErr_Occurred())
+        return 1;
+    *out = i;
+    return 0;
+}
+
+static int obj2ast_bool(PyObject* obj, bool* out, PyArena* arena)
+{
+    if (!PyBool_Check(obj)) {
+        PyObject *s = PyObject_Repr(obj);
+        if (s == NULL) return 1;
+        PyErr_Format(PyExc_ValueError, "invalid boolean value: %.400s",
+                     _PyUnicode_AsString(s));
+        Py_DECREF(s);
+        return 1;
+    }
+
+    *out = (obj == Py_True);
+    return 0;
+}
+
+static int add_ast_fields(void)
+{
+    PyObject *empty_tuple, *d;
+    if (PyType_Ready(&AST_type) < 0)
+        return -1;
+    d = AST_type.tp_dict;
+    empty_tuple = PyTuple_New(0);
+    if (!empty_tuple ||
+        PyDict_SetItemString(d, "_fields", empty_tuple) < 0 ||
+        PyDict_SetItemString(d, "_attributes", empty_tuple) < 0) {
+        Py_XDECREF(empty_tuple);
+        return -1;
+    }
+    Py_DECREF(empty_tuple);
+    return 0;
+}
+
+""", 0, reflow=False)
+
+        self.emit("static int init_types(void)",0)
+        self.emit("{", 0)
+        self.emit("static int initialized;", 1)
+        self.emit("if (initialized) return 1;", 1)
+        self.emit("if (add_ast_fields() < 0) return 0;", 1)
+        for dfn in mod.dfns:
+            self.visit(dfn)
+        self.emit("initialized = 1;", 1)
+        self.emit("return 1;", 1);
+        self.emit("}", 0)
+
+    def visitProduct(self, prod, name):
+        if prod.fields:
+            fields = name.value+"_fields"
+        else:
+            fields = "NULL"
+        self.emit('%s_type = make_type("%s", &AST_type, %s, %d);' %
+                        (name, name, fields, len(prod.fields)), 1)
+        self.emit("if (!%s_type) return 0;" % name, 1)
+
+    def visitSum(self, sum, name):
+        self.emit('%s_type = make_type("%s", &AST_type, NULL, 0);' %
+                  (name, name), 1)
+        self.emit("if (!%s_type) return 0;" % name, 1)
+        if sum.attributes:
+            self.emit("if (!add_attributes(%s_type, %s_attributes, %d)) return 0;" %
+                            (name, name, len(sum.attributes)), 1)
+        else:
+            self.emit("if (!add_attributes(%s_type, NULL, 0)) return 0;" % name, 1)
+        simple = is_simple(sum)
+        for t in sum.types:
+            self.visitConstructor(t, name, simple)
+
+    def visitConstructor(self, cons, name, simple):
+        if cons.fields:
+            fields = cons.name.value+"_fields"
+        else:
+            fields = "NULL"
+        self.emit('%s_type = make_type("%s", %s_type, %s, %d);' %
+                            (cons.name, cons.name, name, fields, len(cons.fields)), 1)
+        self.emit("if (!%s_type) return 0;" % cons.name, 1)
+        if simple:
+            self.emit("%s_singleton = PyType_GenericNew(%s_type, NULL, NULL);" %
+                             (cons.name, cons.name), 1)
+            self.emit("if (!%s_singleton) return 0;" % cons.name, 1)
+
+
+class ASTModuleVisitor(PickleVisitor):
+
+    def visitModule(self, mod):
+        self.emit('PyObject *ast27_parse(PyObject *self, PyObject *args);', 0)
+        self.emit('static PyMethodDef ast27_methods[] = {', 0)
+        self.emit('{"parse",  ast27_parse, METH_VARARGS, "Parse string into typed AST."},', 1)
+        self.emit('{NULL, NULL, 0, NULL}', 1)
+        self.emit('};', 0)
+
+        self.emit("static struct PyModuleDef _astmodule27 = {", 0)
+        self.emit('  PyModuleDef_HEAD_INIT, "_ast27", NULL, 0, ast27_methods', 0)
+        self.emit("};", 0)
+        self.emit("PyMODINIT_FUNC", 0)
+        self.emit("PyInit__ast27(void)", 0)
+        self.emit("{", 0)
+        self.emit("PyObject *m, *d;", 1)
+        self.emit("if (!init_types()) return NULL;", 1)
+        self.emit('m = PyModule_Create(&_astmodule27);', 1)
+        self.emit("if (!m) return NULL;", 1)
+        self.emit("d = PyModule_GetDict(m);", 1)
+        self.emit('if (PyDict_SetItemString(d, "AST", (PyObject*)&AST_type) < 0) return NULL;', 1)
+        self.emit('if (PyModule_AddIntMacro(m, PyCF_ONLY_AST) < 0)', 1)
+        self.emit("return NULL;", 2)
+        for dfn in mod.dfns:
+            self.visit(dfn)
+        self.emit("return m;", 1)
+        self.emit("}", 0)
+
+    def visitProduct(self, prod, name):
+        self.addObj(name)
+
+    def visitSum(self, sum, name):
+        self.addObj(name)
+        for t in sum.types:
+            self.visitConstructor(t, name)
+
+    def visitConstructor(self, cons, name):
+        self.addObj(cons.name)
+
+    def addObj(self, name):
+        self.emit('if (PyDict_SetItemString(d, "%s", (PyObject*)%s_type) < 0) return NULL;' % (name, name), 1)
+
+
+_SPECIALIZED_SEQUENCES = ('stmt', 'expr')
+
+def find_sequence(fields, doing_specialization):
+    """Return True if any field uses a sequence."""
+    for f in fields:
+        if f.seq:
+            if not doing_specialization:
+                return True
+            if str(f.type) not in _SPECIALIZED_SEQUENCES:
+                return True
+    return False
+
+def has_sequence(types, doing_specialization):
+    for t in types:
+        if find_sequence(t.fields, doing_specialization):
+            return True
+    return False
+
+
+class StaticVisitor(PickleVisitor):
+    CODE = '''Very simple, always emit this static code.  Override CODE'''
+
+    def visit(self, object):
+        self.emit(self.CODE, 0, reflow=False)
+
+
+class ObjVisitor(PickleVisitor):
+
+    def func_begin(self, name):
+        ctype = get_c_type(name)
+        self.emit("PyObject*", 0)
+        self.emit("ast2obj_%s(void* _o)" % (name), 0)
+        self.emit("{", 0)
+        self.emit("%s o = (%s)_o;" % (ctype, ctype), 1)
+        self.emit("PyObject *result = NULL, *value = NULL;", 1)
+        self.emit('if (!o) {', 1)
+        self.emit("Py_INCREF(Py_None);", 2)
+        self.emit('return Py_None;', 2)
+        self.emit("}", 1)
+        self.emit('', 0)
+
+    def func_end(self):
+        self.emit("return result;", 1)
+        self.emit("failed:", 0)
+        self.emit("Py_XDECREF(value);", 1)
+        self.emit("Py_XDECREF(result);", 1)
+        self.emit("return NULL;", 1)
+        self.emit("}", 0)
+        self.emit("", 0)
+
+    def visitSum(self, sum, name):
+        if is_simple(sum):
+            self.simpleSum(sum, name)
+            return
+        self.func_begin(name)
+        self.emit("switch (o->kind) {", 1)
+        for i in range(len(sum.types)):
+            t = sum.types[i]
+            self.visitConstructor(t, i + 1, name)
+        self.emit("}", 1)
+        for a in sum.attributes:
+            self.emit("value = ast2obj_%s(o->%s);" % (a.type, a.name), 1)
+            self.emit("if (!value) goto failed;", 1)
+            self.emit('if (PyObject_SetAttrString(result, "%s", value) < 0)' % a.name, 1)
+            self.emit('goto failed;', 2)
+            self.emit('Py_DECREF(value);', 1)
+        self.func_end()
+
+    def simpleSum(self, sum, name):
+        self.emit("PyObject* ast2obj_%s(%s_ty o)" % (name, name), 0)
+        self.emit("{", 0)
+        self.emit("switch(o) {", 1)
+        for t in sum.types:
+            self.emit("case %s:" % t.name, 2)
+            self.emit("Py_INCREF(%s_singleton);" % t.name, 3)
+            self.emit("return %s_singleton;" % t.name, 3)
+        self.emit("default:", 2)
+        self.emit('/* should never happen, but just in case ... */', 3)
+        code = "PyErr_Format(PyExc_SystemError, \"unknown %s found\");" % name
+        self.emit(code, 3, reflow=False)
+        self.emit("return NULL;", 3)
+        self.emit("}", 1)
+        self.emit("}", 0)
+
+    def visitProduct(self, prod, name):
+        self.func_begin(name)
+        self.emit("result = PyType_GenericNew(%s_type, NULL, NULL);" % name, 1);
+        self.emit("if (!result) return NULL;", 1)
+        for field in prod.fields:
+            self.visitField(field, name, 1, True)
+        self.func_end()
+
+    def visitConstructor(self, cons, enum, name):
+        self.emit("case %s_kind:" % cons.name, 1)
+        self.emit("result = PyType_GenericNew(%s_type, NULL, NULL);" % cons.name, 2);
+        self.emit("if (!result) goto failed;", 2)
+        for f in cons.fields:
+            self.visitField(f, cons.name, 2, False)
+        self.emit("break;", 2)
+
+    def visitField(self, field, name, depth, product):
+        def emit(s, d):
+            self.emit(s, depth + d)
+        if product:
+            value = "o->%s" % field.name
+        else:
+            value = "o->v.%s.%s" % (name, field.name)
+        self.set(field, value, depth)
+        emit("if (!value) goto failed;", 0)
+        emit('if (PyObject_SetAttrString(result, "%s", value) == -1)' % field.name, 0)
+        emit("goto failed;", 1)
+        emit("Py_DECREF(value);", 0)
+
+    def emitSeq(self, field, value, depth, emit):
+        emit("seq = %s;" % value, 0)
+        emit("n = asdl_seq_LEN(seq);", 0)
+        emit("value = PyList_New(n);", 0)
+        emit("if (!value) goto failed;", 0)
+        emit("for (i = 0; i < n; i++) {", 0)
+        self.set("value", field, "asdl_seq_GET(seq, i)", depth + 1)
+        emit("if (!value1) goto failed;", 1)
+        emit("PyList_SET_ITEM(value, i, value1);", 1)
+        emit("value1 = NULL;", 1)
+        emit("}", 0)
+
+    def set(self, field, value, depth):
+        if field.seq:
+            # XXX should really check for is_simple, but that requires a symbol table
+            if field.type.value == "cmpop":
+                # While the sequence elements are stored as void*,
+                # ast2obj_cmpop expects an enum
+                self.emit("{", depth)
+                self.emit("int i, n = asdl_seq_LEN(%s);" % value, depth+1)
+                self.emit("value = PyList_New(n);", depth+1)
+                self.emit("if (!value) goto failed;", depth+1)
+                self.emit("for(i = 0; i < n; i++)", depth+1)
+                # This cannot fail, so no need for error handling
+                self.emit("PyList_SET_ITEM(value, i, ast2obj_cmpop((cmpop_ty)asdl_seq_GET(%s, i)));" % value,
+                          depth+2, reflow=False)
+                self.emit("}", depth)
+            else:
+                self.emit("value = ast2obj_list(%s, ast2obj_%s);" % (value, field.type), depth)
+        else:
+            ctype = get_c_type(field.type)
+            self.emit("value = ast2obj_%s(%s);" % (field.type, value), depth, reflow=False)
+
+
+class PartingShots(StaticVisitor):
+
+    CODE = """
+PyObject* Ta27AST_mod2obj(mod_ty t)
+{
+    init_types();
+    return ast2obj_mod(t);
+}
+
+/* mode is 0 for "exec", 1 for "eval" and 2 for "single" input */
+mod_ty Ta27AST_obj2mod(PyObject* ast, PyArena* arena, int mode)
+{
+    mod_ty res;
+    PyObject *req_type[3];
+    char *req_name[3];
+    int isinstance;
+
+    req_type[0] = (PyObject*)Module_type;
+    req_type[1] = (PyObject*)Expression_type;
+    req_type[2] = (PyObject*)Interactive_type;
+
+    req_name[0] = "Module";
+    req_name[1] = "Expression";
+    req_name[2] = "Interactive";
+
+    assert(0 <= mode && mode <= 2);
+
+    init_types();
+
+    isinstance = PyObject_IsInstance(ast, req_type[mode]);
+    if (isinstance == -1)
+        return NULL;
+    if (!isinstance) {
+        PyErr_Format(PyExc_TypeError, "expected %s node, got %.400s",
+                     req_name[mode], Py_TYPE(ast)->tp_name);
+        return NULL;
+    }
+    if (obj2ast_mod(ast, &res, arena) != 0)
+        return NULL;
+    else
+        return res;
+}
+
+int Ta27AST_Check(PyObject* obj)
+{
+    init_types();
+    return PyObject_IsInstance(obj, (PyObject*)&AST_type);
+}
+"""
+
+class ChainOfVisitors:
+    def __init__(self, *visitors):
+        self.visitors = visitors
+
+    def visit(self, object):
+        for v in self.visitors:
+            v.visit(object)
+            v.emit("", 0)
+
+common_msg = "/* File automatically generated by %s. */\n\n"
+
+c_file_msg = """
+/*
+   __version__ %s.
+
+   This module must be committed separately after each AST grammar change;
+   The __version__ number is set to the revision number of the commit
+   containing the grammar change.
+*/
+
+"""
+
+def main(srcfile):
+    argv0 = sys.argv[0]
+    components = argv0.split(os.sep)
+    argv0 = os.sep.join(components[-2:])
+    auto_gen_msg = common_msg % argv0
+    mod = asdl.parse(srcfile)
+    mod.version = "82160"
+    if not asdl.check(mod):
+        sys.exit(1)
+    if INC_DIR:
+        p = "%s/%s-ast.h" % (INC_DIR, mod.name)
+        f = open(p, "wb")
+        f.write(auto_gen_msg)
+        f.write('#include "asdl.h"\n\n')
+        c = ChainOfVisitors(TypeDefVisitor(f),
+                            StructVisitor(f),
+                            PrototypeVisitor(f),
+                            )
+        c.visit(mod)
+        f.write("PyObject* Ta27AST_mod2obj(mod_ty t);\n")
+        f.write("mod_ty Ta27AST_obj2mod(PyObject* ast, PyArena* arena, int mode);\n")
+        f.write("int Ta27AST_Check(PyObject* obj);\n")
+        f.close()
+
+    if SRC_DIR:
+        p = os.path.join(SRC_DIR, str(mod.name) + "-ast.c")
+        f = open(p, "wb")
+        f.write(auto_gen_msg)
+        f.write(c_file_msg % mod.version)
+        f.write('#include "Python.h"\n')
+        f.write('#include "%s-ast.h"\n' % mod.name)
+        f.write('\n')
+        f.write("static PyTypeObject AST_type;\n")
+        v = ChainOfVisitors(
+            PyTypesDeclareVisitor(f),
+            PyTypesVisitor(f),
+            Obj2ModPrototypeVisitor(f),
+            FunctionVisitor(f),
+            ObjVisitor(f),
+            Obj2ModVisitor(f),
+            ASTModuleVisitor(f),
+            PartingShots(f),
+            )
+        v.visit(mod)
+        f.close()
+
+if __name__ == "__main__":
+    import sys
+    import getopt
+
+    INC_DIR = ''
+    SRC_DIR = ''
+    opts, args = getopt.getopt(sys.argv[1:], "h:c:")
+    if len(opts) != 1:
+        print "Must specify exactly one output file"
+        sys.exit(1)
+    for o, v in opts:
+        if o == '-h':
+            INC_DIR = v
+        if o == '-c':
+            SRC_DIR = v
+    if len(args) != 1:
+        print "Must specify single input file"
+        sys.exit(1)
+    main(args[0])
diff --git a/ast27/Parser/bitset.c b/ast27/Parser/bitset.c
new file mode 100644
index 0000000..f5bfd41
--- /dev/null
+++ b/ast27/Parser/bitset.c
@@ -0,0 +1,66 @@
+
+/* Bitset primitives used by the parser generator */
+
+#include "pgenheaders.h"
+#include "bitset.h"
+
+bitset
+newbitset(int nbits)
+{
+    int nbytes = NBYTES(nbits);
+    bitset ss = (char *)PyObject_MALLOC(sizeof(BYTE) *  nbytes);
+
+    if (ss == NULL)
+        Py_FatalError("no mem for bitset");
+
+    ss += nbytes;
+    while (--nbytes >= 0)
+        *--ss = 0;
+    return ss;
+}
+
+void
+delbitset(bitset ss)
+{
+    PyObject_FREE(ss);
+}
+
+int
+addbit(bitset ss, int ibit)
+{
+    int ibyte = BIT2BYTE(ibit);
+    BYTE mask = BIT2MASK(ibit);
+
+    if (ss[ibyte] & mask)
+        return 0; /* Bit already set */
+    ss[ibyte] |= mask;
+    return 1;
+}
+
+#if 0 /* Now a macro */
+int
+testbit(bitset ss, int ibit)
+{
+    return (ss[BIT2BYTE(ibit)] & BIT2MASK(ibit)) != 0;
+}
+#endif
+
+int
+samebitset(bitset ss1, bitset ss2, int nbits)
+{
+    int i;
+
+    for (i = NBYTES(nbits); --i >= 0; )
+        if (*ss1++ != *ss2++)
+            return 0;
+    return 1;
+}
+
+void
+mergebitset(bitset ss1, bitset ss2, int nbits)
+{
+    int i;
+
+    for (i = NBYTES(nbits); --i >= 0; )
+        *ss1++ |= *ss2++;
+}
diff --git a/ast27/Parser/grammar.c b/ast27/Parser/grammar.c
new file mode 100644
index 0000000..e21fb87
--- /dev/null
+++ b/ast27/Parser/grammar.c
@@ -0,0 +1,254 @@
+
+/* Grammar implementation */
+
+#include "Python.h"
+#include "pgenheaders.h"
+
+#include <ctype.h>
+
+#include "token.h"
+#include "grammar.h"
+
+#ifdef RISCOS
+#include <unixlib.h>
+#endif
+
+extern int Py_DebugFlag;
+
+grammar *
+newgrammar(int start)
+{
+    grammar *g;
+
+    g = (grammar *)PyObject_MALLOC(sizeof(grammar));
+    if (g == NULL)
+        Py_FatalError("no mem for new grammar");
+    g->g_ndfas = 0;
+    g->g_dfa = NULL;
+    g->g_start = start;
+    g->g_ll.ll_nlabels = 0;
+    g->g_ll.ll_label = NULL;
+    g->g_accel = 0;
+    return g;
+}
+
+dfa *
+adddfa(grammar *g, int type, char *name)
+{
+    dfa *d;
+
+    g->g_dfa = (dfa *)PyObject_REALLOC(g->g_dfa,
+                                        sizeof(dfa) * (g->g_ndfas + 1));
+    if (g->g_dfa == NULL)
+        Py_FatalError("no mem to resize dfa in adddfa");
+    d = &g->g_dfa[g->g_ndfas++];
+    d->d_type = type;
+    d->d_name = strdup(name);
+    d->d_nstates = 0;
+    d->d_state = NULL;
+    d->d_initial = -1;
+    d->d_first = NULL;
+    return d; /* Only use while fresh! */
+}
+
+int
+addstate(dfa *d)
+{
+    state *s;
+
+    d->d_state = (state *)PyObject_REALLOC(d->d_state,
+                                  sizeof(state) * (d->d_nstates + 1));
+    if (d->d_state == NULL)
+        Py_FatalError("no mem to resize state in addstate");
+    s = &d->d_state[d->d_nstates++];
+    s->s_narcs = 0;
+    s->s_arc = NULL;
+    s->s_lower = 0;
+    s->s_upper = 0;
+    s->s_accel = NULL;
+    s->s_accept = 0;
+    return s - d->d_state;
+}
+
+void
+addarc(dfa *d, int from, int to, int lbl)
+{
+    state *s;
+    arc *a;
+
+    assert(0 <= from && from < d->d_nstates);
+    assert(0 <= to && to < d->d_nstates);
+
+    s = &d->d_state[from];
+    s->s_arc = (arc *)PyObject_REALLOC(s->s_arc, sizeof(arc) * (s->s_narcs + 1));
+    if (s->s_arc == NULL)
+        Py_FatalError("no mem to resize arc list in addarc");
+    a = &s->s_arc[s->s_narcs++];
+    a->a_lbl = lbl;
+    a->a_arrow = to;
+}
+
+int
+addlabel(labellist *ll, int type, char *str)
+{
+    int i;
+    label *lb;
+
+    for (i = 0; i < ll->ll_nlabels; i++) {
+        if (ll->ll_label[i].lb_type == type &&
+            strcmp(ll->ll_label[i].lb_str, str) == 0)
+            return i;
+    }
+    ll->ll_label = (label *)PyObject_REALLOC(ll->ll_label,
+                                    sizeof(label) * (ll->ll_nlabels + 1));
+    if (ll->ll_label == NULL)
+        Py_FatalError("no mem to resize labellist in addlabel");
+    lb = &ll->ll_label[ll->ll_nlabels++];
+    lb->lb_type = type;
+    lb->lb_str = strdup(str);
+    if (Py_DebugFlag)
+        printf("Label @ %8p, %d: %s\n", ll, ll->ll_nlabels,
+               Ta27Grammar_LabelRepr(lb));
+    return lb - ll->ll_label;
+}
+
+/* Same, but rather dies than adds */
+
+int
+findlabel(labellist *ll, int type, char *str)
+{
+    int i;
+
+    for (i = 0; i < ll->ll_nlabels; i++) {
+        if (ll->ll_label[i].lb_type == type /*&&
+            strcmp(ll->ll_label[i].lb_str, str) == 0*/)
+            return i;
+    }
+    fprintf(stderr, "Label %d/'%s' not found\n", type, str);
+    Py_FatalError("grammar.c:findlabel()");
+    return 0; /* Make gcc -Wall happy */
+}
+
+/* Forward */
+static void translabel(grammar *, label *);
+
+void
+translatelabels(grammar *g)
+{
+    int i;
+
+#ifdef Py_DEBUG
+    printf("Translating labels ...\n");
+#endif
+    /* Don't translate EMPTY */
+    for (i = EMPTY+1; i < g->g_ll.ll_nlabels; i++)
+        translabel(g, &g->g_ll.ll_label[i]);
+}
+
+static void
+translabel(grammar *g, label *lb)
+{
+    int i;
+
+    if (Py_DebugFlag)
+        printf("Translating label %s ...\n", Ta27Grammar_LabelRepr(lb));
+
+    if (lb->lb_type == NAME) {
+        for (i = 0; i < g->g_ndfas; i++) {
+            if (strcmp(lb->lb_str, g->g_dfa[i].d_name) == 0) {
+                if (Py_DebugFlag)
+                    printf(
+                        "Label %s is non-terminal %d.\n",
+                        lb->lb_str,
+                        g->g_dfa[i].d_type);
+                lb->lb_type = g->g_dfa[i].d_type;
+                free(lb->lb_str);
+                lb->lb_str = NULL;
+                return;
+            }
+        }
+        for (i = 0; i < (int)N_TOKENS; i++) {
+            if (strcmp(lb->lb_str, _Ta27Parser_TokenNames[i]) == 0) {
+                if (Py_DebugFlag)
+                    printf("Label %s is terminal %d.\n",
+                        lb->lb_str, i);
+                lb->lb_type = i;
+                free(lb->lb_str);
+                lb->lb_str = NULL;
+                return;
+            }
+        }
+        printf("Can't translate NAME label '%s'\n", lb->lb_str);
+        return;
+    }
+
+    if (lb->lb_type == STRING) {
+        if (isalpha(Py_CHARMASK(lb->lb_str[1])) ||
+            lb->lb_str[1] == '_') {
+            char *p;
+            char *src;
+            char *dest;
+            size_t name_len;
+            if (Py_DebugFlag)
+                printf("Label %s is a keyword\n", lb->lb_str);
+            lb->lb_type = NAME;
+            src = lb->lb_str + 1;
+            p = strchr(src, '\'');
+            if (p)
+                name_len = p - src;
+            else
+                name_len = strlen(src);
+            dest = (char *)malloc(name_len + 1);
+            if (!dest) {
+                printf("Can't alloc dest '%s'\n", src);
+                return;
+            }
+            strncpy(dest, src, name_len);
+            dest[name_len] = '\0';
+            free(lb->lb_str);
+            lb->lb_str = dest;
+        }
+        else if (lb->lb_str[2] == lb->lb_str[0]) {
+            int type = (int) Ta27Token_OneChar(lb->lb_str[1]);
+            if (type != OP) {
+                lb->lb_type = type;
+                free(lb->lb_str);
+                lb->lb_str = NULL;
+            }
+            else
+                printf("Unknown OP label %s\n",
+                    lb->lb_str);
+        }
+        else if (lb->lb_str[2] && lb->lb_str[3] == lb->lb_str[0]) {
+            int type = (int) Ta27Token_TwoChars(lb->lb_str[1],
+                                       lb->lb_str[2]);
+            if (type != OP) {
+                lb->lb_type = type;
+                free(lb->lb_str);
+                lb->lb_str = NULL;
+            }
+            else
+                printf("Unknown OP label %s\n",
+                    lb->lb_str);
+        }
+        else if (lb->lb_str[2] && lb->lb_str[3] && lb->lb_str[4] == lb->lb_str[0]) {
+            int type = (int) Ta27Token_ThreeChars(lb->lb_str[1],
+                                                lb->lb_str[2],
+                                                lb->lb_str[3]);
+            if (type != OP) {
+                lb->lb_type = type;
+                free(lb->lb_str);
+                lb->lb_str = NULL;
+            }
+            else
+                printf("Unknown OP label %s\n",
+                    lb->lb_str);
+        }
+        else
+            printf("Can't translate STRING label %s\n",
+                lb->lb_str);
+    }
+    else
+        printf("Can't translate label '%s'\n",
+               Ta27Grammar_LabelRepr(lb));
+}
diff --git a/ast27/Parser/grammar1.c b/ast27/Parser/grammar1.c
new file mode 100644
index 0000000..6ba64ed
--- /dev/null
+++ b/ast27/Parser/grammar1.c
@@ -0,0 +1,57 @@
+
+/* Grammar subroutines needed by parser */
+
+#include "Python.h"
+#include "pgenheaders.h"
+#include "grammar.h"
+#include "token.h"
+
+/* Return the DFA for the given type */
+
+dfa *
+Ta27Grammar_FindDFA(grammar *g, register int type)
+{
+    register dfa *d;
+#if 1
+    /* Massive speed-up */
+    d = &g->g_dfa[type - NT_OFFSET];
+    assert(d->d_type == type);
+    return d;
+#else
+    /* Old, slow version */
+    register int i;
+
+    for (i = g->g_ndfas, d = g->g_dfa; --i >= 0; d++) {
+        if (d->d_type == type)
+            return d;
+    }
+    assert(0);
+    /* NOTREACHED */
+#endif
+}
+
+char *
+Ta27Grammar_LabelRepr(label *lb)
+{
+    static char buf[100];
+
+    if (lb->lb_type == ENDMARKER)
+        return "EMPTY";
+    else if (ISNONTERMINAL(lb->lb_type)) {
+        if (lb->lb_str == NULL) {
+            PyOS_snprintf(buf, sizeof(buf), "NT%d", lb->lb_type);
+            return buf;
+        }
+        else
+            return lb->lb_str;
+    }
+    else {
+        if (lb->lb_str == NULL)
+            return _Ta27Parser_TokenNames[lb->lb_type];
+        else {
+            PyOS_snprintf(buf, sizeof(buf), "%.32s(%.32s)",
+                _Ta27Parser_TokenNames[lb->lb_type], lb->lb_str);
+            return buf;
+        }
+    }
+}
diff --git a/ast27/Parser/node.c b/ast27/Parser/node.c
new file mode 100644
index 0000000..e43e2cb
--- /dev/null
+++ b/ast27/Parser/node.c
@@ -0,0 +1,164 @@
+/* Parse tree node implementation */
+
+#include "Python.h"
+#include "node.h"
+#include "errcode.h"
+
+node *
+Ta27Node_New(int type)
+{
+    node *n = (node *) PyObject_MALLOC(1 * sizeof(node));
+    if (n == NULL)
+        return NULL;
+    n->n_type = type;
+    n->n_str = NULL;
+    n->n_lineno = 0;
+    n->n_nchildren = 0;
+    n->n_child = NULL;
+    return n;
+}
+
+/* See comments at XXXROUNDUP below.  Returns -1 on overflow. */
+static int
+fancy_roundup(int n)
+{
+    /* Round up to the closest power of 2 >= n. */
+    int result = 256;
+    assert(n > 128);
+    while (result < n) {
+        result <<= 1;
+        if (result <= 0)
+            return -1;
+    }
+    return result;
+}
+
+/* A gimmick to make massive numbers of reallocs quicker.  The result is
+ * a number >= the input.  In Ta27Node_AddChild, it's used like so, when
+ * we're about to add child number current_size + 1:
+ *
+ *     if XXXROUNDUP(current_size) < XXXROUNDUP(current_size + 1):
+ *         allocate space for XXXROUNDUP(current_size + 1) total children
+ *     else:
+ *         we already have enough space
+ *
+ * Since a node starts out empty, we must have
+ *
+ *     XXXROUNDUP(0) < XXXROUNDUP(1)
+ *
+ * so that we allocate space for the first child.  One-child nodes are very
+ * common (presumably that would change if we used a more abstract form
+ * of syntax tree), so to avoid wasting memory it's desirable that
+ * XXXROUNDUP(1) == 1.  That in turn forces XXXROUNDUP(0) == 0.
+ *
+ * Else for 2 <= n <= 128, we round up to the closest multiple of 4.  Why 4?
+ * Rounding up to a multiple of an exact power of 2 is very efficient, and
+ * most nodes with more than one child have <= 4 kids.
+ *
+ * Else we call fancy_roundup() to grow proportionately to n.  We've got an
+ * extreme case then (like test_longexp.py), and on many platforms doing
+ * anything less than proportional growth leads to exorbitant runtime
+ * (e.g., MacPython), or extreme fragmentation of user address space (e.g.,
+ * Win98).
+ *
+ * In a run of compileall across the 2.3a0 Lib directory, Andrew MacIntyre
+ * reported that, with this scheme, 89% of PyObject_REALLOC calls in
+ * Ta27Node_AddChild passed 1 for the size, and 9% passed 4.  So this usually
+ * wastes very little memory, but is very effective at sidestepping
+ * platform-realloc disasters on vulnerable platforms.
+ *
+ * Note that this would be straightforward if a node stored its current
+ * capacity.  The code is tricky to avoid that.
+ */
+#define XXXROUNDUP(n) ((n) <= 1 ? (n) :                 \
+               (n) <= 128 ? (((n) + 3) & ~3) :          \
+               fancy_roundup(n))
+
+
+int
+Ta27Node_AddChild(register node *n1, int type, char *str, int lineno, int col_offset)
+{
+    const int nch = n1->n_nchildren;
+    int current_capacity;
+    int required_capacity;
+    node *n;
+
+    if (nch == INT_MAX || nch < 0)
+        return E_OVERFLOW;
+
+    current_capacity = XXXROUNDUP(nch);
+    required_capacity = XXXROUNDUP(nch + 1);
+    if (current_capacity < 0 || required_capacity < 0)
+        return E_OVERFLOW;
+    if (current_capacity < required_capacity) {
+        if ((size_t)required_capacity > PY_SIZE_MAX / sizeof(node)) {
+            return E_NOMEM;
+        }
+        n = n1->n_child;
+        n = (node *) PyObject_REALLOC(n,
+                                      required_capacity * sizeof(node));
+        if (n == NULL)
+            return E_NOMEM;
+        n1->n_child = n;
+    }
+
+    n = &n1->n_child[n1->n_nchildren++];
+    n->n_type = type;
+    n->n_str = str;
+    n->n_lineno = lineno;
+    n->n_col_offset = col_offset;
+    n->n_nchildren = 0;
+    n->n_child = NULL;
+    return 0;
+}
+
+/* Forward */
+static void freechildren(node *);
+static Py_ssize_t sizeofchildren(node *n);
+
+
+void
+Ta27Node_Free(node *n)
+{
+    if (n != NULL) {
+        freechildren(n);
+        PyObject_FREE(n);
+    }
+}
+
+Py_ssize_t
+_Ta27Node_SizeOf(node *n)
+{
+    Py_ssize_t res = 0;
+
+    if (n != NULL)
+        res = sizeof(node) + sizeofchildren(n);
+    return res;
+}
+
+static void
+freechildren(node *n)
+{
+    int i;
+    for (i = NCH(n); --i >= 0; )
+        freechildren(CHILD(n, i));
+    if (n->n_child != NULL)
+        PyObject_FREE(n->n_child);
+    if (STR(n) != NULL)
+        PyObject_FREE(STR(n));
+}
+
+static Py_ssize_t
+sizeofchildren(node *n)
+{
+    Py_ssize_t res = 0;
+    int i;
+    for (i = NCH(n); --i >= 0; )
+        res += sizeofchildren(CHILD(n, i));
+    if (n->n_child != NULL)
+        /* allocated size of n->n_child array */
+        res += XXXROUNDUP(NCH(n)) * sizeof(node);
+    if (STR(n) != NULL)
+        res += strlen(STR(n)) + 1;
+    return res;
+}
diff --git a/ast27/Parser/parser.c b/ast27/Parser/parser.c
new file mode 100644
index 0000000..c7e621e
--- /dev/null
+++ b/ast27/Parser/parser.c
@@ -0,0 +1,436 @@
+
+/* Parser implementation */
+
+/* For a description, see the comments at end of this file */
+
+/* XXX To do: error recovery */
+
+#include "Python.h"
+#include "pgenheaders.h"
+#include "token.h"
+#include "grammar.h"
+#include "node.h"
+#include "parser.h"
+#include "errcode.h"
+
+
+#ifdef Py_DEBUG
+extern int Py_DebugFlag;
+#define D(x) if (!Py_DebugFlag); else x
+#else
+#define D(x)
+#endif
+
+
+/* STACK DATA TYPE */
+
+static void s_reset(stack *);
+
+static void
+s_reset(stack *s)
+{
+    s->s_top = &s->s_base[MAXSTACK];
+}
+
+#define s_empty(s) ((s)->s_top == &(s)->s_base[MAXSTACK])
+
+static int
+s_push(register stack *s, dfa *d, node *parent)
+{
+    register stackentry *top;
+    if (s->s_top == s->s_base) {
+        fprintf(stderr, "s_push: parser stack overflow\n");
+        return E_NOMEM;
+    }
+    top = --s->s_top;
+    top->s_dfa = d;
+    top->s_parent = parent;
+    top->s_state = 0;
+    return 0;
+}
+
+#ifdef Py_DEBUG
+
+static void
+s_pop(register stack *s)
+{
+    if (s_empty(s))
+        Py_FatalError("s_pop: parser stack underflow -- FATAL");
+    s->s_top++;
+}
+
+#else /* !Py_DEBUG */
+
+#define s_pop(s) (s)->s_top++
+
+#endif
+
+
+/* PARSER CREATION */
+
+parser_state *
+Ta27Parser_New(grammar *g, int start)
+{
+    parser_state *ps;
+
+    if (!g->g_accel)
+        Ta27Grammar_AddAccelerators(g);
+    ps = (parser_state *)PyMem_MALLOC(sizeof(parser_state));
+    if (ps == NULL)
+        return NULL;
+    ps->p_grammar = g;
+#ifdef PY_PARSER_REQUIRES_FUTURE_KEYWORD
+    ps->p_flags = 0;
+#endif
+    ps->p_tree = Ta27Node_New(start);
+    if (ps->p_tree == NULL) {
+        PyMem_FREE(ps);
+        return NULL;
+    }
+    s_reset(&ps->p_stack);
+    (void) s_push(&ps->p_stack, Ta27Grammar_FindDFA(g, start), ps->p_tree);
+    return ps;
+}
+
+void
+Ta27Parser_Delete(parser_state *ps)
+{
+    /* NB If you want to save the parse tree,
+       you must set p_tree to NULL before calling delparser! */
+    Ta27Node_Free(ps->p_tree);
+    PyMem_FREE(ps);
+}
+
+
+/* PARSER STACK OPERATIONS */
+
+static int
+shift(register stack *s, int type, char *str, int newstate, int lineno, int col_offset)
+{
+    int err;
+    assert(!s_empty(s));
+    err = Ta27Node_AddChild(s->s_top->s_parent, type, str, lineno, col_offset);
+    if (err)
+        return err;
+    s->s_top->s_state = newstate;
+    return 0;
+}
+
+static int
+push(register stack *s, int type, dfa *d, int newstate, int lineno, int col_offset)
+{
+    int err;
+    register node *n;
+    n = s->s_top->s_parent;
+    assert(!s_empty(s));
+    err = Ta27Node_AddChild(n, type, (char *)NULL, lineno, col_offset);
+    if (err)
+        return err;
+    s->s_top->s_state = newstate;
+    return s_push(s, d, CHILD(n, NCH(n)-1));
+}
+
+
+/* PARSER PROPER */
+
+static int
+classify(parser_state *ps, int type, char *str)
+{
+    grammar *g = ps->p_grammar;
+    register int n = g->g_ll.ll_nlabels;
+
+    if (type == NAME) {
+        register char *s = str;
+        register label *l = g->g_ll.ll_label;
+        register int i;
+        for (i = n; i > 0; i--, l++) {
+            if (l->lb_type != NAME || l->lb_str == NULL ||
+                l->lb_str[0] != s[0] ||
+                strcmp(l->lb_str, s) != 0)
+                continue;
+#ifdef PY_PARSER_REQUIRES_FUTURE_KEYWORD
+            if (ps->p_flags & CO_FUTURE_PRINT_FUNCTION &&
+                s[0] == 'p' && strcmp(s, "print") == 0) {
+                break; /* no longer a keyword */
+            }
+#endif
+            D(printf("It's a keyword\n"));
+            return n - i;
+        }
+    }
+
+    {
+        register label *l = g->g_ll.ll_label;
+        register int i;
+        for (i = n; i > 0; i--, l++) {
+            if (l->lb_type == type && l->lb_str == NULL) {
+                D(printf("It's a token we know\n"));
+                return n - i;
+            }
+        }
+    }
+
+    D(printf("Illegal token\n"));
+    return -1;
+}
+
+#ifdef PY_PARSER_REQUIRES_FUTURE_KEYWORD
+static void
+future_hack(parser_state *ps)
+{
+    node *n = ps->p_stack.s_top->s_parent;
+    node *ch, *cch;
+    int i;
+
+    /* from __future__ import ..., must have at least 4 children */
+    n = CHILD(n, 0);
+    if (NCH(n) < 4)
+        return;
+    ch = CHILD(n, 0);
+    if (STR(ch) == NULL || strcmp(STR(ch), "from") != 0)
+        return;
+    ch = CHILD(n, 1);
+    if (NCH(ch) == 1 && STR(CHILD(ch, 0)) &&
+        strcmp(STR(CHILD(ch, 0)), "__future__") != 0)
+        return;
+    ch = CHILD(n, 3);
+    /* ch can be a star, a parenthesis or import_as_names */
+    if (TYPE(ch) == STAR)
+        return;
+    if (TYPE(ch) == LPAR)
+        ch = CHILD(n, 4);
+
+    for (i = 0; i < NCH(ch); i += 2) {
+        cch = CHILD(ch, i);
+        if (NCH(cch) >= 1 && TYPE(CHILD(cch, 0)) == NAME) {
+            char *str_ch = STR(CHILD(cch, 0));
+            if (strcmp(str_ch, FUTURE_WITH_STATEMENT) == 0) {
+                ps->p_flags |= CO_FUTURE_WITH_STATEMENT;
+            } else if (strcmp(str_ch, FUTURE_PRINT_FUNCTION) == 0) {
+                ps->p_flags |= CO_FUTURE_PRINT_FUNCTION;
+            } else if (strcmp(str_ch, FUTURE_UNICODE_LITERALS) == 0) {
+                ps->p_flags |= CO_FUTURE_UNICODE_LITERALS;
+            }
+        }
+    }
+}
+#endif /* future keyword */
+
+int
+Ta27Parser_AddToken(register parser_state *ps, register int type, char *str,
+                  int lineno, int col_offset, int *expected_ret)
+{
+    register int ilabel;
+    int err;
+
+    D(printf("Token %s/'%s' ... ", _Ta27Parser_TokenNames[type], str));
+
+    /* Find out which label this token is */
+    ilabel = classify(ps, type, str);
+    if (ilabel < 0)
+        return E_SYNTAX;
+
+    /* Loop until the token is shifted or an error occurred */
+    for (;;) {
+        /* Fetch the current dfa and state */
+        register dfa *d = ps->p_stack.s_top->s_dfa;
+        register state *s = &d->d_state[ps->p_stack.s_top->s_state];
+
+        D(printf(" DFA '%s', state %d:",
+            d->d_name, ps->p_stack.s_top->s_state));
+
+        /* Check accelerator */
+        if (s->s_lower <= ilabel && ilabel < s->s_upper) {
+            register int x = s->s_accel[ilabel - s->s_lower];
+            if (x != -1) {
+                if (x & (1<<7)) {
+                    /* Push non-terminal */
+                    int nt = (x >> 8) + NT_OFFSET;
+                    int arrow = x & ((1<<7)-1);
+                    dfa *d1 = Ta27Grammar_FindDFA(
+                        ps->p_grammar, nt);
+                    if ((err = push(&ps->p_stack, nt, d1,
+                        arrow, lineno, col_offset)) > 0) {
+                        D(printf(" MemError: push\n"));
+                        return err;
+                    }
+                    D(printf(" Push ...\n"));
+                    continue;
+                }
+
+                /* Shift the token */
+                if ((err = shift(&ps->p_stack, type, str,
+                                x, lineno, col_offset)) > 0) {
+                    D(printf(" MemError: shift.\n"));
+                    return err;
+                }
+                D(printf(" Shift.\n"));
+                /* Pop while we are in an accept-only state */
+                while (s = &d->d_state
+                                [ps->p_stack.s_top->s_state],
+                    s->s_accept && s->s_narcs == 1) {
+                    D(printf("  DFA '%s', state %d: "
+                             "Direct pop.\n",
+                             d->d_name,
+                             ps->p_stack.s_top->s_state));
+#ifdef PY_PARSER_REQUIRES_FUTURE_KEYWORD
+                    if (d->d_name[0] == 'i' &&
+                        strcmp(d->d_name,
+                           "import_stmt") == 0)
+                        future_hack(ps);
+#endif
+                    s_pop(&ps->p_stack);
+                    if (s_empty(&ps->p_stack)) {
+                        D(printf("  ACCEPT.\n"));
+                        return E_DONE;
+                    }
+                    d = ps->p_stack.s_top->s_dfa;
+                }
+                return E_OK;
+            }
+        }
+
+        if (s->s_accept) {
+#ifdef PY_PARSER_REQUIRES_FUTURE_KEYWORD
+            if (d->d_name[0] == 'i' &&
+                strcmp(d->d_name, "import_stmt") == 0)
+                future_hack(ps);
+#endif
+            /* Pop this dfa and try again */
+            s_pop(&ps->p_stack);
+            D(printf(" Pop ...\n"));
+            if (s_empty(&ps->p_stack)) {
+                D(printf(" Error: bottom of stack.\n"));
+                return E_SYNTAX;
+            }
+            continue;
+        }
+
+        /* Stuck, report syntax error */
+        D(printf(" Error.\n"));
+        if (expected_ret) {
+            if (s->s_lower == s->s_upper - 1) {
+                /* Only one possible expected token */
+                *expected_ret = ps->p_grammar->
+                    g_ll.ll_label[s->s_lower].lb_type;
+            }
+            else
+                *expected_ret = -1;
+        }
+        return E_SYNTAX;
+    }
+}
+
+
+#ifdef Py_DEBUG
+
+/* DEBUG OUTPUT */
+
+void
+dumptree(grammar *g, node *n)
+{
+    int i;
+
+    if (n == NULL)
+        printf("NIL");
+    else {
+        label l;
+        l.lb_type = TYPE(n);
+        l.lb_str = STR(n);
+        printf("%s", Ta27Grammar_LabelRepr(&l));
+        if (ISNONTERMINAL(TYPE(n))) {
+            printf("(");
+            for (i = 0; i < NCH(n); i++) {
+                if (i > 0)
+                    printf(",");
+                dumptree(g, CHILD(n, i));
+            }
+            printf(")");
+        }
+    }
+}
+
+void
+showtree(grammar *g, node *n)
+{
+    int i;
+
+    if (n == NULL)
+        return;
+    if (ISNONTERMINAL(TYPE(n))) {
+        for (i = 0; i < NCH(n); i++)
+            showtree(g, CHILD(n, i));
+    }
+    else if (ISTERMINAL(TYPE(n))) {
+        printf("%s", _Ta27Parser_TokenNames[TYPE(n)]);
+        if (TYPE(n) == NUMBER || TYPE(n) == NAME)
+            printf("(%s)", STR(n));
+        printf(" ");
+    }
+    else
+        printf("? ");
+}
+
+void
+printtree(parser_state *ps)
+{
+    if (Py_DebugFlag) {
+        printf("Parse tree:\n");
+        dumptree(ps->p_grammar, ps->p_tree);
+        printf("\n");
+        printf("Tokens:\n");
+        showtree(ps->p_grammar, ps->p_tree);
+        printf("\n");
+    }
+    printf("Listing:\n");
+    PyNode_ListTree(ps->p_tree);
+    printf("\n");
+}
+
+#endif /* Py_DEBUG */
+
+/*
+
+Description
+-----------
+
+The parser's interface is different than usual: the function addtoken()
+must be called for each token in the input.  This makes it possible to
+turn it into an incremental parsing system later.  The parsing system
+constructs a parse tree as it goes.
+
+A parsing rule is represented as a Deterministic Finite-state Automaton
+(DFA).  A node in a DFA represents a state of the parser; an arc represents
+a transition.  Transitions are either labeled with terminal symbols or
+with non-terminals.  When the parser decides to follow an arc labeled
+with a non-terminal, it is invoked recursively with the DFA representing
+the parsing rule for that as its initial state; when that DFA accepts,
+the parser that invoked it continues.  The parse tree constructed by the
+recursively called parser is inserted as a child in the current parse tree.
+
+The DFA's can be constructed automatically from a more conventional
+language description.  An extended LL(1) grammar (ELL(1)) is suitable.
+Certain restrictions make the parser's life easier: rules that can produce
+the empty string should be outlawed (there are other ways to put loops
+or optional parts in the language).  To avoid the need to construct
+FIRST sets, we can require that all but the last alternative of a rule
+(really: arc going out of a DFA's state) must begin with a terminal
+symbol.
+
+As an example, consider this grammar:
+
+expr:   term (OP term)*
+term:   CONSTANT | '(' expr ')'
+
+The DFA corresponding to the rule for expr is:
+
+------->.---term-->.------->
+    ^          |
+    |          |
+    \----OP----/
+
+The parse tree generated for the input a+b is:
+
+(expr: (term: (NAME: a)), (OP: +), (term: (NAME: b)))
+
+*/
diff --git a/ast27/Parser/parser.h b/ast27/Parser/parser.h
new file mode 100644
index 0000000..540dae0
--- /dev/null
+++ b/ast27/Parser/parser.h
@@ -0,0 +1,42 @@
+#ifndef Ta27_PARSER_H
+#define Ta27_PARSER_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* Parser interface */
+
+#define MAXSTACK 1500
+
+typedef struct {
+	int		 s_state;	/* State in current DFA */
+	dfa		*s_dfa;		/* Current DFA */
+	struct _node	*s_parent;	/* Where to add next node */
+} stackentry;
+
+typedef struct {
+	stackentry	*s_top;		/* Top entry */
+	stackentry	 s_base[MAXSTACK];/* Array of stack entries */
+					/* NB The stack grows down */
+} stack;
+
+typedef struct {
+	stack	 	p_stack;	/* Stack of parser states */
+	grammar		*p_grammar;	/* Grammar to use */
+	node		*p_tree;	/* Top of parse tree */
+#ifdef PY_PARSER_REQUIRES_FUTURE_KEYWORD
+	unsigned long	p_flags;	/* see co_flags in Include/code.h */
+#endif
+} parser_state;
+
+parser_state *Ta27Parser_New(grammar *g, int start);
+void Ta27Parser_Delete(parser_state *ps);
+int Ta27Parser_AddToken(parser_state *ps, int type, char *str, int lineno, int col_offset,
+                      int *expected_ret);
+void Ta27Grammar_AddAccelerators(grammar *g);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* !Ta27_PARSER_H */
diff --git a/ast27/Parser/parsetok.c b/ast27/Parser/parsetok.c
new file mode 100644
index 0000000..503e0ed
--- /dev/null
+++ b/ast27/Parser/parsetok.c
@@ -0,0 +1,395 @@
+
+/* Parser-tokenizer link implementation */
+
+#include "pgenheaders.h"
+#include "tokenizer.h"
+#include "node.h"
+#include "grammar.h"
+#include "parser.h"
+#include "parsetok.h"
+#include "errcode.h"
+#include "graminit.h"
+
+int Ta27_TabcheckFlag;
+
+
+/* Forward */
+static node *parsetok(struct tok_state *, grammar *, int, perrdetail *, int *);
+static void initerr(perrdetail *err_ret, const char* filename);
+static int initerr_object(perrdetail *err_ret, PyObject *filename);
+
+/* Parse input coming from a string.  Return error code, print some errors. */
+node *
+Ta27Parser_ParseString(const char *s, grammar *g, int start, perrdetail *err_ret)
+{
+    return Ta27Parser_ParseStringFlagsFilename(s, NULL, g, start, err_ret, 0);
+}
+
+node *
+Ta27Parser_ParseStringFlags(const char *s, grammar *g, int start,
+                          perrdetail *err_ret, int flags)
+{
+    return Ta27Parser_ParseStringFlagsFilename(s, NULL,
+                                             g, start, err_ret, flags);
+}
+
+node *
+Ta27Parser_ParseStringFlagsFilename(const char *s, const char *filename,
+                          grammar *g, int start,
+                          perrdetail *err_ret, int flags)
+{
+    int iflags = flags;
+    return Ta27Parser_ParseStringFlagsFilenameEx(s, filename, g, start,
+                                               err_ret, &iflags);
+}
+
+node *
+Ta27Parser_ParseStringFlagsFilenameEx(const char *s, const char *filename,
+                          grammar *g, int start,
+                          perrdetail *err_ret, int *flags)
+{
+    struct tok_state *tok;
+
+    initerr(err_ret, filename);
+
+    if ((tok = Ta27Tokenizer_FromString(s, start == file_input)) == NULL) {
+        err_ret->error = PyErr_Occurred() ? E_DECODE : E_NOMEM;
+        return NULL;
+    }
+
+    tok->filename = filename ? filename : "<string>";
+    if (Ta27_TabcheckFlag || Py_VerboseFlag) {
+        tok->altwarning = (tok->filename != NULL);
+        if (Ta27_TabcheckFlag >= 2)
+            tok->alterror++;
+    }
+
+    return parsetok(tok, g, start, err_ret, flags);
+}
+
+node *
+Ta27Parser_ParseStringObject(const char *s, PyObject *filename,
+                           grammar *g, int start,
+                           perrdetail *err_ret, int *flags)
+{
+    struct tok_state *tok;
+    int exec_input = start == file_input;
+
+    initerr_object(err_ret, filename);
+
+    if (*flags & PyPARSE_IGNORE_COOKIE)
+        tok = Ta27Tokenizer_FromUTF8(s, exec_input);
+    else
+        tok = Ta27Tokenizer_FromString(s, exec_input);
+
+    if (tok == NULL) {
+        err_ret->error = PyErr_Occurred() ? E_DECODE : E_NOMEM;
+        return NULL;
+    }
+
+#ifndef PGEN
+    Py_INCREF(err_ret->filename);
+    tok->filename = PyUnicode_AsUTF8(err_ret->filename);
+#endif
+    return parsetok(tok, g, start, err_ret, flags);
+}
+
+/* Parse input coming from a file.  Return error code, print some errors. */
+
+node *
+Ta27Parser_ParseFile(FILE *fp, const char *filename, grammar *g, int start,
+                   char *ps1, char *ps2, perrdetail *err_ret)
+{
+    return Ta27Parser_ParseFileFlags(fp, filename, g, start, ps1, ps2,
+                                   err_ret, 0);
+}
+
+node *
+Ta27Parser_ParseFileFlags(FILE *fp, const char *filename, grammar *g, int start,
+                        char *ps1, char *ps2, perrdetail *err_ret, int flags)
+{
+    int iflags = flags;
+    return Ta27Parser_ParseFileFlagsEx(fp, filename, g, start, ps1, ps2, err_ret, &iflags);
+}
+
+node *
+Ta27Parser_ParseFileFlagsEx(FILE *fp, const char *filename, grammar *g, int start,
+                          char *ps1, char *ps2, perrdetail *err_ret, int *flags)
+{
+    struct tok_state *tok;
+
+    initerr(err_ret, filename);
+
+    if ((tok = Ta27Tokenizer_FromFile(fp, ps1, ps2)) == NULL) {
+        err_ret->error = E_NOMEM;
+        return NULL;
+    }
+    tok->filename = filename;
+    if (Ta27_TabcheckFlag || Py_VerboseFlag) {
+        tok->altwarning = (filename != NULL);
+        if (Ta27_TabcheckFlag >= 2)
+            tok->alterror++;
+    }
+
+    return parsetok(tok, g, start, err_ret, flags);
+}
+
+#if 0
+static char with_msg[] =
+"%s:%d: Warning: 'with' will become a reserved keyword in Python 2.6\n";
+
+static char as_msg[] =
+"%s:%d: Warning: 'as' will become a reserved keyword in Python 2.6\n";
+
+static void
+warn(const char *msg, const char *filename, int lineno)
+{
+    if (filename == NULL)
+        filename = "<string>";
+    PySys_WriteStderr(msg, filename, lineno);
+}
+#endif
+
+
+typedef struct {
+    int *items;
+    size_t size;
+    size_t num_items;
+} growable_int_array;
+
+int growable_int_array_init(growable_int_array *arr, size_t initial_size) {
+    assert(initial_size > 0);
+    arr->items = malloc(initial_size * sizeof(*arr->items));
+    arr->size = initial_size;
+    arr->num_items = 0;
+
+    return arr->items != NULL;
+}
+
+int growable_int_array_add(growable_int_array *arr, int item) {
+    if (arr->num_items >= arr->size) {
+        arr->size *= 2;
+        arr->items = realloc(arr->items, arr->size * sizeof(*arr->items));
+        if (!arr->items)
+            return 0;
+    }
+
+    arr->items[arr->num_items] = item;
+    arr->num_items++;
+    return 1;
+}
+
+void growable_int_array_deallocate(growable_int_array *arr) {
+    free(arr->items);
+}
+
+
+/* Parse input coming from the given tokenizer structure.
+   Return error code. */
+
+static node *
+parsetok(struct tok_state *tok, grammar *g, int start, perrdetail *err_ret,
+         int *flags)
+{
+    parser_state *ps;
+    node *n;
+    int started = 0;
+
+    growable_int_array type_ignores;
+    if (!growable_int_array_init(&type_ignores, 10)) {
+        err_ret->error = E_NOMEM;
+        Ta27Tokenizer_Free(tok);
+        return NULL;
+    }
+
+    if ((ps = Ta27Parser_New(g, start)) == NULL) {
+        fprintf(stderr, "no mem for new parser\n");
+        err_ret->error = E_NOMEM;
+        Ta27Tokenizer_Free(tok);
+        return NULL;
+    }
+#ifdef PY_PARSER_REQUIRES_FUTURE_KEYWORD
+    if (*flags & PyPARSE_PRINT_IS_FUNCTION) {
+        ps->p_flags |= CO_FUTURE_PRINT_FUNCTION;
+    }
+    if (*flags & PyPARSE_UNICODE_LITERALS) {
+        ps->p_flags |= CO_FUTURE_UNICODE_LITERALS;
+    }
+
+#endif
+
+    for (;;) {
+        char *a, *b;
+        int type;
+        size_t len;
+        char *str;
+        int col_offset;
+
+        type = Ta27Tokenizer_Get(tok, &a, &b);
+        if (type == ERRORTOKEN) {
+            err_ret->error = tok->done;
+            break;
+        }
+        if (type == ENDMARKER && started) {
+            type = NEWLINE; /* Add an extra newline */
+            started = 0;
+            /* Add the right number of dedent tokens,
+               except if a certain flag is given --
+               codeop.py uses this. */
+            if (tok->indent &&
+                !(*flags & PyPARSE_DONT_IMPLY_DEDENT))
+            {
+                tok->pendin = -tok->indent;
+                tok->indent = 0;
+            }
+        }
+        else
+            started = 1;
+        len = b - a; /* XXX this may compute NULL - NULL */
+        str = (char *) PyObject_MALLOC(len + 1);
+        if (str == NULL) {
+            fprintf(stderr, "no mem for next token\n");
+            err_ret->error = E_NOMEM;
+            break;
+        }
+        if (len > 0)
+            strncpy(str, a, len);
+        str[len] = '\0';
+
+#ifdef PY_PARSER_REQUIRES_FUTURE_KEYWORD
+#endif
+        if (a >= tok->line_start)
+            col_offset = a - tok->line_start;
+        else
+            col_offset = -1;
+
+        if (type == TYPE_IGNORE) {
+            if (!growable_int_array_add(&type_ignores, tok->lineno)) {
+                err_ret->error = E_NOMEM;
+                break;
+            }
+            continue;
+        }
+
+        if ((err_ret->error =
+             Ta27Parser_AddToken(ps, (int)type, str, tok->lineno, col_offset,
+                               &(err_ret->expected))) != E_OK) {
+            if (err_ret->error != E_DONE) {
+                PyObject_FREE(str);
+                err_ret->token = type;
+            }
+            break;
+        }
+    }
+
+    if (err_ret->error == E_DONE) {
+        n = ps->p_tree;
+        ps->p_tree = NULL;
+
+        if (n->n_type == file_input) {
+            /* Put type_ignore nodes in the ENDMARKER of file_input. */
+            int num;
+            node *ch;
+            size_t i;
+
+            num = NCH(n);
+            ch = CHILD(n, num - 1);
+            REQ(ch, ENDMARKER);
+
+            for (i = 0; i < type_ignores.num_items; i++) {
+                Ta27Node_AddChild(ch, TYPE_IGNORE, NULL, type_ignores.items[i], 0);
+            }
+        }
+        growable_int_array_deallocate(&type_ignores);
+
+    }
+    else
+        n = NULL;
+
+#ifdef PY_PARSER_REQUIRES_FUTURE_KEYWORD
+    *flags = ps->p_flags;
+#endif
+    Ta27Parser_Delete(ps);
+
+    if (n == NULL) {
+        if (tok->lineno <= 1 && tok->done == E_EOF)
+            err_ret->error = E_EOF;
+        err_ret->lineno = tok->lineno;
+        if (tok->buf != NULL) {
+            char *text = NULL;
+            size_t len;
+            assert(tok->cur - tok->buf < INT_MAX);
+            err_ret->offset = (int)(tok->cur - tok->buf);
+            len = tok->inp - tok->buf;
+#ifdef Py_USING_UNICODE
+            text = Ta27Tokenizer_RestoreEncoding(tok, len, &err_ret->offset);
+
+#endif
+            if (text == NULL) {
+                text = (char *) PyObject_MALLOC(len + 1);
+                if (text != NULL) {
+                    if (len > 0)
+                        strncpy(text, tok->buf, len);
+                    text[len] = '\0';
+                }
+            }
+            err_ret->text = text;
+        }
+    } else if (tok->encoding != NULL) {
+        /* 'nodes->n_str' uses PyObject_*, while 'tok->encoding' was
+         * allocated using PyMem_
+         */
+        node* r = Ta27Node_New(encoding_decl);
+        if (r)
+            r->n_str = PyObject_MALLOC(strlen(tok->encoding)+1);
+        if (!r || !r->n_str) {
+            err_ret->error = E_NOMEM;
+            if (r)
+                PyObject_FREE(r);
+            n = NULL;
+            goto done;
+        }
+        strcpy(r->n_str, tok->encoding);
+        PyMem_FREE(tok->encoding);
+        tok->encoding = NULL;
+        r->n_nchildren = 1;
+        r->n_child = n;
+        n = r;
+    }
+
+done:
+    Ta27Tokenizer_Free(tok);
+
+    return n;
+}
+
+static void
+initerr(perrdetail *err_ret, const char *filename)
+{
+  initerr_object(err_ret, PyUnicode_FromString(filename));
+}
+
+static int
+initerr_object(perrdetail *err_ret, PyObject *filename)
+{
+    err_ret->error = E_OK;
+    err_ret->lineno = 0;
+    err_ret->offset = 0;
+    err_ret->text = NULL;
+    err_ret->token = -1;
+    err_ret->expected = -1;
+#ifndef PGEN
+    if (filename) {
+        Py_INCREF(filename);
+        err_ret->filename = filename;
+    }
+    else {
+        err_ret->filename = PyUnicode_FromString("<string>");
+        if (err_ret->filename == NULL) {
+            err_ret->error = E_ERROR;
+            return -1;
+        }
+    }
+#endif
+    return 0;
+}
diff --git a/ast27/Parser/spark.py b/ast27/Parser/spark.py
new file mode 100644
index 0000000..b064d62
--- /dev/null
+++ b/ast27/Parser/spark.py
@@ -0,0 +1,839 @@
+#  Copyright (c) 1998-2002 John Aycock
+#
+#  Permission is hereby granted, free of charge, to any person obtaining
+#  a copy of this software and associated documentation files (the
+#  "Software"), to deal in the Software without restriction, including
+#  without limitation the rights to use, copy, modify, merge, publish,
+#  distribute, sublicense, and/or sell copies of the Software, and to
+#  permit persons to whom the Software is furnished to do so, subject to
+#  the following conditions:
+#
+#  The above copyright notice and this permission notice shall be
+#  included in all copies or substantial portions of the Software.
+#
+#  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+#  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+#  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+#  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+#  CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+#  TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+#  SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+__version__ = 'SPARK-0.7 (pre-alpha-5)'
+
+import re
+import string
+
+def _namelist(instance):
+    namelist, namedict, classlist = [], {}, [instance.__class__]
+    for c in classlist:
+        for b in c.__bases__:
+            classlist.append(b)
+        for name in c.__dict__.keys():
+            if not namedict.has_key(name):
+                namelist.append(name)
+                namedict[name] = 1
+    return namelist
+
+class GenericScanner:
+    def __init__(self, flags=0):
+        pattern = self.reflect()
+        self.re = re.compile(pattern, re.VERBOSE|flags)
+
+        self.index2func = {}
+        for name, number in self.re.groupindex.items():
+            self.index2func[number-1] = getattr(self, 't_' + name)
+
+    def makeRE(self, name):
+        doc = getattr(self, name).__doc__
+        rv = '(?P<%s>%s)' % (name[2:], doc)
+        return rv
+
+    def reflect(self):
+        rv = []
+        for name in _namelist(self):
+            if name[:2] == 't_' and name != 't_default':
+                rv.append(self.makeRE(name))
+
+        rv.append(self.makeRE('t_default'))
+        return string.join(rv, '|')
+
+    def error(self, s, pos):
+        print "Lexical error at position %s" % pos
+        raise SystemExit
+
+    def tokenize(self, s):
+        pos = 0
+        n = len(s)
+        while pos < n:
+            m = self.re.match(s, pos)
+            if m is None:
+                self.error(s, pos)
+
+            groups = m.groups()
+            for i in range(len(groups)):
+                if groups[i] and self.index2func.has_key(i):
+                    self.index2func[i](groups[i])
+            pos = m.end()
+
+    def t_default(self, s):
+        r'( . | \n )+'
+        print "Specification error: unmatched input"
+        raise SystemExit
+
+#
+#  Extracted from GenericParser and made global so that [un]picking works.
+#
+class _State:
+    def __init__(self, stateno, items):
+        self.T, self.complete, self.items = [], [], items
+        self.stateno = stateno
+
+class GenericParser:
+    #
+    #  An Earley parser, as per J. Earley, "An Efficient Context-Free
+    #  Parsing Algorithm", CACM 13(2), pp. 94-102.  Also J. C. Earley,
+    #  "An Efficient Context-Free Parsing Algorithm", Ph.D. thesis,
+    #  Carnegie-Mellon University, August 1968.  New formulation of
+    #  the parser according to J. Aycock, "Practical Earley Parsing
+    #  and the SPARK Toolkit", Ph.D. thesis, University of Victoria,
+    #  2001, and J. Aycock and R. N. Horspool, "Practical Earley
+    #  Parsing", unpublished paper, 2001.
+    #
+
+    def __init__(self, start):
+        self.rules = {}
+        self.rule2func = {}
+        self.rule2name = {}
+        self.collectRules()
+        self.augment(start)
+        self.ruleschanged = 1
+
+    _NULLABLE = '\e_'
+    _START = 'START'
+    _BOF = '|-'
+
+    #
+    #  When pickling, take the time to generate the full state machine;
+    #  some information is then extraneous, too.  Unfortunately we
+    #  can't save the rule2func map.
+    #
+    def __getstate__(self):
+        if self.ruleschanged:
+            #
+            #  XXX - duplicated from parse()
+            #
+            self.computeNull()
+            self.newrules = {}
+            self.new2old = {}
+            self.makeNewRules()
+            self.ruleschanged = 0
+            self.edges, self.cores = {}, {}
+            self.states = { 0: self.makeState0() }
+            self.makeState(0, self._BOF)
+        #
+        #  XXX - should find a better way to do this..
+        #
+        changes = 1
+        while changes:
+            changes = 0
+            for k, v in self.edges.items():
+                if v is None:
+                    state, sym = k
+                    if self.states.has_key(state):
+                        self.goto(state, sym)
+                        changes = 1
+        rv = self.__dict__.copy()
+        for s in self.states.values():
+            del s.items
+        del rv['rule2func']
+        del rv['nullable']
+        del rv['cores']
+        return rv
+
+    def __setstate__(self, D):
+        self.rules = {}
+        self.rule2func = {}
+        self.rule2name = {}
+        self.collectRules()
+        start = D['rules'][self._START][0][1][1]        # Blech.
+        self.augment(start)
+        D['rule2func'] = self.rule2func
+        D['makeSet'] = self.makeSet_fast
+        self.__dict__ = D
+
+    #
+    #  A hook for GenericASTBuilder and GenericASTMatcher.  Mess
+    #  thee not with this; nor shall thee toucheth the _preprocess
+    #  argument to addRule.
+    #
+    def preprocess(self, rule, func):       return rule, func
+
+    def addRule(self, doc, func, _preprocess=1):
+        fn = func
+        rules = string.split(doc)
+
+        index = []
+        for i in range(len(rules)):
+            if rules[i] == '::=':
+                index.append(i-1)
+        index.append(len(rules))
+
+        for i in range(len(index)-1):
+            lhs = rules[index[i]]
+            rhs = rules[index[i]+2:index[i+1]]
+            rule = (lhs, tuple(rhs))
+
+            if _preprocess:
+                rule, fn = self.preprocess(rule, func)
+
+            if self.rules.has_key(lhs):
+                self.rules[lhs].append(rule)
+            else:
+                self.rules[lhs] = [ rule ]
+            self.rule2func[rule] = fn
+            self.rule2name[rule] = func.__name__[2:]
+        self.ruleschanged = 1
+
+    def collectRules(self):
+        for name in _namelist(self):
+            if name[:2] == 'p_':
+                func = getattr(self, name)
+                doc = func.__doc__
+                self.addRule(doc, func)
+
+    def augment(self, start):
+        rule = '%s ::= %s %s' % (self._START, self._BOF, start)
+        self.addRule(rule, lambda args: args[1], 0)
+
+    def computeNull(self):
+        self.nullable = {}
+        tbd = []
+
+        for rulelist in self.rules.values():
+            lhs = rulelist[0][0]
+            self.nullable[lhs] = 0
+            for rule in rulelist:
+                rhs = rule[1]
+                if len(rhs) == 0:
+                    self.nullable[lhs] = 1
+                    continue
+                #
+                #  We only need to consider rules which
+                #  consist entirely of nonterminal symbols.
+                #  This should be a savings on typical
+                #  grammars.
+                #
+                for sym in rhs:
+                    if not self.rules.has_key(sym):
+                        break
+                else:
+                    tbd.append(rule)
+        changes = 1
+        while changes:
+            changes = 0
+            for lhs, rhs in tbd:
+                if self.nullable[lhs]:
+                    continue
+                for sym in rhs:
+                    if not self.nullable[sym]:
+                        break
+                else:
+                    self.nullable[lhs] = 1
+                    changes = 1
+
+    def makeState0(self):
+        s0 = _State(0, [])
+        for rule in self.newrules[self._START]:
+            s0.items.append((rule, 0))
+        return s0
+
+    def finalState(self, tokens):
+        #
+        #  Yuck.
+        #
+        if len(self.newrules[self._START]) == 2 and len(tokens) == 0:
+            return 1
+        start = self.rules[self._START][0][1][1]
+        return self.goto(1, start)
+
+    def makeNewRules(self):
+        worklist = []
+        for rulelist in self.rules.values():
+            for rule in rulelist:
+                worklist.append((rule, 0, 1, rule))
+
+        for rule, i, candidate, oldrule in worklist:
+            lhs, rhs = rule
+            n = len(rhs)
+            while i < n:
+                sym = rhs[i]
+                if not self.rules.has_key(sym) or \
+                   not self.nullable[sym]:
+                    candidate = 0
+                    i = i + 1
+                    continue
+
+                newrhs = list(rhs)
+                newrhs[i] = self._NULLABLE+sym
+                newrule = (lhs, tuple(newrhs))
+                worklist.append((newrule, i+1,
+                                 candidate, oldrule))
+                candidate = 0
+                i = i + 1
+            else:
+                if candidate:
+                    lhs = self._NULLABLE+lhs
+                    rule = (lhs, rhs)
+                if self.newrules.has_key(lhs):
+                    self.newrules[lhs].append(rule)
+                else:
+                    self.newrules[lhs] = [ rule ]
+                self.new2old[rule] = oldrule
+
+    def typestring(self, token):
+        return None
+
+    def error(self, token):
+        print "Syntax error at or near `%s' token" % token
+        raise SystemExit
+
+    def parse(self, tokens):
+        sets = [ [(1,0), (2,0)] ]
+        self.links = {}
+
+        if self.ruleschanged:
+            self.computeNull()
+            self.newrules = {}
+            self.new2old = {}
+            self.makeNewRules()
+            self.ruleschanged = 0
+            self.edges, self.cores = {}, {}
+            self.states = { 0: self.makeState0() }
+            self.makeState(0, self._BOF)
+
+        for i in xrange(len(tokens)):
+            sets.append([])
+
+            if sets[i] == []:
+                break
+            self.makeSet(tokens[i], sets, i)
+        else:
+            sets.append([])
+            self.makeSet(None, sets, len(tokens))
+
+        #_dump(tokens, sets, self.states)
+
+        finalitem = (self.finalState(tokens), 0)
+        if finalitem not in sets[-2]:
+            if len(tokens) > 0:
+                self.error(tokens[i-1])
+            else:
+                self.error(None)
+
+        return self.buildTree(self._START, finalitem,
+                              tokens, len(sets)-2)
+
+    def isnullable(self, sym):
+        #
+        #  For symbols in G_e only.  If we weren't supporting 1.5,
+        #  could just use sym.startswith().
+        #
+        return self._NULLABLE == sym[0:len(self._NULLABLE)]
+
+    def skip(self, (lhs, rhs), pos=0):
+        n = len(rhs)
+        while pos < n:
+            if not self.isnullable(rhs[pos]):
+                break
+            pos = pos + 1
+        return pos
+
+    def makeState(self, state, sym):
+        assert sym is not None
+        #
+        #  Compute \epsilon-kernel state's core and see if
+        #  it exists already.
+        #
+        kitems = []
+        for rule, pos in self.states[state].items:
+            lhs, rhs = rule
+            if rhs[pos:pos+1] == (sym,):
+                kitems.append((rule, self.skip(rule, pos+1)))
+        core = kitems
+
+        core.sort()
+        tcore = tuple(core)
+        if self.cores.has_key(tcore):
+            return self.cores[tcore]
+        #
+        #  Nope, doesn't exist.  Compute it and the associated
+        #  \epsilon-nonkernel state together; we'll need it right away.
+        #
+        k = self.cores[tcore] = len(self.states)
+        K, NK = _State(k, kitems), _State(k+1, [])
+        self.states[k] = K
+        predicted = {}
+
+        edges = self.edges
+        rules = self.newrules
+        for X in K, NK:
+            worklist = X.items
+            for item in worklist:
+                rule, pos = item
+                lhs, rhs = rule
+                if pos == len(rhs):
+                    X.complete.append(rule)
+                    continue
+
+                nextSym = rhs[pos]
+                key = (X.stateno, nextSym)
+                if not rules.has_key(nextSym):
+                    if not edges.has_key(key):
+                        edges[key] = None
+                        X.T.append(nextSym)
+                else:
+                    edges[key] = None
+                    if not predicted.has_key(nextSym):
+                        predicted[nextSym] = 1
+                        for prule in rules[nextSym]:
+                            ppos = self.skip(prule)
+                            new = (prule, ppos)
+                            NK.items.append(new)
+            #
+            #  Problem: we know K needs generating, but we
+            #  don't yet know about NK.  Can't commit anything
+            #  regarding NK to self.edges until we're sure.  Should
+            #  we delay committing on both K and NK to avoid this
+            #  hacky code?  This creates other problems..
+            #
+            if X is K:
+                edges = {}
+
+        if NK.items == []:
+            return k
+
+        #
+        #  Check for \epsilon-nonkernel's core.  Unfortunately we
+        #  need to know the entire set of predicted nonterminals
+        #  to do this without accidentally duplicating states.
+        #
+        core = predicted.keys()
+        core.sort()
+        tcore = tuple(core)
+        if self.cores.has_key(tcore):
+            self.edges[(k, None)] = self.cores[tcore]
+            return k
+
+        nk = self.cores[tcore] = self.edges[(k, None)] = NK.stateno
+        self.edges.update(edges)
+        self.states[nk] = NK
+        return k
+
+    def goto(self, state, sym):
+        key = (state, sym)
+        if not self.edges.has_key(key):
+            #
+            #  No transitions from state on sym.
+            #
+            return None
+
+        rv = self.edges[key]
+        if rv is None:
+            #
+            #  Target state isn't generated yet.  Remedy this.
+            #
+            rv = self.makeState(state, sym)
+            self.edges[key] = rv
+        return rv
+
+    def gotoT(self, state, t):
+        return [self.goto(state, t)]
+
+    def gotoST(self, state, st):
+        rv = []
+        for t in self.states[state].T:
+            if st == t:
+                rv.append(self.goto(state, t))
+        return rv
+
+    def add(self, set, item, i=None, predecessor=None, causal=None):
+        if predecessor is None:
+            if item not in set:
+                set.append(item)
+        else:
+            key = (item, i)
+            if item not in set:
+                self.links[key] = []
+                set.append(item)
+            self.links[key].append((predecessor, causal))
+
+    def makeSet(self, token, sets, i):
+        cur, next = sets[i], sets[i+1]
+
+        ttype = token is not None and self.typestring(token) or None
+        if ttype is not None:
+            fn, arg = self.gotoT, ttype
+        else:
+            fn, arg = self.gotoST, token
+
+        for item in cur:
+            ptr = (item, i)
+            state, parent = item
+            add = fn(state, arg)
+            for k in add:
+                if k is not None:
+                    self.add(next, (k, parent), i+1, ptr)
+                    nk = self.goto(k, None)
+                    if nk is not None:
+                        self.add(next, (nk, i+1))
+
+            if parent == i:
+                continue
+
+            for rule in self.states[state].complete:
+                lhs, rhs = rule
+                for pitem in sets[parent]:
+                    pstate, pparent = pitem
+                    k = self.goto(pstate, lhs)
+                    if k is not None:
+                        why = (item, i, rule)
+                        pptr = (pitem, parent)
+                        self.add(cur, (k, pparent),
+                                 i, pptr, why)
+                        nk = self.goto(k, None)
+                        if nk is not None:
+                            self.add(cur, (nk, i))
+
+    def makeSet_fast(self, token, sets, i):
+        #
+        #  Call *only* when the entire state machine has been built!
+        #  It relies on self.edges being filled in completely, and
+        #  then duplicates and inlines code to boost speed at the
+        #  cost of extreme ugliness.
+        #
+        cur, next = sets[i], sets[i+1]
+        ttype = token is not None and self.typestring(token) or None
+
+        for item in cur:
+            ptr = (item, i)
+            state, parent = item
+            if ttype is not None:
+                k = self.edges.get((state, ttype), None)
+                if k is not None:
+                    #self.add(next, (k, parent), i+1, ptr)
+                    #INLINED --v
+                    new = (k, parent)
+                    key = (new, i+1)
+                    if new not in next:
+                        self.links[key] = []
+                        next.append(new)
+                    self.links[key].append((ptr, None))
+                    #INLINED --^
+                    #nk = self.goto(k, None)
+                    nk = self.edges.get((k, None), None)
+                    if nk is not None:
+                        #self.add(next, (nk, i+1))
+                        #INLINED --v
+                        new = (nk, i+1)
+                        if new not in next:
+                            next.append(new)
+                        #INLINED --^
+            else:
+                add = self.gotoST(state, token)
+                for k in add:
+                    if k is not None:
+                        self.add(next, (k, parent), i+1, ptr)
+                        #nk = self.goto(k, None)
+                        nk = self.edges.get((k, None), None)
+                        if nk is not None:
+                            self.add(next, (nk, i+1))
+
+            if parent == i:
+                continue
+
+            for rule in self.states[state].complete:
+                lhs, rhs = rule
+                for pitem in sets[parent]:
+                    pstate, pparent = pitem
+                    #k = self.goto(pstate, lhs)
+                    k = self.edges.get((pstate, lhs), None)
+                    if k is not None:
+                        why = (item, i, rule)
+                        pptr = (pitem, parent)
+                        #self.add(cur, (k, pparent),
+                        #        i, pptr, why)
+                        #INLINED --v
+                        new = (k, pparent)
+                        key = (new, i)
+                        if new not in cur:
+                            self.links[key] = []
+                            cur.append(new)
+                        self.links[key].append((pptr, why))
+                        #INLINED --^
+                        #nk = self.goto(k, None)
+                        nk = self.edges.get((k, None), None)
+                        if nk is not None:
+                            #self.add(cur, (nk, i))
+                            #INLINED --v
+                            new = (nk, i)
+                            if new not in cur:
+                                cur.append(new)
+                            #INLINED --^
+
+    def predecessor(self, key, causal):
+        for p, c in self.links[key]:
+            if c == causal:
+                return p
+        assert 0
+
+    def causal(self, key):
+        links = self.links[key]
+        if len(links) == 1:
+            return links[0][1]
+        choices = []
+        rule2cause = {}
+        for p, c in links:
+            rule = c[2]
+            choices.append(rule)
+            rule2cause[rule] = c
+        return rule2cause[self.ambiguity(choices)]
+
+    def deriveEpsilon(self, nt):
+        if len(self.newrules[nt]) > 1:
+            rule = self.ambiguity(self.newrules[nt])
+        else:
+            rule = self.newrules[nt][0]
+        #print rule
+
+        rhs = rule[1]
+        attr = [None] * len(rhs)
+
+        for i in range(len(rhs)-1, -1, -1):
+            attr[i] = self.deriveEpsilon(rhs[i])
+        return self.rule2func[self.new2old[rule]](attr)
+
+    def buildTree(self, nt, item, tokens, k):
+        state, parent = item
+
+        choices = []
+        for rule in self.states[state].complete:
+            if rule[0] == nt:
+                choices.append(rule)
+        rule = choices[0]
+        if len(choices) > 1:
+            rule = self.ambiguity(choices)
+        #print rule
+
+        rhs = rule[1]
+        attr = [None] * len(rhs)
+
+        for i in range(len(rhs)-1, -1, -1):
+            sym = rhs[i]
+            if not self.newrules.has_key(sym):
+                if sym != self._BOF:
+                    attr[i] = tokens[k-1]
+                    key = (item, k)
+                    item, k = self.predecessor(key, None)
+            #elif self.isnullable(sym):
+            elif self._NULLABLE == sym[0:len(self._NULLABLE)]:
+                attr[i] = self.deriveEpsilon(sym)
+            else:
+                key = (item, k)
+                why = self.causal(key)
+                attr[i] = self.buildTree(sym, why[0],
+                                         tokens, why[1])
+                item, k = self.predecessor(key, why)
+        return self.rule2func[self.new2old[rule]](attr)
+
+    def ambiguity(self, rules):
+        #
+        #  XXX - problem here and in collectRules() if the same rule
+        #        appears in >1 method.  Also undefined results if rules
+        #        causing the ambiguity appear in the same method.
+        #
+        sortlist = []
+        name2index = {}
+        for i in range(len(rules)):
+            lhs, rhs = rule = rules[i]
+            name = self.rule2name[self.new2old[rule]]
+            sortlist.append((len(rhs), name))
+            name2index[name] = i
+        sortlist.sort()
+        list = map(lambda (a,b): b, sortlist)
+        return rules[name2index[self.resolve(list)]]
+
+    def resolve(self, list):
+        #
+        #  Resolve ambiguity in favor of the shortest RHS.
+        #  Since we walk the tree from the top down, this
+        #  should effectively resolve in favor of a "shift".
+        #
+        return list[0]
+
+#
+#  GenericASTBuilder automagically constructs a concrete/abstract syntax tree
+#  for a given input.  The extra argument is a class (not an instance!)
+#  which supports the "__setslice__" and "__len__" methods.
+#
+#  XXX - silently overrides any user code in methods.
+#
+
+class GenericASTBuilder(GenericParser):
+    def __init__(self, AST, start):
+        GenericParser.__init__(self, start)
+        self.AST = AST
+
+    def preprocess(self, rule, func):
+        rebind = lambda lhs, self=self: \
+                        lambda args, lhs=lhs, self=self: \
+                                self.buildASTNode(args, lhs)
+        lhs, rhs = rule
+        return rule, rebind(lhs)
+
+    def buildASTNode(self, args, lhs):
+        children = []
+        for arg in args:
+            if isinstance(arg, self.AST):
+                children.append(arg)
+            else:
+                children.append(self.terminal(arg))
+        return self.nonterminal(lhs, children)
+
+    def terminal(self, token):      return token
+
+    def nonterminal(self, type, args):
+        rv = self.AST(type)
+        rv[:len(args)] = args
+        return rv
+
+#
+#  GenericASTTraversal is a Visitor pattern according to Design Patterns.  For
+#  each node it attempts to invoke the method n_<node type>, falling
+#  back onto the default() method if the n_* can't be found.  The preorder
+#  traversal also looks for an exit hook named n_<node type>_exit (no default
+#  routine is called if it's not found).  To prematurely halt traversal
+#  of a subtree, call the prune() method -- this only makes sense for a
+#  preorder traversal.  Node type is determined via the typestring() method.
+#
+
+class GenericASTTraversalPruningException:
+    pass
+
+class GenericASTTraversal:
+    def __init__(self, ast):
+        self.ast = ast
+
+    def typestring(self, node):
+        return node.type
+
+    def prune(self):
+        raise GenericASTTraversalPruningException
+
+    def preorder(self, node=None):
+        if node is None:
+            node = self.ast
+
+        try:
+            name = 'n_' + self.typestring(node)
+            if hasattr(self, name):
+                func = getattr(self, name)
+                func(node)
+            else:
+                self.default(node)
+        except GenericASTTraversalPruningException:
+            return
+
+        for kid in node:
+            self.preorder(kid)
+
+        name = name + '_exit'
+        if hasattr(self, name):
+            func = getattr(self, name)
+            func(node)
+
+    def postorder(self, node=None):
+        if node is None:
+            node = self.ast
+
+        for kid in node:
+            self.postorder(kid)
+
+        name = 'n_' + self.typestring(node)
+        if hasattr(self, name):
+            func = getattr(self, name)
+            func(node)
+        else:
+            self.default(node)
+
+
+    def default(self, node):
+        pass
+
+#
+#  GenericASTMatcher.  AST nodes must have "__getitem__" and "__cmp__"
+#  implemented.
+#
+#  XXX - makes assumptions about how GenericParser walks the parse tree.
+#
+
+class GenericASTMatcher(GenericParser):
+    def __init__(self, start, ast):
+        GenericParser.__init__(self, start)
+        self.ast = ast
+
+    def preprocess(self, rule, func):
+        rebind = lambda func, self=self: \
+                        lambda args, func=func, self=self: \
+                                self.foundMatch(args, func)
+        lhs, rhs = rule
+        rhslist = list(rhs)
+        rhslist.reverse()
+
+        return (lhs, tuple(rhslist)), rebind(func)
+
+    def foundMatch(self, args, func):
+        func(args[-1])
+        return args[-1]
+
+    def match_r(self, node):
+        self.input.insert(0, node)
+        children = 0
+
+        for child in node:
+            if children == 0:
+                self.input.insert(0, '(')
+            children = children + 1
+            self.match_r(child)
+
+        if children > 0:
+            self.input.insert(0, ')')
+
+    def match(self, ast=None):
+        if ast is None:
+            ast = self.ast
+        self.input = []
+
+        self.match_r(ast)
+        self.parse(self.input)
+
+    def resolve(self, list):
+        #
+        #  Resolve ambiguity in favor of the longest RHS.
+        #
+        return list[-1]
+
+def _dump(tokens, sets, states):
+    for i in range(len(sets)):
+        print 'set', i
+        for item in sets[i]:
+            print '\t', item
+            for (lhs, rhs), pos in states[item[0]].items:
+                print '\t\t', lhs, '::=',
+                print string.join(rhs[:pos]),
+                print '.',
+                print string.join(rhs[pos:])
+        if i < len(tokens):
+            print
+            print 'token', str(tokens[i])
+            print
diff --git a/ast27/Parser/tokenizer.c b/ast27/Parser/tokenizer.c
new file mode 100644
index 0000000..e435d49
--- /dev/null
+++ b/ast27/Parser/tokenizer.c
@@ -0,0 +1,1827 @@
+
+/* Tokenizer implementation */
+
+#include "Python.h"
+#include "pgenheaders.h"
+
+#include <ctype.h>
+#include <assert.h>
+
+#include "tokenizer.h"
+#include "errcode.h"
+
+#ifndef PGEN
+#include "unicodeobject.h"
+#include "bytesobject.h"
+#include "fileobject.h"
+#include "codecs.h"
+#include "abstract.h"
+#include "pydebug.h"
+#endif /* PGEN */
+
+#if PY_MINOR_VERSION >= 4
+extern char *PyOS_Readline(FILE *, FILE *, const char *);
+#else
+extern char *PyOS_Readline(FILE *, FILE *, char *);
+#endif
+/* Return malloc'ed string including trailing \n;
+   empty malloc'ed string for EOF;
+   NULL if interrupted */
+
+/* Don't ever change this -- it would break the portability of Python code */
+#define TABSIZE 8
+
+/* Forward */
+static struct tok_state *tok_new(void);
+static int tok_nextc(struct tok_state *tok);
+static void tok_backup(struct tok_state *tok, int c);
+
+/* Token names */
+
+char *_Ta27Parser_TokenNames[] = {
+    "ENDMARKER",
+    "NAME",
+    "NUMBER",
+    "STRING",
+    "NEWLINE",
+    "INDENT",
+    "DEDENT",
+    "LPAR",
+    "RPAR",
+    "LSQB",
+    "RSQB",
+    "COLON",
+    "COMMA",
+    "SEMI",
+    "PLUS",
+    "MINUS",
+    "STAR",
+    "SLASH",
+    "VBAR",
+    "AMPER",
+    "LESS",
+    "GREATER",
+    "EQUAL",
+    "DOT",
+    "PERCENT",
+    "BACKQUOTE",
+    "LBRACE",
+    "RBRACE",
+    "EQEQUAL",
+    "NOTEQUAL",
+    "LESSEQUAL",
+    "GREATEREQUAL",
+    "TILDE",
+    "CIRCUMFLEX",
+    "LEFTSHIFT",
+    "RIGHTSHIFT",
+    "DOUBLESTAR",
+    "PLUSEQUAL",
+    "MINEQUAL",
+    "STAREQUAL",
+    "SLASHEQUAL",
+    "PERCENTEQUAL",
+    "AMPEREQUAL",
+    "VBAREQUAL",
+    "CIRCUMFLEXEQUAL",
+    "LEFTSHIFTEQUAL",
+    "RIGHTSHIFTEQUAL",
+    "DOUBLESTAREQUAL",
+    "DOUBLESLASH",
+    "DOUBLESLASHEQUAL",
+    "AT",
+    /* This table must match the #defines in token.h! */
+    "OP",
+    "RARROW",
+    "TYPE_IGNORE",
+    "TYPE_COMMENT",
+    "<ERRORTOKEN>",
+    "<N_TOKENS>"
+};
+
+/* Spaces in this constant are treated as "zero or more spaces or tabs" when
+   tokenizing. */
+static const char* type_comment_prefix = "# type: ";
+
+/* Create and initialize a new tok_state structure */
+
+static struct tok_state *
+tok_new(void)
+{
+    struct tok_state *tok = (struct tok_state *)PyMem_MALLOC(
+                                            sizeof(struct tok_state));
+    if (tok == NULL)
+        return NULL;
+    tok->buf = tok->cur = tok->end = tok->inp = tok->start = NULL;
+    tok->done = E_OK;
+    tok->fp = NULL;
+    tok->input = NULL;
+    tok->tabsize = TABSIZE;
+    tok->indent = 0;
+    tok->indstack[0] = 0;
+    tok->atbol = 1;
+    tok->pendin = 0;
+    tok->prompt = tok->nextprompt = NULL;
+    tok->lineno = 0;
+    tok->level = 0;
+    tok->filename = NULL;
+    tok->altwarning = 0;
+    tok->alterror = 0;
+    tok->alttabsize = 1;
+    tok->altindstack[0] = 0;
+    tok->decoding_state = 0;
+    tok->decoding_erred = 0;
+    tok->read_coding_spec = 0;
+    tok->encoding = NULL;
+    tok->cont_line = 0;
+#ifndef PGEN
+    tok->decoding_readline = NULL;
+    tok->decoding_buffer = NULL;
+#endif
+    return tok;
+}
+
+static char *
+new_string(const char *s, Py_ssize_t len)
+{
+    char* result = (char *)PyMem_MALLOC(len + 1);
+    if (result != NULL) {
+        memcpy(result, s, len);
+        result[len] = '\0';
+    }
+    return result;
+}
+
+#ifdef PGEN
+
+static char *
+decoding_fgets(char *s, int size, struct tok_state *tok)
+{
+    return fgets(s, size, tok->fp);
+}
+
+static int
+decoding_feof(struct tok_state *tok)
+{
+    return feof(tok->fp);
+}
+
+static char *
+decode_str(const char *str, int exec_input, struct tok_state *tok)
+{
+    return new_string(str, strlen(str));
+}
+
+#else /* PGEN */
+
+static char *
+error_ret(struct tok_state *tok) /* XXX */
+{
+    tok->decoding_erred = 1;
+    if (tok->fp != NULL && tok->buf != NULL) /* see Ta27Tokenizer_Free */
+        PyMem_FREE(tok->buf);
+    tok->buf = tok->cur = tok->end = tok->inp = tok->start = NULL;
+    tok->done = E_DECODE;
+    return NULL;                /* as if it were EOF */
+}
+
+
+static char *
+get_normal_name(char *s)        /* for utf-8 and latin-1 */
+{
+    char buf[13];
+    int i;
+    for (i = 0; i < 12; i++) {
+        int c = s[i];
+        if (c == '\0')
+            break;
+        else if (c == '_')
+            buf[i] = '-';
+        else
+            buf[i] = tolower(c);
+    }
+    buf[i] = '\0';
+    if (strcmp(buf, "utf-8") == 0 ||
+        strncmp(buf, "utf-8-", 6) == 0)
+        return "utf-8";
+    else if (strcmp(buf, "latin-1") == 0 ||
+             strcmp(buf, "iso-8859-1") == 0 ||
+             strcmp(buf, "iso-latin-1") == 0 ||
+             strncmp(buf, "latin-1-", 8) == 0 ||
+             strncmp(buf, "iso-8859-1-", 11) == 0 ||
+             strncmp(buf, "iso-latin-1-", 12) == 0)
+        return "iso-8859-1";
+    else
+        return s;
+}
+
+/* Return the coding spec in S, or NULL if none is found.  */
+
+static char *
+get_coding_spec(const char *s, Py_ssize_t size)
+{
+    Py_ssize_t i;
+    /* Coding spec must be in a comment, and that comment must be
+     * the only statement on the source code line. */
+    for (i = 0; i < size - 6; i++) {
+        if (s[i] == '#')
+            break;
+        if (s[i] != ' ' && s[i] != '\t' && s[i] != '\014')
+            return NULL;
+    }
+    for (; i < size - 6; i++) { /* XXX inefficient search */
+        const char* t = s + i;
+        if (strncmp(t, "coding", 6) == 0) {
+            const char* begin = NULL;
+            t += 6;
+            if (t[0] != ':' && t[0] != '=')
+                continue;
+            do {
+                t++;
+            } while (t[0] == '\x20' || t[0] == '\t');
+
+            begin = t;
+            while (Py_ISALNUM(t[0]) ||
+                   t[0] == '-' || t[0] == '_' || t[0] == '.')
+                t++;
+
+            if (begin < t) {
+                char* r = new_string(begin, t - begin);
+                char* q;
+                if (!r)
+                    return NULL;
+                q = get_normal_name(r);
+                if (r != q) {
+                    PyMem_FREE(r);
+                    r = new_string(q, strlen(q));
+                }
+                return r;
+            }
+        }
+    }
+    return NULL;
+}
+
+/* Check whether the line contains a coding spec. If it does,
+   invoke the set_readline function for the new encoding.
+   This function receives the tok_state and the new encoding.
+   Return 1 on success, 0 on failure.  */
+
+static int
+check_coding_spec(const char* line, Py_ssize_t size, struct tok_state *tok,
+                  int set_readline(struct tok_state *, const char *))
+{
+    char * cs;
+    int r = 1;
+
+    if (tok->cont_line) {
+        /* It's a continuation line, so it can't be a coding spec. */
+        tok->read_coding_spec = 1;
+        return 1;
+    }
+    cs = get_coding_spec(line, size);
+    if (!cs) {
+        Py_ssize_t i;
+        for (i = 0; i < size; i++) {
+            if (line[i] == '#' || line[i] == '\n' || line[i] == '\r')
+                break;
+            if (line[i] != ' ' && line[i] != '\t' && line[i] != '\014') {
+                /* Stop checking coding spec after a line containing
+                 * anything except a comment. */
+                tok->read_coding_spec = 1;
+                break;
+            }
+        }
+    } else {
+        tok->read_coding_spec = 1;
+        if (tok->encoding == NULL) {
+            assert(tok->decoding_state == 1); /* raw */
+            if (strcmp(cs, "utf-8") == 0 ||
+                strcmp(cs, "iso-8859-1") == 0) {
+                tok->encoding = cs;
+            } else {
+#ifdef Py_USING_UNICODE
+                r = set_readline(tok, cs);
+                if (r) {
+                    tok->encoding = cs;
+                    tok->decoding_state = -1;
+                }
+                else {
+                    PyErr_Format(PyExc_SyntaxError,
+                                 "encoding problem: %s", cs);
+                    PyMem_FREE(cs);
+                }
+#else
+                /* Without Unicode support, we cannot
+                   process the coding spec. Since there
+                   won't be any Unicode literals, that
+                   won't matter. */
+                PyMem_FREE(cs);
+#endif
+            }
+        } else {                /* then, compare cs with BOM */
+            r = (strcmp(tok->encoding, cs) == 0);
+            if (!r)
+                PyErr_Format(PyExc_SyntaxError,
+                             "encoding problem: %s with BOM", cs);
+            PyMem_FREE(cs);
+        }
+    }
+    return r;
+}
+
+/* See whether the file starts with a BOM. If it does,
+   invoke the set_readline function with the new encoding.
+   Return 1 on success, 0 on failure.  */
+
+static int
+check_bom(int get_char(struct tok_state *),
+          void unget_char(int, struct tok_state *),
+          int set_readline(struct tok_state *, const char *),
+          struct tok_state *tok)
+{
+    int ch1, ch2, ch3;
+    ch1 = get_char(tok);
+    tok->decoding_state = 1;
+    if (ch1 == EOF) {
+        return 1;
+    } else if (ch1 == 0xEF) {
+        ch2 = get_char(tok);
+        if (ch2 != 0xBB) {
+            unget_char(ch2, tok);
+            unget_char(ch1, tok);
+            return 1;
+        }
+        ch3 = get_char(tok);
+        if (ch3 != 0xBF) {
+            unget_char(ch3, tok);
+            unget_char(ch2, tok);
+            unget_char(ch1, tok);
+            return 1;
+        }
+#if 0
+    /* Disable support for UTF-16 BOMs until a decision
+       is made whether this needs to be supported.  */
+    } else if (ch1 == 0xFE) {
+        ch2 = get_char(tok);
+        if (ch2 != 0xFF) {
+            unget_char(ch2, tok);
+            unget_char(ch1, tok);
+            return 1;
+        }
+        if (!set_readline(tok, "utf-16-be"))
+            return 0;
+        tok->decoding_state = -1;
+    } else if (ch1 == 0xFF) {
+        ch2 = get_char(tok);
+        if (ch2 != 0xFE) {
+            unget_char(ch2, tok);
+            unget_char(ch1, tok);
+            return 1;
+        }
+        if (!set_readline(tok, "utf-16-le"))
+            return 0;
+        tok->decoding_state = -1;
+#endif
+    } else {
+        unget_char(ch1, tok);
+        return 1;
+    }
+    if (tok->encoding != NULL)
+        PyMem_FREE(tok->encoding);
+    tok->encoding = new_string("utf-8", 5);     /* resulting is in utf-8 */
+    return 1;
+}
+
+/* Read a line of text from TOK into S, using the stream in TOK.
+   Return NULL on failure, else S.
+
+   On entry, tok->decoding_buffer will be one of:
+     1) NULL: need to call tok->decoding_readline to get a new line
+     2) PyUnicodeObject *: decoding_feof has called tok->decoding_readline and
+       stored the result in tok->decoding_buffer
+     3) PyBytesObject *: previous call to fp_readl did not have enough room
+       (in the s buffer) to copy entire contents of the line read
+       by tok->decoding_readline.  tok->decoding_buffer has the overflow.
+       In this case, fp_readl is called in a loop (with an expanded buffer)
+       until the buffer ends with a '\n' (or until the end of the file is
+       reached): see tok_nextc and its calls to decoding_fgets.
+*/
+
+static char *
+fp_readl(char *s, int size, struct tok_state *tok)
+{
+#ifndef Py_USING_UNICODE
+    /* In a non-Unicode built, this should never be called. */
+    Py_FatalError("fp_readl should not be called in this build.");
+    return NULL; /* Keep compiler happy (not reachable) */
+#else
+    PyObject* utf8 = NULL;
+    PyObject* buf = tok->decoding_buffer;
+    char *str;
+    Py_ssize_t utf8len;
+
+    /* Ask for one less byte so we can terminate it */
+    assert(size > 0);
+    size--;
+
+    if (buf == NULL) {
+        buf = PyObject_CallObject(tok->decoding_readline, NULL);
+        if (buf == NULL)
+            return error_ret(tok);
+        if (!PyUnicode_Check(buf)) {
+            Py_DECREF(buf);
+            PyErr_SetString(PyExc_SyntaxError,
+                            "codec did not return a unicode object");
+            return error_ret(tok);
+        }
+    } else {
+        tok->decoding_buffer = NULL;
+        if (PyBytes_CheckExact(buf))
+            utf8 = buf;
+    }
+    if (utf8 == NULL) {
+        utf8 = PyUnicode_AsUTF8String(buf);
+        Py_DECREF(buf);
+        if (utf8 == NULL)
+            return error_ret(tok);
+    }
+    str = PyBytes_AsString(utf8);
+    utf8len = PyBytes_GET_SIZE(utf8);
+    if (utf8len > size) {
+        tok->decoding_buffer = PyBytes_FromStringAndSize(str+size, utf8len-size);
+        if (tok->decoding_buffer == NULL) {
+            Py_DECREF(utf8);
+            return error_ret(tok);
+        }
+        utf8len = size;
+    }
+    memcpy(s, str, utf8len);
+    s[utf8len] = '\0';
+    Py_DECREF(utf8);
+    if (utf8len == 0)
+        return NULL; /* EOF */
+    return s;
+#endif
+}
+
+/* Set the readline function for TOK to a StreamReader's
+   readline function. The StreamReader is named ENC.
+
+   This function is called from check_bom and check_coding_spec.
+
+   ENC is usually identical to the future value of tok->encoding,
+   except for the (currently unsupported) case of UTF-16.
+
+   Return 1 on success, 0 on failure. */
+
+/* taken from Python 3.5.1 */
+
+static int
+fp_setreadl(struct tok_state *tok, const char* enc)
+{
+    PyObject *readline = NULL, *stream = NULL, *io = NULL;
+    _Py_IDENTIFIER(open);
+    _Py_IDENTIFIER(readline);
+    int fd;
+    long pos;
+
+    io = PyImport_ImportModuleNoBlock("io");
+    if (io == NULL)
+        goto cleanup;
+
+    fd = fileno(tok->fp);
+    /* Due to buffering the file offset for fd can be different from the file
+     * position of tok->fp.  If tok->fp was opened in text mode on Windows,
+     * its file position counts CRLF as one char and can't be directly mapped
+     * to the file offset for fd.  Instead we step back one byte and read to
+     * the end of line.*/
+    pos = ftell(tok->fp);
+    if (pos == -1 ||
+        lseek(fd, (off_t)(pos > 0 ? pos - 1 : pos), SEEK_SET) == (off_t)-1) {
+        PyErr_SetFromErrnoWithFilename(PyExc_OSError, NULL);
+        goto cleanup;
+    }
+
+    stream = _PyObject_CallMethodId(io, &PyId_open, "isisOOO",
+                    fd, "r", -1, enc, Py_None, Py_None, Py_False);
+    if (stream == NULL)
+        goto cleanup;
+
+    Py_XDECREF(tok->decoding_readline);
+    readline = _PyObject_GetAttrId(stream, &PyId_readline);
+    tok->decoding_readline = readline;
+    if (pos > 0) {
+        if (PyObject_CallObject(readline, NULL) == NULL) {
+            readline = NULL;
+            goto cleanup;
+        }
+    }
+
+  cleanup:
+    Py_XDECREF(stream);
+    Py_XDECREF(io);
+    return readline != NULL;
+}
+
+/* Fetch the next byte from TOK. */
+
+static int fp_getc(struct tok_state *tok) {
+    return getc(tok->fp);
+}
+
+/* Unfetch the last byte back into TOK.  */
+
+static void fp_ungetc(int c, struct tok_state *tok) {
+    ungetc(c, tok->fp);
+}
+
+/* Read a line of input from TOK. Determine encoding
+   if necessary.  */
+
+static char *
+decoding_fgets(char *s, int size, struct tok_state *tok)
+{
+    char *line = NULL;
+    int badchar = 0;
+    for (;;) {
+        if (tok->decoding_state < 0) {
+            /* We already have a codec associated with
+               this input. */
+            line = fp_readl(s, size, tok);
+            break;
+        } else if (tok->decoding_state > 0) {
+            /* We want a 'raw' read. */
+            line = Py_UniversalNewlineFgets(s, size,
+                                            tok->fp, NULL);
+            break;
+        } else {
+            /* We have not yet determined the encoding.
+               If an encoding is found, use the file-pointer
+               reader functions from now on. */
+            if (!check_bom(fp_getc, fp_ungetc, fp_setreadl, tok))
+                return error_ret(tok);
+            assert(tok->decoding_state != 0);
+        }
+    }
+    if (line != NULL && tok->lineno < 2 && !tok->read_coding_spec) {
+        if (!check_coding_spec(line, strlen(line), tok, fp_setreadl)) {
+            return error_ret(tok);
+        }
+    }
+#ifndef PGEN
+    /* The default encoding is ASCII, so make sure we don't have any
+       non-ASCII bytes in it. */
+    if (line && !tok->encoding) {
+        unsigned char *c;
+        for (c = (unsigned char *)line; *c; c++)
+            if (*c > 127) {
+                badchar = *c;
+                break;
+            }
+    }
+    if (badchar) {
+        char buf[500];
+        /* Need to add 1 to the line number, since this line
+           has not been counted, yet.  */
+        sprintf(buf,
+            "Non-ASCII character '\\x%.2x' "
+            "in file %.200s on line %i, "
+            "but no encoding declared; "
+            "see http://python.org/dev/peps/pep-0263/ for details",
+            badchar, tok->filename, tok->lineno + 1);
+        PyErr_SetString(PyExc_SyntaxError, buf);
+        return error_ret(tok);
+    }
+#endif
+    return line;
+}
+
+static int
+decoding_feof(struct tok_state *tok)
+{
+    if (tok->decoding_state >= 0) {
+        return feof(tok->fp);
+    } else {
+        PyObject* buf = tok->decoding_buffer;
+        if (buf == NULL) {
+            buf = PyObject_CallObject(tok->decoding_readline, NULL);
+            if (buf == NULL) {
+                error_ret(tok);
+                return 1;
+            } else {
+                tok->decoding_buffer = buf;
+            }
+        }
+        return PyObject_Length(buf) == 0;
+    }
+}
+
+/* Fetch a byte from TOK, using the string buffer. */
+
+static int
+buf_getc(struct tok_state *tok) {
+    return Py_CHARMASK(*tok->str++);
+}
+
+/* Unfetch a byte from TOK, using the string buffer. */
+
+static void
+buf_ungetc(int c, struct tok_state *tok) {
+    tok->str--;
+    assert(Py_CHARMASK(*tok->str) == c);        /* tok->cur may point to read-only segment */
+}
+
+/* Set the readline function for TOK to ENC. For the string-based
+   tokenizer, this means to just record the encoding. */
+
+static int
+buf_setreadl(struct tok_state *tok, const char* enc) {
+    tok->enc = enc;
+    return 1;
+}
+
+/* Return a UTF-8 encoding Python string object from the
+   C byte string STR, which is encoded with ENC. */
+
+#ifdef Py_USING_UNICODE
+static PyObject *
+translate_into_utf8(const char* str, const char* enc) {
+    PyObject *utf8;
+    PyObject* buf = PyUnicode_Decode(str, strlen(str), enc, NULL);
+    if (buf == NULL)
+        return NULL;
+    utf8 = PyUnicode_AsUTF8String(buf);
+    Py_DECREF(buf);
+    return utf8;
+}
+#endif
+
+
+static char *
+translate_newlines(const char *s, int exec_input, struct tok_state *tok) {
+    int skip_next_lf = 0, needed_length = strlen(s) + 2, final_length;
+    char *buf, *current;
+    char c = '\0';
+    buf = PyMem_MALLOC(needed_length);
+    if (buf == NULL) {
+        tok->done = E_NOMEM;
+        return NULL;
+    }
+    for (current = buf; *s; s++, current++) {
+        c = *s;
+        if (skip_next_lf) {
+            skip_next_lf = 0;
+            if (c == '\n') {
+                c = *++s;
+                if (!c)
+                    break;
+            }
+        }
+        if (c == '\r') {
+            skip_next_lf = 1;
+            c = '\n';
+        }
+        *current = c;
+    }
+    /* If this is exec input, add a newline to the end of the string if
+       there isn't one already. */
+    if (exec_input && c != '\n') {
+        *current = '\n';
+        current++;
+    }
+    *current = '\0';
+    final_length = current - buf + 1;
+    if (final_length < needed_length && final_length)
+        /* should never fail */
+        buf = PyMem_REALLOC(buf, final_length);
+    return buf;
+}
+
+/* Decode a byte string STR for use as the buffer of TOK.
+   Look for encoding declarations inside STR, and record them
+   inside TOK.  */
+
+static const char *
+decode_str(const char *input, int single, struct tok_state *tok)
+{
+    PyObject* utf8 = NULL;
+    const char *str;
+    const char *s;
+    const char *newl[2] = {NULL, NULL};
+    int lineno = 0;
+    tok->input = str = translate_newlines(input, single, tok);
+    if (str == NULL)
+        return NULL;
+    tok->enc = NULL;
+    tok->str = str;
+    if (!check_bom(buf_getc, buf_ungetc, buf_setreadl, tok))
+        return error_ret(tok);
+    str = tok->str;             /* string after BOM if any */
+    assert(str);
+#ifdef Py_USING_UNICODE
+    if (tok->enc != NULL) {
+        utf8 = translate_into_utf8(str, tok->enc);
+        if (utf8 == NULL)
+            return error_ret(tok);
+        str = PyBytes_AsString(utf8);
+    }
+#endif
+    for (s = str;; s++) {
+        if (*s == '\0') break;
+        else if (*s == '\n') {
+            assert(lineno < 2);
+            newl[lineno] = s;
+            lineno++;
+            if (lineno == 2) break;
+        }
+    }
+    tok->enc = NULL;
+    /* need to check line 1 and 2 separately since check_coding_spec
+       assumes a single line as input */
+    if (newl[0]) {
+        if (!check_coding_spec(str, newl[0] - str, tok, buf_setreadl))
+            return error_ret(tok);
+        if (tok->enc == NULL && !tok->read_coding_spec && newl[1]) {
+            if (!check_coding_spec(newl[0]+1, newl[1] - newl[0],
+                                   tok, buf_setreadl))
+                return error_ret(tok);
+        }
+    }
+#ifdef Py_USING_UNICODE
+    if (tok->enc != NULL) {
+        assert(utf8 == NULL);
+        utf8 = translate_into_utf8(str, tok->enc);
+        if (utf8 == NULL)
+            return error_ret(tok);
+        str = PyBytes_AsString(utf8);
+    }
+#endif
+    assert(tok->decoding_buffer == NULL);
+    tok->decoding_buffer = utf8; /* CAUTION */
+    return str;
+}
+
+#endif /* PGEN */
+
+/* Set up tokenizer for string */
+
+struct tok_state *
+Ta27Tokenizer_FromString(const char *str, int exec_input)
+{
+    struct tok_state *tok = tok_new();
+    if (tok == NULL)
+        return NULL;
+    str = (char *)decode_str(str, exec_input, tok);
+    if (str == NULL) {
+        Ta27Tokenizer_Free(tok);
+        return NULL;
+    }
+
+    /* XXX: constify members. */
+    tok->buf = tok->cur = tok->end = tok->inp = (char*)str;
+    return tok;
+}
+
+/* adapted from Python 3.5.1 */
+struct tok_state *
+Ta27Tokenizer_FromUTF8(const char *str, int exec_input)
+{
+    struct tok_state *tok = tok_new();
+    if (tok == NULL)
+        return NULL;
+#ifndef PGEN
+    tok->input = str = translate_newlines(str, exec_input, tok);
+#endif
+    if (str == NULL) {
+        Ta27Tokenizer_Free(tok);
+        return NULL;
+    }
+    tok->decoding_state = 1;
+    tok->read_coding_spec = 1;
+    tok->enc = NULL;
+    tok->str = str;
+
+    /* XXX: constify members. */
+    tok->buf = tok->cur = tok->end = tok->inp = (char*)str;
+    return tok;
+}
+
+
+/* Set up tokenizer for file */
+
+struct tok_state *
+Ta27Tokenizer_FromFile(FILE *fp, char *ps1, char *ps2)
+{
+    struct tok_state *tok = tok_new();
+    if (tok == NULL)
+        return NULL;
+    if ((tok->buf = (char *)PyMem_MALLOC(BUFSIZ)) == NULL) {
+        Ta27Tokenizer_Free(tok);
+        return NULL;
+    }
+    tok->cur = tok->inp = tok->buf;
+    tok->end = tok->buf + BUFSIZ;
+    tok->fp = fp;
+    tok->prompt = ps1;
+    tok->nextprompt = ps2;
+    return tok;
+}
+
+
+/* Free a tok_state structure */
+
+void
+Ta27Tokenizer_Free(struct tok_state *tok)
+{
+    if (tok->encoding != NULL)
+        PyMem_FREE(tok->encoding);
+#ifndef PGEN
+    Py_XDECREF(tok->decoding_readline);
+    Py_XDECREF(tok->decoding_buffer);
+#endif
+    if (tok->fp != NULL && tok->buf != NULL)
+        PyMem_FREE(tok->buf);
+    if (tok->input)
+        PyMem_FREE((char *)tok->input);
+    PyMem_FREE(tok);
+}
+
+/* Get next char, updating state; error code goes into tok->done */
+/* taken from Python 3.5.1 */
+static int
+tok_nextc(struct tok_state *tok)
+{
+    for (;;) {
+        if (tok->cur != tok->inp) {
+            return Py_CHARMASK(*tok->cur++); /* Fast path */
+        }
+        if (tok->done != E_OK)
+            return EOF;
+        if (tok->fp == NULL) {
+            char *end = strchr(tok->inp, '\n');
+            if (end != NULL)
+                end++;
+            else {
+                end = strchr(tok->inp, '\0');
+                if (end == tok->inp) {
+                    tok->done = E_EOF;
+                    return EOF;
+                }
+            }
+            if (tok->start == NULL)
+                tok->buf = tok->cur;
+            tok->line_start = tok->cur;
+            tok->lineno++;
+            tok->inp = end;
+            return Py_CHARMASK(*tok->cur++);
+        }
+        if (tok->prompt != NULL) {
+            char *newtok = PyOS_Readline(stdin, stdout, tok->prompt);
+#ifndef PGEN
+            if (newtok != NULL) {
+                char *translated = translate_newlines(newtok, 0, tok);
+                PyMem_FREE(newtok);
+                if (translated == NULL)
+                    return EOF;
+                newtok = translated;
+            }
+            if (tok->encoding && newtok && *newtok) {
+                /* Recode to UTF-8 */
+                Py_ssize_t buflen;
+                const char* buf;
+                PyObject *u = translate_into_utf8(newtok, tok->encoding);
+                PyMem_FREE(newtok);
+                if (!u) {
+                    tok->done = E_DECODE;
+                    return EOF;
+                }
+                buflen = PyBytes_GET_SIZE(u);
+                buf = PyBytes_AS_STRING(u);
+                newtok = PyMem_MALLOC(buflen+1);
+                strcpy(newtok, buf);
+                Py_DECREF(u);
+            }
+#endif
+            if (tok->nextprompt != NULL)
+                tok->prompt = tok->nextprompt;
+            if (newtok == NULL)
+                tok->done = E_INTR;
+            else if (*newtok == '\0') {
+                PyMem_FREE(newtok);
+                tok->done = E_EOF;
+            }
+            else if (tok->start != NULL) {
+                size_t start = tok->start - tok->buf;
+                size_t oldlen = tok->cur - tok->buf;
+                size_t newlen = oldlen + strlen(newtok);
+                char *buf = tok->buf;
+                buf = (char *)PyMem_REALLOC(buf, newlen+1);
+                tok->lineno++;
+                if (buf == NULL) {
+                    PyMem_FREE(tok->buf);
+                    tok->buf = NULL;
+                    PyMem_FREE(newtok);
+                    tok->done = E_NOMEM;
+                    return EOF;
+                }
+                tok->buf = buf;
+                tok->cur = tok->buf + oldlen;
+                tok->line_start = tok->cur;
+                strcpy(tok->buf + oldlen, newtok);
+                PyMem_FREE(newtok);
+                tok->inp = tok->buf + newlen;
+                tok->end = tok->inp + 1;
+                tok->start = tok->buf + start;
+            }
+            else {
+                tok->lineno++;
+                if (tok->buf != NULL)
+                    PyMem_FREE(tok->buf);
+                tok->buf = newtok;
+                tok->cur = tok->buf;
+                tok->line_start = tok->buf;
+                tok->inp = strchr(tok->buf, '\0');
+                tok->end = tok->inp + 1;
+            }
+        }
+        else {
+            int done = 0;
+            Py_ssize_t cur = 0;
+            char *pt;
+            if (tok->start == NULL) {
+                if (tok->buf == NULL) {
+                    tok->buf = (char *)
+                        PyMem_MALLOC(BUFSIZ);
+                    if (tok->buf == NULL) {
+                        tok->done = E_NOMEM;
+                        return EOF;
+                    }
+                    tok->end = tok->buf + BUFSIZ;
+                }
+                if (decoding_fgets(tok->buf, (int)(tok->end - tok->buf),
+                          tok) == NULL) {
+                    if (!tok->decoding_erred)
+                        tok->done = E_EOF;
+                    done = 1;
+                }
+                else {
+                    tok->done = E_OK;
+                    tok->inp = strchr(tok->buf, '\0');
+                    done = tok->inp[-1] == '\n';
+                }
+            }
+            else {
+                cur = tok->cur - tok->buf;
+                if (decoding_feof(tok)) {
+                    tok->done = E_EOF;
+                    done = 1;
+                }
+                else
+                    tok->done = E_OK;
+            }
+            tok->lineno++;
+            /* Read until '\n' or EOF */
+            while (!done) {
+                Py_ssize_t curstart = tok->start == NULL ? -1 :
+                          tok->start - tok->buf;
+                Py_ssize_t curvalid = tok->inp - tok->buf;
+                Py_ssize_t newsize = curvalid + BUFSIZ;
+                char *newbuf = tok->buf;
+                newbuf = (char *)PyMem_REALLOC(newbuf,
+                                               newsize);
+                if (newbuf == NULL) {
+                    tok->done = E_NOMEM;
+                    tok->cur = tok->inp;
+                    return EOF;
+                }
+                tok->buf = newbuf;
+                tok->cur = tok->buf + cur;
+                tok->line_start = tok->cur;
+                tok->inp = tok->buf + curvalid;
+                tok->end = tok->buf + newsize;
+                tok->start = curstart < 0 ? NULL :
+                         tok->buf + curstart;
+                if (decoding_fgets(tok->inp,
+                               (int)(tok->end - tok->inp),
+                               tok) == NULL) {
+                    /* Break out early on decoding
+                       errors, as tok->buf will be NULL
+                     */
+                    if (tok->decoding_erred)
+                        return EOF;
+                    /* Last line does not end in \n,
+                       fake one */
+                    strcpy(tok->inp, "\n");
+                }
+                tok->inp = strchr(tok->inp, '\0');
+                done = tok->inp[-1] == '\n';
+            }
+            if (tok->buf != NULL) {
+                tok->cur = tok->buf + cur;
+                tok->line_start = tok->cur;
+                /* replace "\r\n" with "\n" */
+                /* For Mac leave the \r, giving a syntax error */
+                pt = tok->inp - 2;
+                if (pt >= tok->buf && *pt == '\r') {
+                    *pt++ = '\n';
+                    *pt = '\0';
+                    tok->inp = pt;
+                }
+            }
+        }
+        if (tok->done != E_OK) {
+            if (tok->prompt != NULL)
+                PySys_WriteStderr("\n");
+            tok->cur = tok->inp;
+            return EOF;
+        }
+    }
+    /*NOTREACHED*/
+}
+
+
+/* Back-up one character */
+
+static void
+tok_backup(register struct tok_state *tok, register int c)
+{
+    if (c != EOF) {
+        if (--tok->cur < tok->buf)
+            Py_FatalError("tok_backup: beginning of buffer");
+        if (*tok->cur != c)
+            *tok->cur = c;
+    }
+}
+
+
+/* Return the token corresponding to a single character */
+
+int
+Ta27Token_OneChar(int c)
+{
+    switch (c) {
+    case '(':           return LPAR;
+    case ')':           return RPAR;
+    case '[':           return LSQB;
+    case ']':           return RSQB;
+    case ':':           return COLON;
+    case ',':           return COMMA;
+    case ';':           return SEMI;
+    case '+':           return PLUS;
+    case '-':           return MINUS;
+    case '*':           return STAR;
+    case '/':           return SLASH;
+    case '|':           return VBAR;
+    case '&':           return AMPER;
+    case '<':           return LESS;
+    case '>':           return GREATER;
+    case '=':           return EQUAL;
+    case '.':           return DOT;
+    case '%':           return PERCENT;
+    case '`':           return BACKQUOTE;
+    case '{':           return LBRACE;
+    case '}':           return RBRACE;
+    case '^':           return CIRCUMFLEX;
+    case '~':           return TILDE;
+    case '@':       return AT;
+    default:            return OP;
+    }
+}
+
+
+int
+Ta27Token_TwoChars(int c1, int c2)
+{
+    switch (c1) {
+    case '=':
+        switch (c2) {
+        case '=':               return EQEQUAL;
+        }
+        break;
+    case '!':
+        switch (c2) {
+        case '=':               return NOTEQUAL;
+        }
+        break;
+    case '<':
+        switch (c2) {
+        case '>':               return NOTEQUAL;
+        case '=':               return LESSEQUAL;
+        case '<':               return LEFTSHIFT;
+        }
+        break;
+    case '>':
+        switch (c2) {
+        case '=':               return GREATEREQUAL;
+        case '>':               return RIGHTSHIFT;
+        }
+        break;
+    case '+':
+        switch (c2) {
+        case '=':               return PLUSEQUAL;
+        }
+        break;
+    case '-':
+        switch (c2) {
+        case '=':               return MINEQUAL;
+        case '>':               return RARROW;
+        }
+        break;
+    case '*':
+        switch (c2) {
+        case '*':               return DOUBLESTAR;
+        case '=':               return STAREQUAL;
+        }
+        break;
+    case '/':
+        switch (c2) {
+        case '/':               return DOUBLESLASH;
+        case '=':               return SLASHEQUAL;
+        }
+        break;
+    case '|':
+        switch (c2) {
+        case '=':               return VBAREQUAL;
+        }
+        break;
+    case '%':
+        switch (c2) {
+        case '=':               return PERCENTEQUAL;
+        }
+        break;
+    case '&':
+        switch (c2) {
+        case '=':               return AMPEREQUAL;
+        }
+        break;
+    case '^':
+        switch (c2) {
+        case '=':               return CIRCUMFLEXEQUAL;
+        }
+        break;
+    }
+    return OP;
+}
+
+int
+Ta27Token_ThreeChars(int c1, int c2, int c3)
+{
+    switch (c1) {
+    case '<':
+        switch (c2) {
+        case '<':
+            switch (c3) {
+            case '=':
+                return LEFTSHIFTEQUAL;
+            }
+            break;
+        }
+        break;
+    case '>':
+        switch (c2) {
+        case '>':
+            switch (c3) {
+            case '=':
+                return RIGHTSHIFTEQUAL;
+            }
+            break;
+        }
+        break;
+    case '*':
+        switch (c2) {
+        case '*':
+            switch (c3) {
+            case '=':
+                return DOUBLESTAREQUAL;
+            }
+            break;
+        }
+        break;
+    case '/':
+        switch (c2) {
+        case '/':
+            switch (c3) {
+            case '=':
+                return DOUBLESLASHEQUAL;
+            }
+            break;
+        }
+        break;
+    }
+    return OP;
+}
+
+static int
+indenterror(struct tok_state *tok)
+{
+    if (tok->alterror) {
+        tok->done = E_TABSPACE;
+        tok->cur = tok->inp;
+        return 1;
+    }
+    if (tok->altwarning) {
+        PySys_WriteStderr("%s: inconsistent use of tabs and spaces "
+                          "in indentation\n", tok->filename);
+        tok->altwarning = 0;
+    }
+    return 0;
+}
+
+/* Get next token, after space stripping etc. */
+
+static int
+tok_get(register struct tok_state *tok, char **p_start, char **p_end)
+{
+    register int c;
+    int blankline;
+
+    *p_start = *p_end = NULL;
+  nextline:
+    tok->start = NULL;
+    blankline = 0;
+
+    /* Get indentation level */
+    if (tok->atbol) {
+        register int col = 0;
+        register int altcol = 0;
+        tok->atbol = 0;
+        for (;;) {
+            c = tok_nextc(tok);
+            if (c == ' ')
+                col++, altcol++;
+            else if (c == '\t') {
+                col = (col/tok->tabsize + 1) * tok->tabsize;
+                altcol = (altcol/tok->alttabsize + 1)
+                    * tok->alttabsize;
+            }
+            else if (c == '\014') /* Control-L (formfeed) */
+                col = altcol = 0; /* For Emacs users */
+            else
+                break;
+        }
+        tok_backup(tok, c);
+        if (c == '#' || c == '\n') {
+            /* Lines with only whitespace and/or comments
+               shouldn't affect the indentation and are
+               not passed to the parser as NEWLINE tokens,
+               except *totally* empty lines in interactive
+               mode, which signal the end of a command group. */
+            if (col == 0 && c == '\n' && tok->prompt != NULL)
+                blankline = 0; /* Let it through */
+            else
+                blankline = 1; /* Ignore completely */
+            /* We can't jump back right here since we still
+               may need to skip to the end of a comment */
+        }
+        if (!blankline && tok->level == 0) {
+            if (col == tok->indstack[tok->indent]) {
+                /* No change */
+                if (altcol != tok->altindstack[tok->indent]) {
+                    if (indenterror(tok))
+                        return ERRORTOKEN;
+                }
+            }
+            else if (col > tok->indstack[tok->indent]) {
+                /* Indent -- always one */
+                if (tok->indent+1 >= MAXINDENT) {
+                    tok->done = E_TOODEEP;
+                    tok->cur = tok->inp;
+                    return ERRORTOKEN;
+                }
+                if (altcol <= tok->altindstack[tok->indent]) {
+                    if (indenterror(tok))
+                        return ERRORTOKEN;
+                }
+                tok->pendin++;
+                tok->indstack[++tok->indent] = col;
+                tok->altindstack[tok->indent] = altcol;
+            }
+            else /* col < tok->indstack[tok->indent] */ {
+                /* Dedent -- any number, must be consistent */
+                while (tok->indent > 0 &&
+                    col < tok->indstack[tok->indent]) {
+                    tok->pendin--;
+                    tok->indent--;
+                }
+                if (col != tok->indstack[tok->indent]) {
+                    tok->done = E_DEDENT;
+                    tok->cur = tok->inp;
+                    return ERRORTOKEN;
+                }
+                if (altcol != tok->altindstack[tok->indent]) {
+                    if (indenterror(tok))
+                        return ERRORTOKEN;
+                }
+            }
+        }
+    }
+
+    tok->start = tok->cur;
+
+    /* Return pending indents/dedents */
+    if (tok->pendin != 0) {
+        if (tok->pendin < 0) {
+            tok->pendin++;
+            return DEDENT;
+        }
+        else {
+            tok->pendin--;
+            return INDENT;
+        }
+    }
+
+ again:
+    tok->start = NULL;
+    /* Skip spaces */
+    do {
+        c = tok_nextc(tok);
+    } while (c == ' ' || c == '\t' || c == '\014');
+
+    /* Set start of current token */
+    tok->start = tok->cur - 1;
+
+    /* Skip comment, while looking for tab-setting magic and type comments */
+    if (c == '#') {
+        static char *tabforms[] = {
+            "tab-width:",                       /* Emacs */
+            ":tabstop=",                        /* vim, full form */
+            ":ts=",                             /* vim, abbreviated form */
+            "set tabsize=",                     /* will vi never die? */
+        /* more templates can be added here to support other editors */
+        };
+        char cbuf[80];
+        char *tp, **cp;
+        tp = cbuf;
+        do {
+            *tp++ = c = tok_nextc(tok);
+        } while (c != EOF && c != '\n' &&
+                 (size_t)(tp - cbuf + 1) < sizeof(cbuf));
+        *tp = '\0';
+        for (cp = tabforms;
+             cp < tabforms + sizeof(tabforms)/sizeof(tabforms[0]);
+             cp++) {
+            if ((tp = strstr(cbuf, *cp))) {
+                int newsize = atoi(tp + strlen(*cp));
+
+                if (newsize >= 1 && newsize <= 40) {
+                    tok->tabsize = newsize;
+                    if (Py_VerboseFlag)
+                        PySys_WriteStderr(
+                        "Tab size set to %d\n",
+                        newsize);
+                }
+            }
+        }
+        while (c != EOF && c != '\n')
+            c = tok_nextc(tok);
+
+        /* check for type comment */
+        const char *prefix, *p, *type_start;
+        p = tok->start;
+        prefix = type_comment_prefix;
+        while (*prefix && p < tok->cur) {
+            if (*prefix == ' ') {
+                while (*p == ' ' || *p == '\t')
+                    p++;
+            } else if (*prefix == *p) {
+                p++;
+            } else {
+                break;
+            }
+
+            prefix++;
+        }
+
+        /* This is a type comment if we matched all of type_comment_prefix. */
+        if (!*prefix) {
+            int is_type_ignore = 1;
+            tok_backup(tok, c);  /* don't eat the newline or EOF */
+
+            type_start = p;
+
+            is_type_ignore = tok->cur >= p + 6 && memcmp(p, "ignore", 6) == 0;
+            p += 6;
+            while (is_type_ignore && p < tok->cur) {
+              if (*p == '#')
+                  break;
+              is_type_ignore = is_type_ignore && (*p == ' ' || *p == '\t');
+              p++;
+            }
+
+            if (is_type_ignore) {
+                /* If this type ignore is the only thing on the line, consume the newline also. */
+                if (blankline) {
+                    tok_nextc(tok);
+                    tok->atbol = 1;
+                }
+                return TYPE_IGNORE;
+            } else {
+                *p_start = (char *) type_start;  /* after type_comment_prefix */
+                *p_end = tok->cur;
+                return TYPE_COMMENT;
+            }
+        }
+
+    }
+
+    /* Check for EOF and errors now */
+    if (c == EOF) {
+        return tok->done == E_EOF ? ENDMARKER : ERRORTOKEN;
+    }
+
+    /* Identifier (most frequent token!) */
+    if (Py_ISALPHA(c) || c == '_') {
+        /* Process r"", u"" and ur"" */
+        switch (c) {
+        case 'b':
+        case 'B':
+            c = tok_nextc(tok);
+            if (c == 'r' || c == 'R')
+                c = tok_nextc(tok);
+            if (c == '"' || c == '\'')
+                goto letter_quote;
+            break;
+        case 'r':
+        case 'R':
+            c = tok_nextc(tok);
+            if (c == '"' || c == '\'')
+                goto letter_quote;
+            break;
+        case 'u':
+        case 'U':
+            c = tok_nextc(tok);
+            if (c == 'r' || c == 'R')
+                c = tok_nextc(tok);
+            if (c == '"' || c == '\'')
+                goto letter_quote;
+            break;
+        }
+        while (c != EOF && (Py_ISALNUM(c) || c == '_')) {
+            c = tok_nextc(tok);
+        }
+        tok_backup(tok, c);
+        *p_start = tok->start;
+        *p_end = tok->cur;
+        return NAME;
+    }
+
+    /* Newline */
+    if (c == '\n') {
+        tok->atbol = 1;
+        if (blankline || tok->level > 0)
+            goto nextline;
+        *p_start = tok->start;
+        *p_end = tok->cur - 1; /* Leave '\n' out of the string */
+        tok->cont_line = 0;
+        return NEWLINE;
+    }
+
+    /* Period or number starting with period? */
+    if (c == '.') {
+        c = tok_nextc(tok);
+        if (isdigit(c)) {
+            goto fraction;
+        }
+        else {
+            tok_backup(tok, c);
+            *p_start = tok->start;
+            *p_end = tok->cur;
+            return DOT;
+        }
+    }
+
+    /* Number */
+    if (isdigit(c)) {
+        if (c == '0') {
+            /* Hex, octal or binary -- maybe. */
+            c = tok_nextc(tok);
+            if (c == '.')
+                goto fraction;
+#ifndef WITHOUT_COMPLEX
+            if (c == 'j' || c == 'J')
+                goto imaginary;
+#endif
+            if (c == 'x' || c == 'X') {
+
+                /* Hex */
+                c = tok_nextc(tok);
+                if (!isxdigit(c)) {
+                    tok->done = E_TOKEN;
+                    tok_backup(tok, c);
+                    return ERRORTOKEN;
+                }
+                do {
+                    c = tok_nextc(tok);
+                } while (isxdigit(c));
+            }
+            else if (c == 'o' || c == 'O') {
+                /* Octal */
+                c = tok_nextc(tok);
+                if (c < '0' || c >= '8') {
+                    tok->done = E_TOKEN;
+                    tok_backup(tok, c);
+                    return ERRORTOKEN;
+                }
+                do {
+                    c = tok_nextc(tok);
+                } while ('0' <= c && c < '8');
+            }
+            else if (c == 'b' || c == 'B') {
+                /* Binary */
+                c = tok_nextc(tok);
+                if (c != '0' && c != '1') {
+                    tok->done = E_TOKEN;
+                    tok_backup(tok, c);
+                    return ERRORTOKEN;
+                }
+                do {
+                    c = tok_nextc(tok);
+                } while (c == '0' || c == '1');
+            }
+            else {
+                int found_decimal = 0;
+                /* Octal; c is first char of it */
+                /* There's no 'isoctdigit' macro, sigh */
+                while ('0' <= c && c < '8') {
+                    c = tok_nextc(tok);
+                }
+                if (isdigit(c)) {
+                    found_decimal = 1;
+                    do {
+                        c = tok_nextc(tok);
+                    } while (isdigit(c));
+                }
+                if (c == '.')
+                    goto fraction;
+                else if (c == 'e' || c == 'E')
+                    goto exponent;
+#ifndef WITHOUT_COMPLEX
+                else if (c == 'j' || c == 'J')
+                    goto imaginary;
+#endif
+                else if (found_decimal) {
+                    tok->done = E_TOKEN;
+                    tok_backup(tok, c);
+                    return ERRORTOKEN;
+                }
+            }
+            if (c == 'l' || c == 'L')
+                c = tok_nextc(tok);
+        }
+        else {
+            /* Decimal */
+            do {
+                c = tok_nextc(tok);
+            } while (isdigit(c));
+            if (c == 'l' || c == 'L')
+                c = tok_nextc(tok);
+            else {
+                /* Accept floating point numbers. */
+                if (c == '.') {
+        fraction:
+                    /* Fraction */
+                    do {
+                        c = tok_nextc(tok);
+                    } while (isdigit(c));
+                }
+                if (c == 'e' || c == 'E') {
+                    int e;
+                  exponent:
+                    e = c;
+                    /* Exponent part */
+                    c = tok_nextc(tok);
+                    if (c == '+' || c == '-') {
+                        c = tok_nextc(tok);
+                        if (!isdigit(c)) {
+                            tok->done = E_TOKEN;
+                            tok_backup(tok, c);
+                            return ERRORTOKEN;
+                        }
+                    } else if (!isdigit(c)) {
+                        tok_backup(tok, c);
+                        tok_backup(tok, e);
+                        *p_start = tok->start;
+                        *p_end = tok->cur;
+                        return NUMBER;
+                    }
+                    do {
+                        c = tok_nextc(tok);
+                    } while (isdigit(c));
+                }
+#ifndef WITHOUT_COMPLEX
+                if (c == 'j' || c == 'J')
+                    /* Imaginary part */
+        imaginary:
+                    c = tok_nextc(tok);
+#endif
+            }
+        }
+        tok_backup(tok, c);
+        *p_start = tok->start;
+        *p_end = tok->cur;
+        return NUMBER;
+    }
+
+  letter_quote:
+    /* String */
+    if (c == '\'' || c == '"') {
+        Py_ssize_t quote2 = tok->cur - tok->start + 1;
+        int quote = c;
+        int triple = 0;
+        int tripcount = 0;
+        for (;;) {
+            c = tok_nextc(tok);
+            if (c == '\n') {
+                if (!triple) {
+                    tok->done = E_EOLS;
+                    tok_backup(tok, c);
+                    return ERRORTOKEN;
+                }
+                tripcount = 0;
+                tok->cont_line = 1; /* multiline string. */
+            }
+            else if (c == EOF) {
+                if (triple)
+                    tok->done = E_EOFS;
+                else
+                    tok->done = E_EOLS;
+                tok->cur = tok->inp;
+                return ERRORTOKEN;
+            }
+            else if (c == quote) {
+                tripcount++;
+                if (tok->cur - tok->start == quote2) {
+                    c = tok_nextc(tok);
+                    if (c == quote) {
+                        triple = 1;
+                        tripcount = 0;
+                        continue;
+                    }
+                    tok_backup(tok, c);
+                }
+                if (!triple || tripcount == 3)
+                    break;
+            }
+            else if (c == '\\') {
+                tripcount = 0;
+                c = tok_nextc(tok);
+                if (c == EOF) {
+                    tok->done = E_EOLS;
+                    tok->cur = tok->inp;
+                    return ERRORTOKEN;
+                }
+            }
+            else
+                tripcount = 0;
+        }
+        *p_start = tok->start;
+        *p_end = tok->cur;
+        return STRING;
+    }
+
+    /* Line continuation */
+    if (c == '\\') {
+        c = tok_nextc(tok);
+        if (c != '\n') {
+            tok->done = E_LINECONT;
+            tok->cur = tok->inp;
+            return ERRORTOKEN;
+        }
+        tok->cont_line = 1;
+        goto again; /* Read next line */
+    }
+
+    /* Check for two-character token */
+    {
+        int c2 = tok_nextc(tok);
+        int token = Ta27Token_TwoChars(c, c2);
+#ifndef PGEN
+        if (token == NOTEQUAL && c == '<') {
+            if (PyErr_WarnExplicit(PyExc_DeprecationWarning,
+                                   "<> not supported in 3.x; use !=",
+                                   tok->filename, tok->lineno,
+                                   NULL, NULL)) {
+                return ERRORTOKEN;
+            }
+        }
+#endif
+        if (token != OP) {
+            int c3 = tok_nextc(tok);
+            int token3 = Ta27Token_ThreeChars(c, c2, c3);
+            if (token3 != OP) {
+                token = token3;
+            } else {
+                tok_backup(tok, c3);
+            }
+            *p_start = tok->start;
+            *p_end = tok->cur;
+            return token;
+        }
+        tok_backup(tok, c2);
+    }
+
+    /* Keep track of parentheses nesting level */
+    switch (c) {
+    case '(':
+    case '[':
+    case '{':
+        tok->level++;
+        break;
+    case ')':
+    case ']':
+    case '}':
+        tok->level--;
+        break;
+    }
+
+    /* Punctuation character */
+    *p_start = tok->start;
+    *p_end = tok->cur;
+    return Ta27Token_OneChar(c);
+}
+
+int
+Ta27Tokenizer_Get(struct tok_state *tok, char **p_start, char **p_end)
+{
+    int result = tok_get(tok, p_start, p_end);
+    if (tok->decoding_erred) {
+        result = ERRORTOKEN;
+        tok->done = E_DECODE;
+    }
+    return result;
+}
+
+/* This function is only called from parsetok. However, it cannot live
+   there, as it must be empty for PGEN, and we can check for PGEN only
+   in this file. */
+
+#if defined(PGEN) || !defined(Py_USING_UNICODE)
+char*
+Ta27Tokenizer_RestoreEncoding(struct tok_state* tok, int len, int* offset)
+{
+    return NULL;
+}
+#else
+#ifdef Py_USING_UNICODE
+static PyObject *
+dec_utf8(const char *enc, const char *text, size_t len) {
+    PyObject *ret = NULL;
+    PyObject *unicode_text = PyUnicode_DecodeUTF8(text, len, "replace");
+    if (unicode_text) {
+        ret = PyUnicode_AsEncodedString(unicode_text, enc, "replace");
+        Py_DECREF(unicode_text);
+    }
+    if (!ret) {
+        PyErr_Clear();
+    }
+    return ret;
+}
+char *
+Ta27Tokenizer_RestoreEncoding(struct tok_state* tok, int len, int *offset)
+{
+    char *text = NULL;
+    if (tok->encoding) {
+        /* convert source to original encondig */
+        PyObject *lineobj = dec_utf8(tok->encoding, tok->buf, len);
+        if (lineobj != NULL) {
+            int linelen = PyBytes_Size(lineobj);
+            const char *line = PyBytes_AsString(lineobj);
+            text = PyObject_MALLOC(linelen + 1);
+            if (text != NULL && line != NULL) {
+                if (linelen)
+                    strncpy(text, line, linelen);
+                text[linelen] = '\0';
+            }
+            Py_DECREF(lineobj);
+
+            /* adjust error offset */
+            if (*offset > 1) {
+                PyObject *offsetobj = dec_utf8(tok->encoding,
+                                               tok->buf, *offset-1);
+                if (offsetobj) {
+                    *offset = PyBytes_Size(offsetobj) + 1;
+                    Py_DECREF(offsetobj);
+                }
+            }
+
+        }
+    }
+    return text;
+
+}
+#endif /* defined(Py_USING_UNICODE) */
+#endif
+
+
+#ifdef Py_DEBUG
+
+void
+tok_dump(int type, char *start, char *end)
+{
+    printf("%s", _Ta27Parser_TokenNames[type]);
+    if (type == NAME || type == NUMBER || type == STRING || type == OP)
+        printf("(%.*s)", (int)(end - start), start);
+}
+
+#endif
diff --git a/ast27/Parser/tokenizer.h b/ast27/Parser/tokenizer.h
new file mode 100644
index 0000000..79df7e0
--- /dev/null
+++ b/ast27/Parser/tokenizer.h
@@ -0,0 +1,71 @@
+#ifndef Ta27_TOKENIZER_H
+#define Ta27_TOKENIZER_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "object.h"
+
+/* Tokenizer interface */
+
+#include "token.h"      /* For token types */
+
+#define MAXINDENT 100   /* Max indentation level */
+
+/* Tokenizer state */
+struct tok_state {
+    /* Input state; buf <= cur <= inp <= end */
+    /* NB an entire line is held in the buffer */
+    char *buf;          /* Input buffer, or NULL; malloc'ed if fp != NULL */
+    char *cur;          /* Next character in buffer */
+    char *inp;          /* End of data in buffer */
+    char *end;          /* End of input buffer if buf != NULL */
+    char *start;        /* Start of current token if not NULL */
+    int done;           /* E_OK normally, E_EOF at EOF, otherwise error code */
+    /* NB If done != E_OK, cur must be == inp!!! */
+    FILE *fp;           /* Rest of input; NULL if tokenizing a string */
+    int tabsize;        /* Tab spacing */
+    int indent;         /* Current indentation index */
+    int indstack[MAXINDENT];            /* Stack of indents */
+    int atbol;          /* Nonzero if at begin of new line */
+    int pendin;         /* Pending indents (if > 0) or dedents (if < 0) */
+    char *prompt, *nextprompt;          /* For interactive prompting */
+    int lineno;         /* Current line number */
+    int level;          /* () [] {} Parentheses nesting level */
+            /* Used to allow free continuations inside them */
+    /* Stuff for checking on different tab sizes */
+    const char *filename;       /* For error messages */
+    int altwarning;     /* Issue warning if alternate tabs don't match */
+    int alterror;       /* Issue error if alternate tabs don't match */
+    int alttabsize;     /* Alternate tab spacing */
+    int altindstack[MAXINDENT];         /* Stack of alternate indents */
+    /* Stuff for PEP 0263 */
+    int decoding_state;         /* -1:decoding, 0:init, 1:raw */
+    int decoding_erred;         /* whether erred in decoding  */
+    int read_coding_spec;       /* whether 'coding:...' has been read  */
+    char *encoding;
+    int cont_line;          /* whether we are in a continuation line. */
+    const char* line_start;     /* pointer to start of current line */
+#ifndef PGEN
+    PyObject *decoding_readline; /* codecs.open(...).readline */
+    PyObject *decoding_buffer;
+#endif
+    const char* enc;
+    const char* str;
+    const char* input; /* Tokenizer's newline translated copy of the string. */
+};
+
+extern struct tok_state *Ta27Tokenizer_FromString(const char *, int);
+extern struct tok_state *Ta27Tokenizer_FromUTF8(const char *, int);
+extern struct tok_state *Ta27Tokenizer_FromFile(FILE *, char *, char *);
+extern void Ta27Tokenizer_Free(struct tok_state *);
+extern int Ta27Tokenizer_Get(struct tok_state *, char **, char **);
+#if defined(PGEN) || defined(Py_USING_UNICODE)
+extern char * Ta27Tokenizer_RestoreEncoding(struct tok_state* tok,
+                                          int len, int *offset);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* !Ta27_TOKENIZER_H */
diff --git a/ast27/Python/Python-ast.c b/ast27/Python/Python-ast.c
new file mode 100644
index 0000000..ec9b340
--- /dev/null
+++ b/ast27/Python/Python-ast.c
@@ -0,0 +1,7030 @@
+/* File automatically generated by Parser/asdl_c.py. */
+
+
+/*
+   __version__ 82160.
+
+   This module must be committed separately after each AST grammar change;
+   The __version__ number is set to the revision number of the commit
+   containing the grammar change.
+*/
+
+#include "Python.h"
+#include "Python-ast.h"
+
+static PyTypeObject AST_type;
+static PyTypeObject *mod_type;
+static PyObject* ast2obj_mod(void*);
+static PyTypeObject *Module_type;
+static char *Module_fields[]={
+        "body",
+        "type_ignores",
+};
+static PyTypeObject *Interactive_type;
+static char *Interactive_fields[]={
+        "body",
+};
+static PyTypeObject *Expression_type;
+static char *Expression_fields[]={
+        "body",
+};
+static PyTypeObject *FunctionType_type;
+static char *FunctionType_fields[]={
+        "argtypes",
+        "returns",
+};
+static PyTypeObject *Suite_type;
+static char *Suite_fields[]={
+        "body",
+};
+static PyTypeObject *stmt_type;
+static char *stmt_attributes[] = {
+        "lineno",
+        "col_offset",
+};
+static PyObject* ast2obj_stmt(void*);
+static PyTypeObject *FunctionDef_type;
+static char *FunctionDef_fields[]={
+        "name",
+        "args",
+        "body",
+        "decorator_list",
+        "type_comment",
+};
+static PyTypeObject *ClassDef_type;
+static char *ClassDef_fields[]={
+        "name",
+        "bases",
+        "body",
+        "decorator_list",
+};
+static PyTypeObject *Return_type;
+static char *Return_fields[]={
+        "value",
+};
+static PyTypeObject *Delete_type;
+static char *Delete_fields[]={
+        "targets",
+};
+static PyTypeObject *Assign_type;
+static char *Assign_fields[]={
+        "targets",
+        "value",
+        "type_comment",
+};
+static PyTypeObject *AugAssign_type;
+static char *AugAssign_fields[]={
+        "target",
+        "op",
+        "value",
+};
+static PyTypeObject *Print_type;
+static char *Print_fields[]={
+        "dest",
+        "values",
+        "nl",
+};
+static PyTypeObject *For_type;
+static char *For_fields[]={
+        "target",
+        "iter",
+        "body",
+        "orelse",
+        "type_comment",
+};
+static PyTypeObject *While_type;
+static char *While_fields[]={
+        "test",
+        "body",
+        "orelse",
+};
+static PyTypeObject *If_type;
+static char *If_fields[]={
+        "test",
+        "body",
+        "orelse",
+};
+static PyTypeObject *With_type;
+static char *With_fields[]={
+        "context_expr",
+        "optional_vars",
+        "body",
+        "type_comment",
+};
+static PyTypeObject *Raise_type;
+static char *Raise_fields[]={
+        "type",
+        "inst",
+        "tback",
+};
+static PyTypeObject *TryExcept_type;
+static char *TryExcept_fields[]={
+        "body",
+        "handlers",
+        "orelse",
+};
+static PyTypeObject *TryFinally_type;
+static char *TryFinally_fields[]={
+        "body",
+        "finalbody",
+};
+static PyTypeObject *Assert_type;
+static char *Assert_fields[]={
+        "test",
+        "msg",
+};
+static PyTypeObject *Import_type;
+static char *Import_fields[]={
+        "names",
+};
+static PyTypeObject *ImportFrom_type;
+static char *ImportFrom_fields[]={
+        "module",
+        "names",
+        "level",
+};
+static PyTypeObject *Exec_type;
+static char *Exec_fields[]={
+        "body",
+        "globals",
+        "locals",
+};
+static PyTypeObject *Global_type;
+static char *Global_fields[]={
+        "names",
+};
+static PyTypeObject *Expr_type;
+static char *Expr_fields[]={
+        "value",
+};
+static PyTypeObject *Pass_type;
+static PyTypeObject *Break_type;
+static PyTypeObject *Continue_type;
+static PyTypeObject *expr_type;
+static char *expr_attributes[] = {
+        "lineno",
+        "col_offset",
+};
+static PyObject* ast2obj_expr(void*);
+static PyTypeObject *BoolOp_type;
+static char *BoolOp_fields[]={
+        "op",
+        "values",
+};
+static PyTypeObject *BinOp_type;
+static char *BinOp_fields[]={
+        "left",
+        "op",
+        "right",
+};
+static PyTypeObject *UnaryOp_type;
+static char *UnaryOp_fields[]={
+        "op",
+        "operand",
+};
+static PyTypeObject *Lambda_type;
+static char *Lambda_fields[]={
+        "args",
+        "body",
+};
+static PyTypeObject *IfExp_type;
+static char *IfExp_fields[]={
+        "test",
+        "body",
+        "orelse",
+};
+static PyTypeObject *Dict_type;
+static char *Dict_fields[]={
+        "keys",
+        "values",
+};
+static PyTypeObject *Set_type;
+static char *Set_fields[]={
+        "elts",
+};
+static PyTypeObject *ListComp_type;
+static char *ListComp_fields[]={
+        "elt",
+        "generators",
+};
+static PyTypeObject *SetComp_type;
+static char *SetComp_fields[]={
+        "elt",
+        "generators",
+};
+static PyTypeObject *DictComp_type;
+static char *DictComp_fields[]={
+        "key",
+        "value",
+        "generators",
+};
+static PyTypeObject *GeneratorExp_type;
+static char *GeneratorExp_fields[]={
+        "elt",
+        "generators",
+};
+static PyTypeObject *Yield_type;
+static char *Yield_fields[]={
+        "value",
+};
+static PyTypeObject *Compare_type;
+static char *Compare_fields[]={
+        "left",
+        "ops",
+        "comparators",
+};
+static PyTypeObject *Call_type;
+static char *Call_fields[]={
+        "func",
+        "args",
+        "keywords",
+        "starargs",
+        "kwargs",
+};
+static PyTypeObject *Repr_type;
+static char *Repr_fields[]={
+        "value",
+};
+static PyTypeObject *Num_type;
+static char *Num_fields[]={
+        "n",
+};
+static PyTypeObject *Str_type;
+static char *Str_fields[]={
+        "s",
+};
+static PyTypeObject *Attribute_type;
+static char *Attribute_fields[]={
+        "value",
+        "attr",
+        "ctx",
+};
+static PyTypeObject *Subscript_type;
+static char *Subscript_fields[]={
+        "value",
+        "slice",
+        "ctx",
+};
+static PyTypeObject *Name_type;
+static char *Name_fields[]={
+        "id",
+        "ctx",
+};
+static PyTypeObject *List_type;
+static char *List_fields[]={
+        "elts",
+        "ctx",
+};
+static PyTypeObject *Tuple_type;
+static char *Tuple_fields[]={
+        "elts",
+        "ctx",
+};
+static PyTypeObject *expr_context_type;
+static PyObject *Load_singleton, *Store_singleton, *Del_singleton, *AugLoad_singleton,
+*AugStore_singleton, *Param_singleton;
+static PyObject* ast2obj_expr_context(expr_context_ty);
+static PyTypeObject *Load_type;
+static PyTypeObject *Store_type;
+static PyTypeObject *Del_type;
+static PyTypeObject *AugLoad_type;
+static PyTypeObject *AugStore_type;
+static PyTypeObject *Param_type;
+static PyTypeObject *slice_type;
+static PyObject* ast2obj_slice(void*);
+static PyTypeObject *Ellipsis_type;
+static PyTypeObject *Slice_type;
+static char *Slice_fields[]={
+        "lower",
+        "upper",
+        "step",
+};
+static PyTypeObject *ExtSlice_type;
+static char *ExtSlice_fields[]={
+        "dims",
+};
+static PyTypeObject *Index_type;
+static char *Index_fields[]={
+        "value",
+};
+static PyTypeObject *boolop_type;
+static PyObject *And_singleton, *Or_singleton;
+static PyObject* ast2obj_boolop(boolop_ty);
+static PyTypeObject *And_type;
+static PyTypeObject *Or_type;
+static PyTypeObject *operator_type;
+static PyObject *Add_singleton, *Sub_singleton, *Mult_singleton, *Div_singleton, *Mod_singleton,
+*Pow_singleton, *LShift_singleton, *RShift_singleton, *BitOr_singleton, *BitXor_singleton,
+*BitAnd_singleton, *FloorDiv_singleton;
+static PyObject* ast2obj_operator(operator_ty);
+static PyTypeObject *Add_type;
+static PyTypeObject *Sub_type;
+static PyTypeObject *Mult_type;
+static PyTypeObject *Div_type;
+static PyTypeObject *Mod_type;
+static PyTypeObject *Pow_type;
+static PyTypeObject *LShift_type;
+static PyTypeObject *RShift_type;
+static PyTypeObject *BitOr_type;
+static PyTypeObject *BitXor_type;
+static PyTypeObject *BitAnd_type;
+static PyTypeObject *FloorDiv_type;
+static PyTypeObject *unaryop_type;
+static PyObject *Invert_singleton, *Not_singleton, *UAdd_singleton, *USub_singleton;
+static PyObject* ast2obj_unaryop(unaryop_ty);
+static PyTypeObject *Invert_type;
+static PyTypeObject *Not_type;
+static PyTypeObject *UAdd_type;
+static PyTypeObject *USub_type;
+static PyTypeObject *cmpop_type;
+static PyObject *Eq_singleton, *NotEq_singleton, *Lt_singleton, *LtE_singleton, *Gt_singleton,
+*GtE_singleton, *Is_singleton, *IsNot_singleton, *In_singleton, *NotIn_singleton;
+static PyObject* ast2obj_cmpop(cmpop_ty);
+static PyTypeObject *Eq_type;
+static PyTypeObject *NotEq_type;
+static PyTypeObject *Lt_type;
+static PyTypeObject *LtE_type;
+static PyTypeObject *Gt_type;
+static PyTypeObject *GtE_type;
+static PyTypeObject *Is_type;
+static PyTypeObject *IsNot_type;
+static PyTypeObject *In_type;
+static PyTypeObject *NotIn_type;
+static PyTypeObject *comprehension_type;
+static PyObject* ast2obj_comprehension(void*);
+static char *comprehension_fields[]={
+        "target",
+        "iter",
+        "ifs",
+};
+static PyTypeObject *excepthandler_type;
+static char *excepthandler_attributes[] = {
+        "lineno",
+        "col_offset",
+};
+static PyObject* ast2obj_excepthandler(void*);
+static PyTypeObject *ExceptHandler_type;
+static char *ExceptHandler_fields[]={
+        "type",
+        "name",
+        "body",
+};
+static PyTypeObject *arguments_type;
+static PyObject* ast2obj_arguments(void*);
+static char *arguments_fields[]={
+        "args",
+        "vararg",
+        "kwarg",
+        "defaults",
+        "type_comments",
+};
+static PyTypeObject *keyword_type;
+static PyObject* ast2obj_keyword(void*);
+static char *keyword_fields[]={
+        "arg",
+        "value",
+};
+static PyTypeObject *alias_type;
+static PyObject* ast2obj_alias(void*);
+static char *alias_fields[]={
+        "name",
+        "asname",
+};
+static PyTypeObject *type_ignore_type;
+static PyObject* ast2obj_type_ignore(void*);
+static PyTypeObject *TypeIgnore_type;
+static char *TypeIgnore_fields[]={
+        "lineno",
+};
+
+
+static int
+ast_type_init(PyObject *self, PyObject *args, PyObject *kw)
+{
+    Py_ssize_t i, numfields = 0;
+    int res = -1;
+    PyObject *key, *value, *fields;
+    fields = PyObject_GetAttrString((PyObject*)Py_TYPE(self), "_fields");
+    if (!fields)
+        PyErr_Clear();
+    if (fields) {
+        numfields = PySequence_Size(fields);
+        if (numfields == -1)
+            goto cleanup;
+    }
+    res = 0; /* if no error occurs, this stays 0 to the end */
+    if (PyTuple_GET_SIZE(args) > 0) {
+        if (numfields != PyTuple_GET_SIZE(args)) {
+            PyErr_Format(PyExc_TypeError, "%.400s constructor takes %s"
+                         "%zd positional argument%s",
+                         Py_TYPE(self)->tp_name,
+                         numfields == 0 ? "" : "either 0 or ",
+                         numfields, numfields == 1 ? "" : "s");
+            res = -1;
+            goto cleanup;
+        }
+        for (i = 0; i < PyTuple_GET_SIZE(args); i++) {
+            /* cannot be reached when fields is NULL */
+            PyObject *name = PySequence_GetItem(fields, i);
+            if (!name) {
+                res = -1;
+                goto cleanup;
+            }
+            res = PyObject_SetAttr(self, name, PyTuple_GET_ITEM(args, i));
+            Py_DECREF(name);
+            if (res < 0)
+                goto cleanup;
+        }
+    }
+    if (kw) {
+        i = 0;  /* needed by PyDict_Next */
+        while (PyDict_Next(kw, &i, &key, &value)) {
+            res = PyObject_SetAttr(self, key, value);
+            if (res < 0)
+                goto cleanup;
+        }
+    }
+  cleanup:
+    Py_XDECREF(fields);
+    return res;
+}
+
+/* Pickling support */
+static PyObject *
+ast_type_reduce(PyObject *self, PyObject *unused)
+{
+    PyObject *res;
+    PyObject *dict = PyObject_GetAttrString(self, "__dict__");
+    if (dict == NULL) {
+        if (PyErr_ExceptionMatches(PyExc_AttributeError))
+            PyErr_Clear();
+        else
+            return NULL;
+    }
+    if (dict) {
+        res = Py_BuildValue("O()O", Py_TYPE(self), dict);
+        Py_DECREF(dict);
+        return res;
+    }
+    return Py_BuildValue("O()", Py_TYPE(self));
+}
+
+static PyMethodDef ast_type_methods[] = {
+    {"__reduce__", ast_type_reduce, METH_NOARGS, NULL},
+    {NULL}
+};
+
+static PyTypeObject AST_type = {
+    PyVarObject_HEAD_INIT(&PyType_Type, 0)
+    "_ast27.AST",
+    sizeof(PyObject),
+    0,
+    0,                       /* tp_dealloc */
+    0,                       /* tp_print */
+    0,                       /* tp_getattr */
+    0,                       /* tp_setattr */
+    0,                       /* tp_compare */
+    0,                       /* tp_repr */
+    0,                       /* tp_as_number */
+    0,                       /* tp_as_sequence */
+    0,                       /* tp_as_mapping */
+    0,                       /* tp_hash */
+    0,                       /* tp_call */
+    0,                       /* tp_str */
+    PyObject_GenericGetAttr, /* tp_getattro */
+    PyObject_GenericSetAttr, /* tp_setattro */
+    0,                       /* tp_as_buffer */
+    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+    0,                       /* tp_doc */
+    0,                       /* tp_traverse */
+    0,                       /* tp_clear */
+    0,                       /* tp_richcompare */
+    0,                       /* tp_weaklistoffset */
+    0,                       /* tp_iter */
+    0,                       /* tp_iternext */
+    ast_type_methods,        /* tp_methods */
+    0,                       /* tp_members */
+    0,                       /* tp_getset */
+    0,                       /* tp_base */
+    0,                       /* tp_dict */
+    0,                       /* tp_descr_get */
+    0,                       /* tp_descr_set */
+    0,                       /* tp_dictoffset */
+    (initproc)ast_type_init, /* tp_init */
+    PyType_GenericAlloc,     /* tp_alloc */
+    PyType_GenericNew,       /* tp_new */
+    PyObject_Del,            /* tp_free */
+};
+
+
+static PyTypeObject* make_type(char *type, PyTypeObject* base, char**fields, int num_fields)
+{
+    PyObject *fnames, *result;
+    int i;
+    fnames = PyTuple_New(num_fields);
+    if (!fnames) return NULL;
+    for (i = 0; i < num_fields; i++) {
+        PyObject *field = PyUnicode_FromString(fields[i]);
+        if (!field) {
+            Py_DECREF(fnames);
+            return NULL;
+        }
+        PyTuple_SET_ITEM(fnames, i, field);
+    }
+    result = PyObject_CallFunction((PyObject*)&PyType_Type, "s(O){sOss}",
+                    type, base, "_fields", fnames, "__module__", "_ast27");
+    Py_DECREF(fnames);
+    return (PyTypeObject*)result;
+}
+
+static int add_attributes(PyTypeObject* type, char**attrs, int num_fields)
+{
+    int i, result;
+    PyObject *s, *l = PyTuple_New(num_fields);
+    if (!l)
+        return 0;
+    for (i = 0; i < num_fields; i++) {
+        s = PyUnicode_FromString(attrs[i]);
+        if (!s) {
+            Py_DECREF(l);
+            return 0;
+        }
+        PyTuple_SET_ITEM(l, i, s);
+    }
+    result = PyObject_SetAttrString((PyObject*)type, "_attributes", l) >= 0;
+    Py_DECREF(l);
+    return result;
+}
+
+/* Conversion AST -> Python */
+
+static PyObject* ast2obj_list(asdl_seq *seq, PyObject* (*func)(void*))
+{
+    int i, n = asdl_seq_LEN(seq);
+    PyObject *result = PyList_New(n);
+    PyObject *value;
+    if (!result)
+        return NULL;
+    for (i = 0; i < n; i++) {
+        value = func(asdl_seq_GET(seq, i));
+        if (!value) {
+            Py_DECREF(result);
+            return NULL;
+        }
+        PyList_SET_ITEM(result, i, value);
+    }
+    return result;
+}
+
+static PyObject* ast2obj_object(void *o)
+{
+    if (!o)
+        o = Py_None;
+    Py_INCREF((PyObject*)o);
+    return (PyObject*)o;
+}
+#define ast2obj_identifier ast2obj_object
+#define ast2obj_string ast2obj_object
+static PyObject* ast2obj_bool(bool b)
+{
+    return PyBool_FromLong(b);
+}
+
+static PyObject* ast2obj_int(long b)
+{
+    return PyLong_FromLong(b);
+}
+
+/* Conversion Python -> AST */
+
+static int obj2ast_object(PyObject* obj, PyObject** out, PyArena* arena)
+{
+    if (obj == Py_None)
+        obj = NULL;
+    if (obj)
+        PyArena_AddPyObject(arena, obj);
+    Py_XINCREF(obj);
+    *out = obj;
+    return 0;
+}
+
+static int obj2ast_identifier(PyObject* obj, PyObject** out, PyArena* arena)
+{
+    if (!PyUnicode_CheckExact(obj) && obj != Py_None) {
+        PyErr_Format(PyExc_TypeError,
+                    "AST identifier must be of type str");
+        return 1;
+    }
+    return obj2ast_object(obj, out, arena);
+}
+
+static int obj2ast_string(PyObject* obj, PyObject** out, PyArena* arena)
+{
+    if (!PyUnicode_CheckExact(obj) && !PyUnicode_CheckExact(obj)) {
+        PyErr_SetString(PyExc_TypeError,
+                       "AST string must be of type str or unicode");
+        return 1;
+    }
+    return obj2ast_object(obj, out, arena);
+}
+
+static int obj2ast_int(PyObject* obj, int* out, PyArena* arena)
+{
+    int i;
+    if (!PyLong_Check(obj) && !PyLong_Check(obj)) {
+        PyObject *s = PyObject_Repr(obj);
+        if (s == NULL) return 1;
+        PyErr_Format(PyExc_ValueError, "invalid integer value: %.400s",
+                     _PyUnicode_AsString(s));
+        Py_DECREF(s);
+        return 1;
+    }
+
+    i = (int)PyLong_AsLong(obj);
+    if (i == -1 && PyErr_Occurred())
+        return 1;
+    *out = i;
+    return 0;
+}
+
+static int obj2ast_bool(PyObject* obj, bool* out, PyArena* arena)
+{
+    if (!PyBool_Check(obj)) {
+        PyObject *s = PyObject_Repr(obj);
+        if (s == NULL) return 1;
+        PyErr_Format(PyExc_ValueError, "invalid boolean value: %.400s",
+                     _PyUnicode_AsString(s));
+        Py_DECREF(s);
+        return 1;
+    }
+
+    *out = (obj == Py_True);
+    return 0;
+}
+
+static int add_ast_fields(void)
+{
+    PyObject *empty_tuple, *d;
+    if (PyType_Ready(&AST_type) < 0)
+        return -1;
+    d = AST_type.tp_dict;
+    empty_tuple = PyTuple_New(0);
+    if (!empty_tuple ||
+        PyDict_SetItemString(d, "_fields", empty_tuple) < 0 ||
+        PyDict_SetItemString(d, "_attributes", empty_tuple) < 0) {
+        Py_XDECREF(empty_tuple);
+        return -1;
+    }
+    Py_DECREF(empty_tuple);
+    return 0;
+}
+
+
+static int init_types(void)
+{
+        static int initialized;
+        if (initialized) return 1;
+        if (add_ast_fields() < 0) return 0;
+        mod_type = make_type("mod", &AST_type, NULL, 0);
+        if (!mod_type) return 0;
+        if (!add_attributes(mod_type, NULL, 0)) return 0;
+        Module_type = make_type("Module", mod_type, Module_fields, 2);
+        if (!Module_type) return 0;
+        Interactive_type = make_type("Interactive", mod_type, Interactive_fields, 1);
+        if (!Interactive_type) return 0;
+        Expression_type = make_type("Expression", mod_type, Expression_fields, 1);
+        if (!Expression_type) return 0;
+        FunctionType_type = make_type("FunctionType", mod_type, FunctionType_fields, 2);
+        if (!FunctionType_type) return 0;
+        Suite_type = make_type("Suite", mod_type, Suite_fields, 1);
+        if (!Suite_type) return 0;
+        stmt_type = make_type("stmt", &AST_type, NULL, 0);
+        if (!stmt_type) return 0;
+        if (!add_attributes(stmt_type, stmt_attributes, 2)) return 0;
+        FunctionDef_type = make_type("FunctionDef", stmt_type, FunctionDef_fields, 5);
+        if (!FunctionDef_type) return 0;
+        ClassDef_type = make_type("ClassDef", stmt_type, ClassDef_fields, 4);
+        if (!ClassDef_type) return 0;
+        Return_type = make_type("Return", stmt_type, Return_fields, 1);
+        if (!Return_type) return 0;
+        Delete_type = make_type("Delete", stmt_type, Delete_fields, 1);
+        if (!Delete_type) return 0;
+        Assign_type = make_type("Assign", stmt_type, Assign_fields, 3);
+        if (!Assign_type) return 0;
+        AugAssign_type = make_type("AugAssign", stmt_type, AugAssign_fields, 3);
+        if (!AugAssign_type) return 0;
+        Print_type = make_type("Print", stmt_type, Print_fields, 3);
+        if (!Print_type) return 0;
+        For_type = make_type("For", stmt_type, For_fields, 5);
+        if (!For_type) return 0;
+        While_type = make_type("While", stmt_type, While_fields, 3);
+        if (!While_type) return 0;
+        If_type = make_type("If", stmt_type, If_fields, 3);
+        if (!If_type) return 0;
+        With_type = make_type("With", stmt_type, With_fields, 4);
+        if (!With_type) return 0;
+        Raise_type = make_type("Raise", stmt_type, Raise_fields, 3);
+        if (!Raise_type) return 0;
+        TryExcept_type = make_type("TryExcept", stmt_type, TryExcept_fields, 3);
+        if (!TryExcept_type) return 0;
+        TryFinally_type = make_type("TryFinally", stmt_type, TryFinally_fields, 2);
+        if (!TryFinally_type) return 0;
+        Assert_type = make_type("Assert", stmt_type, Assert_fields, 2);
+        if (!Assert_type) return 0;
+        Import_type = make_type("Import", stmt_type, Import_fields, 1);
+        if (!Import_type) return 0;
+        ImportFrom_type = make_type("ImportFrom", stmt_type, ImportFrom_fields, 3);
+        if (!ImportFrom_type) return 0;
+        Exec_type = make_type("Exec", stmt_type, Exec_fields, 3);
+        if (!Exec_type) return 0;
+        Global_type = make_type("Global", stmt_type, Global_fields, 1);
+        if (!Global_type) return 0;
+        Expr_type = make_type("Expr", stmt_type, Expr_fields, 1);
+        if (!Expr_type) return 0;
+        Pass_type = make_type("Pass", stmt_type, NULL, 0);
+        if (!Pass_type) return 0;
+        Break_type = make_type("Break", stmt_type, NULL, 0);
+        if (!Break_type) return 0;
+        Continue_type = make_type("Continue", stmt_type, NULL, 0);
+        if (!Continue_type) return 0;
+        expr_type = make_type("expr", &AST_type, NULL, 0);
+        if (!expr_type) return 0;
+        if (!add_attributes(expr_type, expr_attributes, 2)) return 0;
+        BoolOp_type = make_type("BoolOp", expr_type, BoolOp_fields, 2);
+        if (!BoolOp_type) return 0;
+        BinOp_type = make_type("BinOp", expr_type, BinOp_fields, 3);
+        if (!BinOp_type) return 0;
+        UnaryOp_type = make_type("UnaryOp", expr_type, UnaryOp_fields, 2);
+        if (!UnaryOp_type) return 0;
+        Lambda_type = make_type("Lambda", expr_type, Lambda_fields, 2);
+        if (!Lambda_type) return 0;
+        IfExp_type = make_type("IfExp", expr_type, IfExp_fields, 3);
+        if (!IfExp_type) return 0;
+        Dict_type = make_type("Dict", expr_type, Dict_fields, 2);
+        if (!Dict_type) return 0;
+        Set_type = make_type("Set", expr_type, Set_fields, 1);
+        if (!Set_type) return 0;
+        ListComp_type = make_type("ListComp", expr_type, ListComp_fields, 2);
+        if (!ListComp_type) return 0;
+        SetComp_type = make_type("SetComp", expr_type, SetComp_fields, 2);
+        if (!SetComp_type) return 0;
+        DictComp_type = make_type("DictComp", expr_type, DictComp_fields, 3);
+        if (!DictComp_type) return 0;
+        GeneratorExp_type = make_type("GeneratorExp", expr_type, GeneratorExp_fields, 2);
+        if (!GeneratorExp_type) return 0;
+        Yield_type = make_type("Yield", expr_type, Yield_fields, 1);
+        if (!Yield_type) return 0;
+        Compare_type = make_type("Compare", expr_type, Compare_fields, 3);
+        if (!Compare_type) return 0;
+        Call_type = make_type("Call", expr_type, Call_fields, 5);
+        if (!Call_type) return 0;
+        Repr_type = make_type("Repr", expr_type, Repr_fields, 1);
+        if (!Repr_type) return 0;
+        Num_type = make_type("Num", expr_type, Num_fields, 1);
+        if (!Num_type) return 0;
+        Str_type = make_type("Str", expr_type, Str_fields, 1);
+        if (!Str_type) return 0;
+        Attribute_type = make_type("Attribute", expr_type, Attribute_fields, 3);
+        if (!Attribute_type) return 0;
+        Subscript_type = make_type("Subscript", expr_type, Subscript_fields, 3);
+        if (!Subscript_type) return 0;
+        Name_type = make_type("Name", expr_type, Name_fields, 2);
+        if (!Name_type) return 0;
+        List_type = make_type("List", expr_type, List_fields, 2);
+        if (!List_type) return 0;
+        Tuple_type = make_type("Tuple", expr_type, Tuple_fields, 2);
+        if (!Tuple_type) return 0;
+        expr_context_type = make_type("expr_context", &AST_type, NULL, 0);
+        if (!expr_context_type) return 0;
+        if (!add_attributes(expr_context_type, NULL, 0)) return 0;
+        Load_type = make_type("Load", expr_context_type, NULL, 0);
+        if (!Load_type) return 0;
+        Load_singleton = PyType_GenericNew(Load_type, NULL, NULL);
+        if (!Load_singleton) return 0;
+        Store_type = make_type("Store", expr_context_type, NULL, 0);
+        if (!Store_type) return 0;
+        Store_singleton = PyType_GenericNew(Store_type, NULL, NULL);
+        if (!Store_singleton) return 0;
+        Del_type = make_type("Del", expr_context_type, NULL, 0);
+        if (!Del_type) return 0;
+        Del_singleton = PyType_GenericNew(Del_type, NULL, NULL);
+        if (!Del_singleton) return 0;
+        AugLoad_type = make_type("AugLoad", expr_context_type, NULL, 0);
+        if (!AugLoad_type) return 0;
+        AugLoad_singleton = PyType_GenericNew(AugLoad_type, NULL, NULL);
+        if (!AugLoad_singleton) return 0;
+        AugStore_type = make_type("AugStore", expr_context_type, NULL, 0);
+        if (!AugStore_type) return 0;
+        AugStore_singleton = PyType_GenericNew(AugStore_type, NULL, NULL);
+        if (!AugStore_singleton) return 0;
+        Param_type = make_type("Param", expr_context_type, NULL, 0);
+        if (!Param_type) return 0;
+        Param_singleton = PyType_GenericNew(Param_type, NULL, NULL);
+        if (!Param_singleton) return 0;
+        slice_type = make_type("slice", &AST_type, NULL, 0);
+        if (!slice_type) return 0;
+        if (!add_attributes(slice_type, NULL, 0)) return 0;
+        Ellipsis_type = make_type("Ellipsis", slice_type, NULL, 0);
+        if (!Ellipsis_type) return 0;
+        Slice_type = make_type("Slice", slice_type, Slice_fields, 3);
+        if (!Slice_type) return 0;
+        ExtSlice_type = make_type("ExtSlice", slice_type, ExtSlice_fields, 1);
+        if (!ExtSlice_type) return 0;
+        Index_type = make_type("Index", slice_type, Index_fields, 1);
+        if (!Index_type) return 0;
+        boolop_type = make_type("boolop", &AST_type, NULL, 0);
+        if (!boolop_type) return 0;
+        if (!add_attributes(boolop_type, NULL, 0)) return 0;
+        And_type = make_type("And", boolop_type, NULL, 0);
+        if (!And_type) return 0;
+        And_singleton = PyType_GenericNew(And_type, NULL, NULL);
+        if (!And_singleton) return 0;
+        Or_type = make_type("Or", boolop_type, NULL, 0);
+        if (!Or_type) return 0;
+        Or_singleton = PyType_GenericNew(Or_type, NULL, NULL);
+        if (!Or_singleton) return 0;
+        operator_type = make_type("operator", &AST_type, NULL, 0);
+        if (!operator_type) return 0;
+        if (!add_attributes(operator_type, NULL, 0)) return 0;
+        Add_type = make_type("Add", operator_type, NULL, 0);
+        if (!Add_type) return 0;
+        Add_singleton = PyType_GenericNew(Add_type, NULL, NULL);
+        if (!Add_singleton) return 0;
+        Sub_type = make_type("Sub", operator_type, NULL, 0);
+        if (!Sub_type) return 0;
+        Sub_singleton = PyType_GenericNew(Sub_type, NULL, NULL);
+        if (!Sub_singleton) return 0;
+        Mult_type = make_type("Mult", operator_type, NULL, 0);
+        if (!Mult_type) return 0;
+        Mult_singleton = PyType_GenericNew(Mult_type, NULL, NULL);
+        if (!Mult_singleton) return 0;
+        Div_type = make_type("Div", operator_type, NULL, 0);
+        if (!Div_type) return 0;
+        Div_singleton = PyType_GenericNew(Div_type, NULL, NULL);
+        if (!Div_singleton) return 0;
+        Mod_type = make_type("Mod", operator_type, NULL, 0);
+        if (!Mod_type) return 0;
+        Mod_singleton = PyType_GenericNew(Mod_type, NULL, NULL);
+        if (!Mod_singleton) return 0;
+        Pow_type = make_type("Pow", operator_type, NULL, 0);
+        if (!Pow_type) return 0;
+        Pow_singleton = PyType_GenericNew(Pow_type, NULL, NULL);
+        if (!Pow_singleton) return 0;
+        LShift_type = make_type("LShift", operator_type, NULL, 0);
+        if (!LShift_type) return 0;
+        LShift_singleton = PyType_GenericNew(LShift_type, NULL, NULL);
+        if (!LShift_singleton) return 0;
+        RShift_type = make_type("RShift", operator_type, NULL, 0);
+        if (!RShift_type) return 0;
+        RShift_singleton = PyType_GenericNew(RShift_type, NULL, NULL);
+        if (!RShift_singleton) return 0;
+        BitOr_type = make_type("BitOr", operator_type, NULL, 0);
+        if (!BitOr_type) return 0;
+        BitOr_singleton = PyType_GenericNew(BitOr_type, NULL, NULL);
+        if (!BitOr_singleton) return 0;
+        BitXor_type = make_type("BitXor", operator_type, NULL, 0);
+        if (!BitXor_type) return 0;
+        BitXor_singleton = PyType_GenericNew(BitXor_type, NULL, NULL);
+        if (!BitXor_singleton) return 0;
+        BitAnd_type = make_type("BitAnd", operator_type, NULL, 0);
+        if (!BitAnd_type) return 0;
+        BitAnd_singleton = PyType_GenericNew(BitAnd_type, NULL, NULL);
+        if (!BitAnd_singleton) return 0;
+        FloorDiv_type = make_type("FloorDiv", operator_type, NULL, 0);
+        if (!FloorDiv_type) return 0;
+        FloorDiv_singleton = PyType_GenericNew(FloorDiv_type, NULL, NULL);
+        if (!FloorDiv_singleton) return 0;
+        unaryop_type = make_type("unaryop", &AST_type, NULL, 0);
+        if (!unaryop_type) return 0;
+        if (!add_attributes(unaryop_type, NULL, 0)) return 0;
+        Invert_type = make_type("Invert", unaryop_type, NULL, 0);
+        if (!Invert_type) return 0;
+        Invert_singleton = PyType_GenericNew(Invert_type, NULL, NULL);
+        if (!Invert_singleton) return 0;
+        Not_type = make_type("Not", unaryop_type, NULL, 0);
+        if (!Not_type) return 0;
+        Not_singleton = PyType_GenericNew(Not_type, NULL, NULL);
+        if (!Not_singleton) return 0;
+        UAdd_type = make_type("UAdd", unaryop_type, NULL, 0);
+        if (!UAdd_type) return 0;
+        UAdd_singleton = PyType_GenericNew(UAdd_type, NULL, NULL);
+        if (!UAdd_singleton) return 0;
+        USub_type = make_type("USub", unaryop_type, NULL, 0);
+        if (!USub_type) return 0;
+        USub_singleton = PyType_GenericNew(USub_type, NULL, NULL);
+        if (!USub_singleton) return 0;
+        cmpop_type = make_type("cmpop", &AST_type, NULL, 0);
+        if (!cmpop_type) return 0;
+        if (!add_attributes(cmpop_type, NULL, 0)) return 0;
+        Eq_type = make_type("Eq", cmpop_type, NULL, 0);
+        if (!Eq_type) return 0;
+        Eq_singleton = PyType_GenericNew(Eq_type, NULL, NULL);
+        if (!Eq_singleton) return 0;
+        NotEq_type = make_type("NotEq", cmpop_type, NULL, 0);
+        if (!NotEq_type) return 0;
+        NotEq_singleton = PyType_GenericNew(NotEq_type, NULL, NULL);
+        if (!NotEq_singleton) return 0;
+        Lt_type = make_type("Lt", cmpop_type, NULL, 0);
+        if (!Lt_type) return 0;
+        Lt_singleton = PyType_GenericNew(Lt_type, NULL, NULL);
+        if (!Lt_singleton) return 0;
+        LtE_type = make_type("LtE", cmpop_type, NULL, 0);
+        if (!LtE_type) return 0;
+        LtE_singleton = PyType_GenericNew(LtE_type, NULL, NULL);
+        if (!LtE_singleton) return 0;
+        Gt_type = make_type("Gt", cmpop_type, NULL, 0);
+        if (!Gt_type) return 0;
+        Gt_singleton = PyType_GenericNew(Gt_type, NULL, NULL);
+        if (!Gt_singleton) return 0;
+        GtE_type = make_type("GtE", cmpop_type, NULL, 0);
+        if (!GtE_type) return 0;
+        GtE_singleton = PyType_GenericNew(GtE_type, NULL, NULL);
+        if (!GtE_singleton) return 0;
+        Is_type = make_type("Is", cmpop_type, NULL, 0);
+        if (!Is_type) return 0;
+        Is_singleton = PyType_GenericNew(Is_type, NULL, NULL);
+        if (!Is_singleton) return 0;
+        IsNot_type = make_type("IsNot", cmpop_type, NULL, 0);
+        if (!IsNot_type) return 0;
+        IsNot_singleton = PyType_GenericNew(IsNot_type, NULL, NULL);
+        if (!IsNot_singleton) return 0;
+        In_type = make_type("In", cmpop_type, NULL, 0);
+        if (!In_type) return 0;
+        In_singleton = PyType_GenericNew(In_type, NULL, NULL);
+        if (!In_singleton) return 0;
+        NotIn_type = make_type("NotIn", cmpop_type, NULL, 0);
+        if (!NotIn_type) return 0;
+        NotIn_singleton = PyType_GenericNew(NotIn_type, NULL, NULL);
+        if (!NotIn_singleton) return 0;
+        comprehension_type = make_type("comprehension", &AST_type, comprehension_fields, 3);
+        if (!comprehension_type) return 0;
+        excepthandler_type = make_type("excepthandler", &AST_type, NULL, 0);
+        if (!excepthandler_type) return 0;
+        if (!add_attributes(excepthandler_type, excepthandler_attributes, 2)) return 0;
+        ExceptHandler_type = make_type("ExceptHandler", excepthandler_type, ExceptHandler_fields,
+                                       3);
+        if (!ExceptHandler_type) return 0;
+        arguments_type = make_type("arguments", &AST_type, arguments_fields, 5);
+        if (!arguments_type) return 0;
+        keyword_type = make_type("keyword", &AST_type, keyword_fields, 2);
+        if (!keyword_type) return 0;
+        alias_type = make_type("alias", &AST_type, alias_fields, 2);
+        if (!alias_type) return 0;
+        type_ignore_type = make_type("type_ignore", &AST_type, NULL, 0);
+        if (!type_ignore_type) return 0;
+        if (!add_attributes(type_ignore_type, NULL, 0)) return 0;
+        TypeIgnore_type = make_type("TypeIgnore", type_ignore_type, TypeIgnore_fields, 1);
+        if (!TypeIgnore_type) return 0;
+        initialized = 1;
+        return 1;
+}
+
+static int obj2ast_mod(PyObject* obj, mod_ty* out, PyArena* arena);
+static int obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena);
+static int obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena);
+static int obj2ast_expr_context(PyObject* obj, expr_context_ty* out, PyArena* arena);
+static int obj2ast_slice(PyObject* obj, slice_ty* out, PyArena* arena);
+static int obj2ast_boolop(PyObject* obj, boolop_ty* out, PyArena* arena);
+static int obj2ast_operator(PyObject* obj, operator_ty* out, PyArena* arena);
+static int obj2ast_unaryop(PyObject* obj, unaryop_ty* out, PyArena* arena);
+static int obj2ast_cmpop(PyObject* obj, cmpop_ty* out, PyArena* arena);
+static int obj2ast_comprehension(PyObject* obj, comprehension_ty* out, PyArena* arena);
+static int obj2ast_excepthandler(PyObject* obj, excepthandler_ty* out, PyArena* arena);
+static int obj2ast_arguments(PyObject* obj, arguments_ty* out, PyArena* arena);
+static int obj2ast_keyword(PyObject* obj, keyword_ty* out, PyArena* arena);
+static int obj2ast_alias(PyObject* obj, alias_ty* out, PyArena* arena);
+static int obj2ast_type_ignore(PyObject* obj, type_ignore_ty* out, PyArena* arena);
+
+mod_ty
+Module(asdl_seq * body, asdl_seq * type_ignores, PyArena *arena)
+{
+        mod_ty p;
+        p = (mod_ty)PyArena_Malloc(arena, sizeof(*p));
+        if (!p)
+                return NULL;
+        p->kind = Module_kind;
+        p->v.Module.body = body;
+        p->v.Module.type_ignores = type_ignores;
+        return p;
+}
+
+mod_ty
+Interactive(asdl_seq * body, PyArena *arena)
+{
+        mod_ty p;
+        p = (mod_ty)PyArena_Malloc(arena, sizeof(*p));
+        if (!p)
+                return NULL;
+        p->kind = Interactive_kind;
+        p->v.Interactive.body = body;
+        return p;
+}
+
+mod_ty
+Expression(expr_ty body, PyArena *arena)
+{
+        mod_ty p;
+        if (!body) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field body is required for Expression");
+                return NULL;
+        }
+        p = (mod_ty)PyArena_Malloc(arena, sizeof(*p));
+        if (!p)
+                return NULL;
+        p->kind = Expression_kind;
+        p->v.Expression.body = body;
+        return p;
+}
+
+mod_ty
+FunctionType(asdl_seq * argtypes, expr_ty returns, PyArena *arena)
+{
+        mod_ty p;
+        if (!returns) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field returns is required for FunctionType");
+                return NULL;
+        }
+        p = (mod_ty)PyArena_Malloc(arena, sizeof(*p));
+        if (!p)
+                return NULL;
+        p->kind = FunctionType_kind;
+        p->v.FunctionType.argtypes = argtypes;
+        p->v.FunctionType.returns = returns;
+        return p;
+}
+
+mod_ty
+Suite(asdl_seq * body, PyArena *arena)
+{
+        mod_ty p;
+        p = (mod_ty)PyArena_Malloc(arena, sizeof(*p));
+        if (!p)
+                return NULL;
+        p->kind = Suite_kind;
+        p->v.Suite.body = body;
+        return p;
+}
+
+stmt_ty
+FunctionDef(identifier name, arguments_ty args, asdl_seq * body, asdl_seq * decorator_list, string
+            type_comment, int lineno, int col_offset, PyArena *arena)
+{
+        stmt_ty p;
+        if (!name) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field name is required for FunctionDef");
+                return NULL;
+        }
+        if (!args) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field args is required for FunctionDef");
+                return NULL;
+        }
+        p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p));
+        if (!p)
+                return NULL;
+        p->kind = FunctionDef_kind;
+        p->v.FunctionDef.name = name;
+        p->v.FunctionDef.args = args;
+        p->v.FunctionDef.body = body;
+        p->v.FunctionDef.decorator_list = decorator_list;
+        p->v.FunctionDef.type_comment = type_comment;
+        p->lineno = lineno;
+        p->col_offset = col_offset;
+        return p;
+}
+
+stmt_ty
+ClassDef(identifier name, asdl_seq * bases, asdl_seq * body, asdl_seq * decorator_list, int lineno,
+         int col_offset, PyArena *arena)
+{
+        stmt_ty p;
+        if (!name) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field name is required for ClassDef");
+                return NULL;
+        }
+        p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p));
+        if (!p)
+                return NULL;
+        p->kind = ClassDef_kind;
+        p->v.ClassDef.name = name;
+        p->v.ClassDef.bases = bases;
+        p->v.ClassDef.body = body;
+        p->v.ClassDef.decorator_list = decorator_list;
+        p->lineno = lineno;
+        p->col_offset = col_offset;
+        return p;
+}
+
+stmt_ty
+Return(expr_ty value, int lineno, int col_offset, PyArena *arena)
+{
+        stmt_ty p;
+        p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p));
+        if (!p)
+                return NULL;
+        p->kind = Return_kind;
+        p->v.Return.value = value;
+        p->lineno = lineno;
+        p->col_offset = col_offset;
+        return p;
+}
+
+stmt_ty
+Delete(asdl_seq * targets, int lineno, int col_offset, PyArena *arena)
+{
+        stmt_ty p;
+        p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p));
+        if (!p)
+                return NULL;
+        p->kind = Delete_kind;
+        p->v.Delete.targets = targets;
+        p->lineno = lineno;
+        p->col_offset = col_offset;
+        return p;
+}
+
+stmt_ty
+Assign(asdl_seq * targets, expr_ty value, string type_comment, int lineno, int col_offset, PyArena
+       *arena)
+{
+        stmt_ty p;
+        if (!value) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field value is required for Assign");
+                return NULL;
+        }
+        p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p));
+        if (!p)
+                return NULL;
+        p->kind = Assign_kind;
+        p->v.Assign.targets = targets;
+        p->v.Assign.value = value;
+        p->v.Assign.type_comment = type_comment;
+        p->lineno = lineno;
+        p->col_offset = col_offset;
+        return p;
+}
+
+stmt_ty
+AugAssign(expr_ty target, operator_ty op, expr_ty value, int lineno, int col_offset, PyArena *arena)
+{
+        stmt_ty p;
+        if (!target) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field target is required for AugAssign");
+                return NULL;
+        }
+        if (!op) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field op is required for AugAssign");
+                return NULL;
+        }
+        if (!value) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field value is required for AugAssign");
+                return NULL;
+        }
+        p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p));
+        if (!p)
+                return NULL;
+        p->kind = AugAssign_kind;
+        p->v.AugAssign.target = target;
+        p->v.AugAssign.op = op;
+        p->v.AugAssign.value = value;
+        p->lineno = lineno;
+        p->col_offset = col_offset;
+        return p;
+}
+
+stmt_ty
+Print(expr_ty dest, asdl_seq * values, bool nl, int lineno, int col_offset, PyArena *arena)
+{
+        stmt_ty p;
+        p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p));
+        if (!p)
+                return NULL;
+        p->kind = Print_kind;
+        p->v.Print.dest = dest;
+        p->v.Print.values = values;
+        p->v.Print.nl = nl;
+        p->lineno = lineno;
+        p->col_offset = col_offset;
+        return p;
+}
+
+stmt_ty
+For(expr_ty target, expr_ty iter, asdl_seq * body, asdl_seq * orelse, string type_comment, int
+    lineno, int col_offset, PyArena *arena)
+{
+        stmt_ty p;
+        if (!target) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field target is required for For");
+                return NULL;
+        }
+        if (!iter) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field iter is required for For");
+                return NULL;
+        }
+        p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p));
+        if (!p)
+                return NULL;
+        p->kind = For_kind;
+        p->v.For.target = target;
+        p->v.For.iter = iter;
+        p->v.For.body = body;
+        p->v.For.orelse = orelse;
+        p->v.For.type_comment = type_comment;
+        p->lineno = lineno;
+        p->col_offset = col_offset;
+        return p;
+}
+
+stmt_ty
+While(expr_ty test, asdl_seq * body, asdl_seq * orelse, int lineno, int col_offset, PyArena *arena)
+{
+        stmt_ty p;
+        if (!test) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field test is required for While");
+                return NULL;
+        }
+        p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p));
+        if (!p)
+                return NULL;
+        p->kind = While_kind;
+        p->v.While.test = test;
+        p->v.While.body = body;
+        p->v.While.orelse = orelse;
+        p->lineno = lineno;
+        p->col_offset = col_offset;
+        return p;
+}
+
+stmt_ty
+If(expr_ty test, asdl_seq * body, asdl_seq * orelse, int lineno, int col_offset, PyArena *arena)
+{
+        stmt_ty p;
+        if (!test) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field test is required for If");
+                return NULL;
+        }
+        p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p));
+        if (!p)
+                return NULL;
+        p->kind = If_kind;
+        p->v.If.test = test;
+        p->v.If.body = body;
+        p->v.If.orelse = orelse;
+        p->lineno = lineno;
+        p->col_offset = col_offset;
+        return p;
+}
+
+stmt_ty
+With(expr_ty context_expr, expr_ty optional_vars, asdl_seq * body, string type_comment, int lineno,
+     int col_offset, PyArena *arena)
+{
+        stmt_ty p;
+        if (!context_expr) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field context_expr is required for With");
+                return NULL;
+        }
+        p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p));
+        if (!p)
+                return NULL;
+        p->kind = With_kind;
+        p->v.With.context_expr = context_expr;
+        p->v.With.optional_vars = optional_vars;
+        p->v.With.body = body;
+        p->v.With.type_comment = type_comment;
+        p->lineno = lineno;
+        p->col_offset = col_offset;
+        return p;
+}
+
+stmt_ty
+Raise(expr_ty type, expr_ty inst, expr_ty tback, int lineno, int col_offset, PyArena *arena)
+{
+        stmt_ty p;
+        p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p));
+        if (!p)
+                return NULL;
+        p->kind = Raise_kind;
+        p->v.Raise.type = type;
+        p->v.Raise.inst = inst;
+        p->v.Raise.tback = tback;
+        p->lineno = lineno;
+        p->col_offset = col_offset;
+        return p;
+}
+
+stmt_ty
+TryExcept(asdl_seq * body, asdl_seq * handlers, asdl_seq * orelse, int lineno, int col_offset,
+          PyArena *arena)
+{
+        stmt_ty p;
+        p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p));
+        if (!p)
+                return NULL;
+        p->kind = TryExcept_kind;
+        p->v.TryExcept.body = body;
+        p->v.TryExcept.handlers = handlers;
+        p->v.TryExcept.orelse = orelse;
+        p->lineno = lineno;
+        p->col_offset = col_offset;
+        return p;
+}
+
+stmt_ty
+TryFinally(asdl_seq * body, asdl_seq * finalbody, int lineno, int col_offset, PyArena *arena)
+{
+        stmt_ty p;
+        p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p));
+        if (!p)
+                return NULL;
+        p->kind = TryFinally_kind;
+        p->v.TryFinally.body = body;
+        p->v.TryFinally.finalbody = finalbody;
+        p->lineno = lineno;
+        p->col_offset = col_offset;
+        return p;
+}
+
+stmt_ty
+Assert(expr_ty test, expr_ty msg, int lineno, int col_offset, PyArena *arena)
+{
+        stmt_ty p;
+        if (!test) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field test is required for Assert");
+                return NULL;
+        }
+        p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p));
+        if (!p)
+                return NULL;
+        p->kind = Assert_kind;
+        p->v.Assert.test = test;
+        p->v.Assert.msg = msg;
+        p->lineno = lineno;
+        p->col_offset = col_offset;
+        return p;
+}
+
+stmt_ty
+Import(asdl_seq * names, int lineno, int col_offset, PyArena *arena)
+{
+        stmt_ty p;
+        p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p));
+        if (!p)
+                return NULL;
+        p->kind = Import_kind;
+        p->v.Import.names = names;
+        p->lineno = lineno;
+        p->col_offset = col_offset;
+        return p;
+}
+
+stmt_ty
+ImportFrom(identifier module, asdl_seq * names, int level, int lineno, int col_offset, PyArena
+           *arena)
+{
+        stmt_ty p;
+        p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p));
+        if (!p)
+                return NULL;
+        p->kind = ImportFrom_kind;
+        p->v.ImportFrom.module = module;
+        p->v.ImportFrom.names = names;
+        p->v.ImportFrom.level = level;
+        p->lineno = lineno;
+        p->col_offset = col_offset;
+        return p;
+}
+
+stmt_ty
+Exec(expr_ty body, expr_ty globals, expr_ty locals, int lineno, int col_offset, PyArena *arena)
+{
+        stmt_ty p;
+        if (!body) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field body is required for Exec");
+                return NULL;
+        }
+        p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p));
+        if (!p)
+                return NULL;
+        p->kind = Exec_kind;
+        p->v.Exec.body = body;
+        p->v.Exec.globals = globals;
+        p->v.Exec.locals = locals;
+        p->lineno = lineno;
+        p->col_offset = col_offset;
+        return p;
+}
+
+stmt_ty
+Global(asdl_seq * names, int lineno, int col_offset, PyArena *arena)
+{
+        stmt_ty p;
+        p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p));
+        if (!p)
+                return NULL;
+        p->kind = Global_kind;
+        p->v.Global.names = names;
+        p->lineno = lineno;
+        p->col_offset = col_offset;
+        return p;
+}
+
+stmt_ty
+Expr(expr_ty value, int lineno, int col_offset, PyArena *arena)
+{
+        stmt_ty p;
+        if (!value) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field value is required for Expr");
+                return NULL;
+        }
+        p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p));
+        if (!p)
+                return NULL;
+        p->kind = Expr_kind;
+        p->v.Expr.value = value;
+        p->lineno = lineno;
+        p->col_offset = col_offset;
+        return p;
+}
+
+stmt_ty
+Pass(int lineno, int col_offset, PyArena *arena)
+{
+        stmt_ty p;
+        p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p));
+        if (!p)
+                return NULL;
+        p->kind = Pass_kind;
+        p->lineno = lineno;
+        p->col_offset = col_offset;
+        return p;
+}
+
+stmt_ty
+Break(int lineno, int col_offset, PyArena *arena)
+{
+        stmt_ty p;
+        p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p));
+        if (!p)
+                return NULL;
+        p->kind = Break_kind;
+        p->lineno = lineno;
+        p->col_offset = col_offset;
+        return p;
+}
+
+stmt_ty
+Continue(int lineno, int col_offset, PyArena *arena)
+{
+        stmt_ty p;
+        p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p));
+        if (!p)
+                return NULL;
+        p->kind = Continue_kind;
+        p->lineno = lineno;
+        p->col_offset = col_offset;
+        return p;
+}
+
+expr_ty
+BoolOp(boolop_ty op, asdl_seq * values, int lineno, int col_offset, PyArena *arena)
+{
+        expr_ty p;
+        if (!op) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field op is required for BoolOp");
+                return NULL;
+        }
+        p = (expr_ty)PyArena_Malloc(arena, sizeof(*p));
+        if (!p)
+                return NULL;
+        p->kind = BoolOp_kind;
+        p->v.BoolOp.op = op;
+        p->v.BoolOp.values = values;
+        p->lineno = lineno;
+        p->col_offset = col_offset;
+        return p;
+}
+
+expr_ty
+BinOp(expr_ty left, operator_ty op, expr_ty right, int lineno, int col_offset, PyArena *arena)
+{
+        expr_ty p;
+        if (!left) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field left is required for BinOp");
+                return NULL;
+        }
+        if (!op) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field op is required for BinOp");
+                return NULL;
+        }
+        if (!right) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field right is required for BinOp");
+                return NULL;
+        }
+        p = (expr_ty)PyArena_Malloc(arena, sizeof(*p));
+        if (!p)
+                return NULL;
+        p->kind = BinOp_kind;
+        p->v.BinOp.left = left;
+        p->v.BinOp.op = op;
+        p->v.BinOp.right = right;
+        p->lineno = lineno;
+        p->col_offset = col_offset;
+        return p;
+}
+
+expr_ty
+UnaryOp(unaryop_ty op, expr_ty operand, int lineno, int col_offset, PyArena *arena)
+{
+        expr_ty p;
+        if (!op) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field op is required for UnaryOp");
+                return NULL;
+        }
+        if (!operand) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field operand is required for UnaryOp");
+                return NULL;
+        }
+        p = (expr_ty)PyArena_Malloc(arena, sizeof(*p));
+        if (!p)
+                return NULL;
+        p->kind = UnaryOp_kind;
+        p->v.UnaryOp.op = op;
+        p->v.UnaryOp.operand = operand;
+        p->lineno = lineno;
+        p->col_offset = col_offset;
+        return p;
+}
+
+expr_ty
+Lambda(arguments_ty args, expr_ty body, int lineno, int col_offset, PyArena *arena)
+{
+        expr_ty p;
+        if (!args) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field args is required for Lambda");
+                return NULL;
+        }
+        if (!body) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field body is required for Lambda");
+                return NULL;
+        }
+        p = (expr_ty)PyArena_Malloc(arena, sizeof(*p));
+        if (!p)
+                return NULL;
+        p->kind = Lambda_kind;
+        p->v.Lambda.args = args;
+        p->v.Lambda.body = body;
+        p->lineno = lineno;
+        p->col_offset = col_offset;
+        return p;
+}
+
+expr_ty
+IfExp(expr_ty test, expr_ty body, expr_ty orelse, int lineno, int col_offset, PyArena *arena)
+{
+        expr_ty p;
+        if (!test) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field test is required for IfExp");
+                return NULL;
+        }
+        if (!body) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field body is required for IfExp");
+                return NULL;
+        }
+        if (!orelse) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field orelse is required for IfExp");
+                return NULL;
+        }
+        p = (expr_ty)PyArena_Malloc(arena, sizeof(*p));
+        if (!p)
+                return NULL;
+        p->kind = IfExp_kind;
+        p->v.IfExp.test = test;
+        p->v.IfExp.body = body;
+        p->v.IfExp.orelse = orelse;
+        p->lineno = lineno;
+        p->col_offset = col_offset;
+        return p;
+}
+
+expr_ty
+Dict(asdl_seq * keys, asdl_seq * values, int lineno, int col_offset, PyArena *arena)
+{
+        expr_ty p;
+        p = (expr_ty)PyArena_Malloc(arena, sizeof(*p));
+        if (!p)
+                return NULL;
+        p->kind = Dict_kind;
+        p->v.Dict.keys = keys;
+        p->v.Dict.values = values;
+        p->lineno = lineno;
+        p->col_offset = col_offset;
+        return p;
+}
+
+expr_ty
+Set(asdl_seq * elts, int lineno, int col_offset, PyArena *arena)
+{
+        expr_ty p;
+        p = (expr_ty)PyArena_Malloc(arena, sizeof(*p));
+        if (!p)
+                return NULL;
+        p->kind = Set_kind;
+        p->v.Set.elts = elts;
+        p->lineno = lineno;
+        p->col_offset = col_offset;
+        return p;
+}
+
+expr_ty
+ListComp(expr_ty elt, asdl_seq * generators, int lineno, int col_offset, PyArena *arena)
+{
+        expr_ty p;
+        if (!elt) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field elt is required for ListComp");
+                return NULL;
+        }
+        p = (expr_ty)PyArena_Malloc(arena, sizeof(*p));
+        if (!p)
+                return NULL;
+        p->kind = ListComp_kind;
+        p->v.ListComp.elt = elt;
+        p->v.ListComp.generators = generators;
+        p->lineno = lineno;
+        p->col_offset = col_offset;
+        return p;
+}
+
+expr_ty
+SetComp(expr_ty elt, asdl_seq * generators, int lineno, int col_offset, PyArena *arena)
+{
+        expr_ty p;
+        if (!elt) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field elt is required for SetComp");
+                return NULL;
+        }
+        p = (expr_ty)PyArena_Malloc(arena, sizeof(*p));
+        if (!p)
+                return NULL;
+        p->kind = SetComp_kind;
+        p->v.SetComp.elt = elt;
+        p->v.SetComp.generators = generators;
+        p->lineno = lineno;
+        p->col_offset = col_offset;
+        return p;
+}
+
+expr_ty
+DictComp(expr_ty key, expr_ty value, asdl_seq * generators, int lineno, int col_offset, PyArena
+         *arena)
+{
+        expr_ty p;
+        if (!key) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field key is required for DictComp");
+                return NULL;
+        }
+        if (!value) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field value is required for DictComp");
+                return NULL;
+        }
+        p = (expr_ty)PyArena_Malloc(arena, sizeof(*p));
+        if (!p)
+                return NULL;
+        p->kind = DictComp_kind;
+        p->v.DictComp.key = key;
+        p->v.DictComp.value = value;
+        p->v.DictComp.generators = generators;
+        p->lineno = lineno;
+        p->col_offset = col_offset;
+        return p;
+}
+
+expr_ty
+GeneratorExp(expr_ty elt, asdl_seq * generators, int lineno, int col_offset, PyArena *arena)
+{
+        expr_ty p;
+        if (!elt) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field elt is required for GeneratorExp");
+                return NULL;
+        }
+        p = (expr_ty)PyArena_Malloc(arena, sizeof(*p));
+        if (!p)
+                return NULL;
+        p->kind = GeneratorExp_kind;
+        p->v.GeneratorExp.elt = elt;
+        p->v.GeneratorExp.generators = generators;
+        p->lineno = lineno;
+        p->col_offset = col_offset;
+        return p;
+}
+
+expr_ty
+Yield(expr_ty value, int lineno, int col_offset, PyArena *arena)
+{
+        expr_ty p;
+        p = (expr_ty)PyArena_Malloc(arena, sizeof(*p));
+        if (!p)
+                return NULL;
+        p->kind = Yield_kind;
+        p->v.Yield.value = value;
+        p->lineno = lineno;
+        p->col_offset = col_offset;
+        return p;
+}
+
+expr_ty
+Compare(expr_ty left, asdl_int_seq * ops, asdl_seq * comparators, int lineno, int col_offset,
+        PyArena *arena)
+{
+        expr_ty p;
+        if (!left) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field left is required for Compare");
+                return NULL;
+        }
+        p = (expr_ty)PyArena_Malloc(arena, sizeof(*p));
+        if (!p)
+                return NULL;
+        p->kind = Compare_kind;
+        p->v.Compare.left = left;
+        p->v.Compare.ops = ops;
+        p->v.Compare.comparators = comparators;
+        p->lineno = lineno;
+        p->col_offset = col_offset;
+        return p;
+}
+
+expr_ty
+Call(expr_ty func, asdl_seq * args, asdl_seq * keywords, expr_ty starargs, expr_ty kwargs, int
+     lineno, int col_offset, PyArena *arena)
+{
+        expr_ty p;
+        if (!func) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field func is required for Call");
+                return NULL;
+        }
+        p = (expr_ty)PyArena_Malloc(arena, sizeof(*p));
+        if (!p)
+                return NULL;
+        p->kind = Call_kind;
+        p->v.Call.func = func;
+        p->v.Call.args = args;
+        p->v.Call.keywords = keywords;
+        p->v.Call.starargs = starargs;
+        p->v.Call.kwargs = kwargs;
+        p->lineno = lineno;
+        p->col_offset = col_offset;
+        return p;
+}
+
+expr_ty
+Repr(expr_ty value, int lineno, int col_offset, PyArena *arena)
+{
+        expr_ty p;
+        if (!value) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field value is required for Repr");
+                return NULL;
+        }
+        p = (expr_ty)PyArena_Malloc(arena, sizeof(*p));
+        if (!p)
+                return NULL;
+        p->kind = Repr_kind;
+        p->v.Repr.value = value;
+        p->lineno = lineno;
+        p->col_offset = col_offset;
+        return p;
+}
+
+expr_ty
+Num(object n, int lineno, int col_offset, PyArena *arena)
+{
+        expr_ty p;
+        if (!n) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field n is required for Num");
+                return NULL;
+        }
+        p = (expr_ty)PyArena_Malloc(arena, sizeof(*p));
+        if (!p)
+                return NULL;
+        p->kind = Num_kind;
+        p->v.Num.n = n;
+        p->lineno = lineno;
+        p->col_offset = col_offset;
+        return p;
+}
+
+expr_ty
+Str(string s, int lineno, int col_offset, PyArena *arena)
+{
+        expr_ty p;
+        if (!s) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field s is required for Str");
+                return NULL;
+        }
+        p = (expr_ty)PyArena_Malloc(arena, sizeof(*p));
+        if (!p)
+                return NULL;
+        p->kind = Str_kind;
+        p->v.Str.s = s;
+        p->lineno = lineno;
+        p->col_offset = col_offset;
+        return p;
+}
+
+expr_ty
+Attribute(expr_ty value, identifier attr, expr_context_ty ctx, int lineno, int col_offset, PyArena
+          *arena)
+{
+        expr_ty p;
+        if (!value) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field value is required for Attribute");
+                return NULL;
+        }
+        if (!attr) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field attr is required for Attribute");
+                return NULL;
+        }
+        if (!ctx) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field ctx is required for Attribute");
+                return NULL;
+        }
+        p = (expr_ty)PyArena_Malloc(arena, sizeof(*p));
+        if (!p)
+                return NULL;
+        p->kind = Attribute_kind;
+        p->v.Attribute.value = value;
+        p->v.Attribute.attr = attr;
+        p->v.Attribute.ctx = ctx;
+        p->lineno = lineno;
+        p->col_offset = col_offset;
+        return p;
+}
+
+expr_ty
+Subscript(expr_ty value, slice_ty slice, expr_context_ty ctx, int lineno, int col_offset, PyArena
+          *arena)
+{
+        expr_ty p;
+        if (!value) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field value is required for Subscript");
+                return NULL;
+        }
+        if (!slice) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field slice is required for Subscript");
+                return NULL;
+        }
+        if (!ctx) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field ctx is required for Subscript");
+                return NULL;
+        }
+        p = (expr_ty)PyArena_Malloc(arena, sizeof(*p));
+        if (!p)
+                return NULL;
+        p->kind = Subscript_kind;
+        p->v.Subscript.value = value;
+        p->v.Subscript.slice = slice;
+        p->v.Subscript.ctx = ctx;
+        p->lineno = lineno;
+        p->col_offset = col_offset;
+        return p;
+}
+
+expr_ty
+Name(identifier id, expr_context_ty ctx, int lineno, int col_offset, PyArena *arena)
+{
+        expr_ty p;
+        if (!id) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field id is required for Name");
+                return NULL;
+        }
+        if (!ctx) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field ctx is required for Name");
+                return NULL;
+        }
+        p = (expr_ty)PyArena_Malloc(arena, sizeof(*p));
+        if (!p)
+                return NULL;
+        p->kind = Name_kind;
+        p->v.Name.id = id;
+        p->v.Name.ctx = ctx;
+        p->lineno = lineno;
+        p->col_offset = col_offset;
+        return p;
+}
+
+expr_ty
+List(asdl_seq * elts, expr_context_ty ctx, int lineno, int col_offset, PyArena *arena)
+{
+        expr_ty p;
+        if (!ctx) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field ctx is required for List");
+                return NULL;
+        }
+        p = (expr_ty)PyArena_Malloc(arena, sizeof(*p));
+        if (!p)
+                return NULL;
+        p->kind = List_kind;
+        p->v.List.elts = elts;
+        p->v.List.ctx = ctx;
+        p->lineno = lineno;
+        p->col_offset = col_offset;
+        return p;
+}
+
+expr_ty
+Tuple(asdl_seq * elts, expr_context_ty ctx, int lineno, int col_offset, PyArena *arena)
+{
+        expr_ty p;
+        if (!ctx) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field ctx is required for Tuple");
+                return NULL;
+        }
+        p = (expr_ty)PyArena_Malloc(arena, sizeof(*p));
+        if (!p)
+                return NULL;
+        p->kind = Tuple_kind;
+        p->v.Tuple.elts = elts;
+        p->v.Tuple.ctx = ctx;
+        p->lineno = lineno;
+        p->col_offset = col_offset;
+        return p;
+}
+
+slice_ty
+Ellipsis(PyArena *arena)
+{
+        slice_ty p;
+        p = (slice_ty)PyArena_Malloc(arena, sizeof(*p));
+        if (!p)
+                return NULL;
+        p->kind = Ellipsis_kind;
+        return p;
+}
+
+slice_ty
+Slice(expr_ty lower, expr_ty upper, expr_ty step, PyArena *arena)
+{
+        slice_ty p;
+        p = (slice_ty)PyArena_Malloc(arena, sizeof(*p));
+        if (!p)
+                return NULL;
+        p->kind = Slice_kind;
+        p->v.Slice.lower = lower;
+        p->v.Slice.upper = upper;
+        p->v.Slice.step = step;
+        return p;
+}
+
+slice_ty
+ExtSlice(asdl_seq * dims, PyArena *arena)
+{
+        slice_ty p;
+        p = (slice_ty)PyArena_Malloc(arena, sizeof(*p));
+        if (!p)
+                return NULL;
+        p->kind = ExtSlice_kind;
+        p->v.ExtSlice.dims = dims;
+        return p;
+}
+
+slice_ty
+Index(expr_ty value, PyArena *arena)
+{
+        slice_ty p;
+        if (!value) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field value is required for Index");
+                return NULL;
+        }
+        p = (slice_ty)PyArena_Malloc(arena, sizeof(*p));
+        if (!p)
+                return NULL;
+        p->kind = Index_kind;
+        p->v.Index.value = value;
+        return p;
+}
+
+comprehension_ty
+comprehension(expr_ty target, expr_ty iter, asdl_seq * ifs, PyArena *arena)
+{
+        comprehension_ty p;
+        if (!target) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field target is required for comprehension");
+                return NULL;
+        }
+        if (!iter) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field iter is required for comprehension");
+                return NULL;
+        }
+        p = (comprehension_ty)PyArena_Malloc(arena, sizeof(*p));
+        if (!p)
+                return NULL;
+        p->target = target;
+        p->iter = iter;
+        p->ifs = ifs;
+        return p;
+}
+
+excepthandler_ty
+ExceptHandler(expr_ty type, expr_ty name, asdl_seq * body, int lineno, int col_offset, PyArena
+              *arena)
+{
+        excepthandler_ty p;
+        p = (excepthandler_ty)PyArena_Malloc(arena, sizeof(*p));
+        if (!p)
+                return NULL;
+        p->kind = ExceptHandler_kind;
+        p->v.ExceptHandler.type = type;
+        p->v.ExceptHandler.name = name;
+        p->v.ExceptHandler.body = body;
+        p->lineno = lineno;
+        p->col_offset = col_offset;
+        return p;
+}
+
+arguments_ty
+arguments(asdl_seq * args, identifier vararg, identifier kwarg, asdl_seq * defaults, asdl_seq *
+          type_comments, PyArena *arena)
+{
+        arguments_ty p;
+        p = (arguments_ty)PyArena_Malloc(arena, sizeof(*p));
+        if (!p)
+                return NULL;
+        p->args = args;
+        p->vararg = vararg;
+        p->kwarg = kwarg;
+        p->defaults = defaults;
+        p->type_comments = type_comments;
+        return p;
+}
+
+keyword_ty
+keyword(identifier arg, expr_ty value, PyArena *arena)
+{
+        keyword_ty p;
+        if (!arg) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field arg is required for keyword");
+                return NULL;
+        }
+        if (!value) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field value is required for keyword");
+                return NULL;
+        }
+        p = (keyword_ty)PyArena_Malloc(arena, sizeof(*p));
+        if (!p)
+                return NULL;
+        p->arg = arg;
+        p->value = value;
+        return p;
+}
+
+alias_ty
+alias(identifier name, identifier asname, PyArena *arena)
+{
+        alias_ty p;
+        if (!name) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field name is required for alias");
+                return NULL;
+        }
+        p = (alias_ty)PyArena_Malloc(arena, sizeof(*p));
+        if (!p)
+                return NULL;
+        p->name = name;
+        p->asname = asname;
+        return p;
+}
+
+type_ignore_ty
+TypeIgnore(int lineno, PyArena *arena)
+{
+        type_ignore_ty p;
+        p = (type_ignore_ty)PyArena_Malloc(arena, sizeof(*p));
+        if (!p)
+                return NULL;
+        p->kind = TypeIgnore_kind;
+        p->v.TypeIgnore.lineno = lineno;
+        return p;
+}
+
+
+PyObject*
+ast2obj_mod(void* _o)
+{
+        mod_ty o = (mod_ty)_o;
+        PyObject *result = NULL, *value = NULL;
+        if (!o) {
+                Py_INCREF(Py_None);
+                return Py_None;
+        }
+
+        switch (o->kind) {
+        case Module_kind:
+                result = PyType_GenericNew(Module_type, NULL, NULL);
+                if (!result) goto failed;
+                value = ast2obj_list(o->v.Module.body, ast2obj_stmt);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "body", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                value = ast2obj_list(o->v.Module.type_ignores, ast2obj_type_ignore);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "type_ignores", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                break;
+        case Interactive_kind:
+                result = PyType_GenericNew(Interactive_type, NULL, NULL);
+                if (!result) goto failed;
+                value = ast2obj_list(o->v.Interactive.body, ast2obj_stmt);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "body", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                break;
+        case Expression_kind:
+                result = PyType_GenericNew(Expression_type, NULL, NULL);
+                if (!result) goto failed;
+                value = ast2obj_expr(o->v.Expression.body);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "body", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                break;
+        case FunctionType_kind:
+                result = PyType_GenericNew(FunctionType_type, NULL, NULL);
+                if (!result) goto failed;
+                value = ast2obj_list(o->v.FunctionType.argtypes, ast2obj_expr);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "argtypes", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                value = ast2obj_expr(o->v.FunctionType.returns);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "returns", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                break;
+        case Suite_kind:
+                result = PyType_GenericNew(Suite_type, NULL, NULL);
+                if (!result) goto failed;
+                value = ast2obj_list(o->v.Suite.body, ast2obj_stmt);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "body", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                break;
+        }
+        return result;
+failed:
+        Py_XDECREF(value);
+        Py_XDECREF(result);
+        return NULL;
+}
+
+PyObject*
+ast2obj_stmt(void* _o)
+{
+        stmt_ty o = (stmt_ty)_o;
+        PyObject *result = NULL, *value = NULL;
+        if (!o) {
+                Py_INCREF(Py_None);
+                return Py_None;
+        }
+
+        switch (o->kind) {
+        case FunctionDef_kind:
+                result = PyType_GenericNew(FunctionDef_type, NULL, NULL);
+                if (!result) goto failed;
+                value = ast2obj_identifier(o->v.FunctionDef.name);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "name", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                value = ast2obj_arguments(o->v.FunctionDef.args);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "args", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                value = ast2obj_list(o->v.FunctionDef.body, ast2obj_stmt);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "body", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                value = ast2obj_list(o->v.FunctionDef.decorator_list, ast2obj_expr);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "decorator_list", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                value = ast2obj_string(o->v.FunctionDef.type_comment);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "type_comment", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                break;
+        case ClassDef_kind:
+                result = PyType_GenericNew(ClassDef_type, NULL, NULL);
+                if (!result) goto failed;
+                value = ast2obj_identifier(o->v.ClassDef.name);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "name", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                value = ast2obj_list(o->v.ClassDef.bases, ast2obj_expr);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "bases", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                value = ast2obj_list(o->v.ClassDef.body, ast2obj_stmt);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "body", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                value = ast2obj_list(o->v.ClassDef.decorator_list, ast2obj_expr);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "decorator_list", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                break;
+        case Return_kind:
+                result = PyType_GenericNew(Return_type, NULL, NULL);
+                if (!result) goto failed;
+                value = ast2obj_expr(o->v.Return.value);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "value", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                break;
+        case Delete_kind:
+                result = PyType_GenericNew(Delete_type, NULL, NULL);
+                if (!result) goto failed;
+                value = ast2obj_list(o->v.Delete.targets, ast2obj_expr);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "targets", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                break;
+        case Assign_kind:
+                result = PyType_GenericNew(Assign_type, NULL, NULL);
+                if (!result) goto failed;
+                value = ast2obj_list(o->v.Assign.targets, ast2obj_expr);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "targets", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                value = ast2obj_expr(o->v.Assign.value);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "value", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                value = ast2obj_string(o->v.Assign.type_comment);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "type_comment", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                break;
+        case AugAssign_kind:
+                result = PyType_GenericNew(AugAssign_type, NULL, NULL);
+                if (!result) goto failed;
+                value = ast2obj_expr(o->v.AugAssign.target);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "target", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                value = ast2obj_operator(o->v.AugAssign.op);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "op", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                value = ast2obj_expr(o->v.AugAssign.value);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "value", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                break;
+        case Print_kind:
+                result = PyType_GenericNew(Print_type, NULL, NULL);
+                if (!result) goto failed;
+                value = ast2obj_expr(o->v.Print.dest);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "dest", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                value = ast2obj_list(o->v.Print.values, ast2obj_expr);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "values", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                value = ast2obj_bool(o->v.Print.nl);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "nl", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                break;
+        case For_kind:
+                result = PyType_GenericNew(For_type, NULL, NULL);
+                if (!result) goto failed;
+                value = ast2obj_expr(o->v.For.target);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "target", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                value = ast2obj_expr(o->v.For.iter);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "iter", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                value = ast2obj_list(o->v.For.body, ast2obj_stmt);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "body", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                value = ast2obj_list(o->v.For.orelse, ast2obj_stmt);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "orelse", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                value = ast2obj_string(o->v.For.type_comment);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "type_comment", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                break;
+        case While_kind:
+                result = PyType_GenericNew(While_type, NULL, NULL);
+                if (!result) goto failed;
+                value = ast2obj_expr(o->v.While.test);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "test", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                value = ast2obj_list(o->v.While.body, ast2obj_stmt);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "body", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                value = ast2obj_list(o->v.While.orelse, ast2obj_stmt);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "orelse", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                break;
+        case If_kind:
+                result = PyType_GenericNew(If_type, NULL, NULL);
+                if (!result) goto failed;
+                value = ast2obj_expr(o->v.If.test);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "test", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                value = ast2obj_list(o->v.If.body, ast2obj_stmt);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "body", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                value = ast2obj_list(o->v.If.orelse, ast2obj_stmt);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "orelse", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                break;
+        case With_kind:
+                result = PyType_GenericNew(With_type, NULL, NULL);
+                if (!result) goto failed;
+                value = ast2obj_expr(o->v.With.context_expr);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "context_expr", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                value = ast2obj_expr(o->v.With.optional_vars);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "optional_vars", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                value = ast2obj_list(o->v.With.body, ast2obj_stmt);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "body", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                value = ast2obj_string(o->v.With.type_comment);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "type_comment", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                break;
+        case Raise_kind:
+                result = PyType_GenericNew(Raise_type, NULL, NULL);
+                if (!result) goto failed;
+                value = ast2obj_expr(o->v.Raise.type);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "type", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                value = ast2obj_expr(o->v.Raise.inst);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "inst", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                value = ast2obj_expr(o->v.Raise.tback);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "tback", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                break;
+        case TryExcept_kind:
+                result = PyType_GenericNew(TryExcept_type, NULL, NULL);
+                if (!result) goto failed;
+                value = ast2obj_list(o->v.TryExcept.body, ast2obj_stmt);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "body", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                value = ast2obj_list(o->v.TryExcept.handlers, ast2obj_excepthandler);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "handlers", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                value = ast2obj_list(o->v.TryExcept.orelse, ast2obj_stmt);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "orelse", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                break;
+        case TryFinally_kind:
+                result = PyType_GenericNew(TryFinally_type, NULL, NULL);
+                if (!result) goto failed;
+                value = ast2obj_list(o->v.TryFinally.body, ast2obj_stmt);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "body", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                value = ast2obj_list(o->v.TryFinally.finalbody, ast2obj_stmt);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "finalbody", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                break;
+        case Assert_kind:
+                result = PyType_GenericNew(Assert_type, NULL, NULL);
+                if (!result) goto failed;
+                value = ast2obj_expr(o->v.Assert.test);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "test", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                value = ast2obj_expr(o->v.Assert.msg);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "msg", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                break;
+        case Import_kind:
+                result = PyType_GenericNew(Import_type, NULL, NULL);
+                if (!result) goto failed;
+                value = ast2obj_list(o->v.Import.names, ast2obj_alias);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "names", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                break;
+        case ImportFrom_kind:
+                result = PyType_GenericNew(ImportFrom_type, NULL, NULL);
+                if (!result) goto failed;
+                value = ast2obj_identifier(o->v.ImportFrom.module);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "module", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                value = ast2obj_list(o->v.ImportFrom.names, ast2obj_alias);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "names", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                value = ast2obj_int(o->v.ImportFrom.level);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "level", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                break;
+        case Exec_kind:
+                result = PyType_GenericNew(Exec_type, NULL, NULL);
+                if (!result) goto failed;
+                value = ast2obj_expr(o->v.Exec.body);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "body", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                value = ast2obj_expr(o->v.Exec.globals);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "globals", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                value = ast2obj_expr(o->v.Exec.locals);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "locals", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                break;
+        case Global_kind:
+                result = PyType_GenericNew(Global_type, NULL, NULL);
+                if (!result) goto failed;
+                value = ast2obj_list(o->v.Global.names, ast2obj_identifier);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "names", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                break;
+        case Expr_kind:
+                result = PyType_GenericNew(Expr_type, NULL, NULL);
+                if (!result) goto failed;
+                value = ast2obj_expr(o->v.Expr.value);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "value", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                break;
+        case Pass_kind:
+                result = PyType_GenericNew(Pass_type, NULL, NULL);
+                if (!result) goto failed;
+                break;
+        case Break_kind:
+                result = PyType_GenericNew(Break_type, NULL, NULL);
+                if (!result) goto failed;
+                break;
+        case Continue_kind:
+                result = PyType_GenericNew(Continue_type, NULL, NULL);
+                if (!result) goto failed;
+                break;
+        }
+        value = ast2obj_int(o->lineno);
+        if (!value) goto failed;
+        if (PyObject_SetAttrString(result, "lineno", value) < 0)
+                goto failed;
+        Py_DECREF(value);
+        value = ast2obj_int(o->col_offset);
+        if (!value) goto failed;
+        if (PyObject_SetAttrString(result, "col_offset", value) < 0)
+                goto failed;
+        Py_DECREF(value);
+        return result;
+failed:
+        Py_XDECREF(value);
+        Py_XDECREF(result);
+        return NULL;
+}
+
+PyObject*
+ast2obj_expr(void* _o)
+{
+        expr_ty o = (expr_ty)_o;
+        PyObject *result = NULL, *value = NULL;
+        if (!o) {
+                Py_INCREF(Py_None);
+                return Py_None;
+        }
+
+        switch (o->kind) {
+        case BoolOp_kind:
+                result = PyType_GenericNew(BoolOp_type, NULL, NULL);
+                if (!result) goto failed;
+                value = ast2obj_boolop(o->v.BoolOp.op);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "op", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                value = ast2obj_list(o->v.BoolOp.values, ast2obj_expr);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "values", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                break;
+        case BinOp_kind:
+                result = PyType_GenericNew(BinOp_type, NULL, NULL);
+                if (!result) goto failed;
+                value = ast2obj_expr(o->v.BinOp.left);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "left", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                value = ast2obj_operator(o->v.BinOp.op);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "op", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                value = ast2obj_expr(o->v.BinOp.right);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "right", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                break;
+        case UnaryOp_kind:
+                result = PyType_GenericNew(UnaryOp_type, NULL, NULL);
+                if (!result) goto failed;
+                value = ast2obj_unaryop(o->v.UnaryOp.op);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "op", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                value = ast2obj_expr(o->v.UnaryOp.operand);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "operand", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                break;
+        case Lambda_kind:
+                result = PyType_GenericNew(Lambda_type, NULL, NULL);
+                if (!result) goto failed;
+                value = ast2obj_arguments(o->v.Lambda.args);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "args", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                value = ast2obj_expr(o->v.Lambda.body);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "body", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                break;
+        case IfExp_kind:
+                result = PyType_GenericNew(IfExp_type, NULL, NULL);
+                if (!result) goto failed;
+                value = ast2obj_expr(o->v.IfExp.test);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "test", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                value = ast2obj_expr(o->v.IfExp.body);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "body", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                value = ast2obj_expr(o->v.IfExp.orelse);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "orelse", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                break;
+        case Dict_kind:
+                result = PyType_GenericNew(Dict_type, NULL, NULL);
+                if (!result) goto failed;
+                value = ast2obj_list(o->v.Dict.keys, ast2obj_expr);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "keys", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                value = ast2obj_list(o->v.Dict.values, ast2obj_expr);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "values", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                break;
+        case Set_kind:
+                result = PyType_GenericNew(Set_type, NULL, NULL);
+                if (!result) goto failed;
+                value = ast2obj_list(o->v.Set.elts, ast2obj_expr);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "elts", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                break;
+        case ListComp_kind:
+                result = PyType_GenericNew(ListComp_type, NULL, NULL);
+                if (!result) goto failed;
+                value = ast2obj_expr(o->v.ListComp.elt);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "elt", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                value = ast2obj_list(o->v.ListComp.generators, ast2obj_comprehension);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "generators", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                break;
+        case SetComp_kind:
+                result = PyType_GenericNew(SetComp_type, NULL, NULL);
+                if (!result) goto failed;
+                value = ast2obj_expr(o->v.SetComp.elt);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "elt", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                value = ast2obj_list(o->v.SetComp.generators, ast2obj_comprehension);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "generators", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                break;
+        case DictComp_kind:
+                result = PyType_GenericNew(DictComp_type, NULL, NULL);
+                if (!result) goto failed;
+                value = ast2obj_expr(o->v.DictComp.key);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "key", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                value = ast2obj_expr(o->v.DictComp.value);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "value", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                value = ast2obj_list(o->v.DictComp.generators, ast2obj_comprehension);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "generators", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                break;
+        case GeneratorExp_kind:
+                result = PyType_GenericNew(GeneratorExp_type, NULL, NULL);
+                if (!result) goto failed;
+                value = ast2obj_expr(o->v.GeneratorExp.elt);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "elt", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                value = ast2obj_list(o->v.GeneratorExp.generators, ast2obj_comprehension);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "generators", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                break;
+        case Yield_kind:
+                result = PyType_GenericNew(Yield_type, NULL, NULL);
+                if (!result) goto failed;
+                value = ast2obj_expr(o->v.Yield.value);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "value", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                break;
+        case Compare_kind:
+                result = PyType_GenericNew(Compare_type, NULL, NULL);
+                if (!result) goto failed;
+                value = ast2obj_expr(o->v.Compare.left);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "left", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                {
+                        int i, n = asdl_seq_LEN(o->v.Compare.ops);
+                        value = PyList_New(n);
+                        if (!value) goto failed;
+                        for(i = 0; i < n; i++)
+                                PyList_SET_ITEM(value, i, ast2obj_cmpop((cmpop_ty)asdl_seq_GET(o->v.Compare.ops, i)));
+                }
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "ops", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                value = ast2obj_list(o->v.Compare.comparators, ast2obj_expr);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "comparators", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                break;
+        case Call_kind:
+                result = PyType_GenericNew(Call_type, NULL, NULL);
+                if (!result) goto failed;
+                value = ast2obj_expr(o->v.Call.func);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "func", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                value = ast2obj_list(o->v.Call.args, ast2obj_expr);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "args", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                value = ast2obj_list(o->v.Call.keywords, ast2obj_keyword);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "keywords", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                value = ast2obj_expr(o->v.Call.starargs);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "starargs", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                value = ast2obj_expr(o->v.Call.kwargs);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "kwargs", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                break;
+        case Repr_kind:
+                result = PyType_GenericNew(Repr_type, NULL, NULL);
+                if (!result) goto failed;
+                value = ast2obj_expr(o->v.Repr.value);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "value", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                break;
+        case Num_kind:
+                result = PyType_GenericNew(Num_type, NULL, NULL);
+                if (!result) goto failed;
+                value = ast2obj_object(o->v.Num.n);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "n", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                break;
+        case Str_kind:
+                result = PyType_GenericNew(Str_type, NULL, NULL);
+                if (!result) goto failed;
+                value = ast2obj_string(o->v.Str.s);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "s", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                break;
+        case Attribute_kind:
+                result = PyType_GenericNew(Attribute_type, NULL, NULL);
+                if (!result) goto failed;
+                value = ast2obj_expr(o->v.Attribute.value);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "value", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                value = ast2obj_identifier(o->v.Attribute.attr);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "attr", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                value = ast2obj_expr_context(o->v.Attribute.ctx);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "ctx", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                break;
+        case Subscript_kind:
+                result = PyType_GenericNew(Subscript_type, NULL, NULL);
+                if (!result) goto failed;
+                value = ast2obj_expr(o->v.Subscript.value);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "value", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                value = ast2obj_slice(o->v.Subscript.slice);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "slice", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                value = ast2obj_expr_context(o->v.Subscript.ctx);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "ctx", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                break;
+        case Name_kind:
+                result = PyType_GenericNew(Name_type, NULL, NULL);
+                if (!result) goto failed;
+                value = ast2obj_identifier(o->v.Name.id);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "id", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                value = ast2obj_expr_context(o->v.Name.ctx);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "ctx", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                break;
+        case List_kind:
+                result = PyType_GenericNew(List_type, NULL, NULL);
+                if (!result) goto failed;
+                value = ast2obj_list(o->v.List.elts, ast2obj_expr);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "elts", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                value = ast2obj_expr_context(o->v.List.ctx);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "ctx", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                break;
+        case Tuple_kind:
+                result = PyType_GenericNew(Tuple_type, NULL, NULL);
+                if (!result) goto failed;
+                value = ast2obj_list(o->v.Tuple.elts, ast2obj_expr);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "elts", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                value = ast2obj_expr_context(o->v.Tuple.ctx);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "ctx", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                break;
+        }
+        value = ast2obj_int(o->lineno);
+        if (!value) goto failed;
+        if (PyObject_SetAttrString(result, "lineno", value) < 0)
+                goto failed;
+        Py_DECREF(value);
+        value = ast2obj_int(o->col_offset);
+        if (!value) goto failed;
+        if (PyObject_SetAttrString(result, "col_offset", value) < 0)
+                goto failed;
+        Py_DECREF(value);
+        return result;
+failed:
+        Py_XDECREF(value);
+        Py_XDECREF(result);
+        return NULL;
+}
+
+PyObject* ast2obj_expr_context(expr_context_ty o)
+{
+        switch(o) {
+                case Load:
+                        Py_INCREF(Load_singleton);
+                        return Load_singleton;
+                case Store:
+                        Py_INCREF(Store_singleton);
+                        return Store_singleton;
+                case Del:
+                        Py_INCREF(Del_singleton);
+                        return Del_singleton;
+                case AugLoad:
+                        Py_INCREF(AugLoad_singleton);
+                        return AugLoad_singleton;
+                case AugStore:
+                        Py_INCREF(AugStore_singleton);
+                        return AugStore_singleton;
+                case Param:
+                        Py_INCREF(Param_singleton);
+                        return Param_singleton;
+                default:
+                        /* should never happen, but just in case ... */
+                        PyErr_Format(PyExc_SystemError, "unknown expr_context found");
+                        return NULL;
+        }
+}
+PyObject*
+ast2obj_slice(void* _o)
+{
+        slice_ty o = (slice_ty)_o;
+        PyObject *result = NULL, *value = NULL;
+        if (!o) {
+                Py_INCREF(Py_None);
+                return Py_None;
+        }
+
+        switch (o->kind) {
+        case Ellipsis_kind:
+                result = PyType_GenericNew(Ellipsis_type, NULL, NULL);
+                if (!result) goto failed;
+                break;
+        case Slice_kind:
+                result = PyType_GenericNew(Slice_type, NULL, NULL);
+                if (!result) goto failed;
+                value = ast2obj_expr(o->v.Slice.lower);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "lower", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                value = ast2obj_expr(o->v.Slice.upper);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "upper", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                value = ast2obj_expr(o->v.Slice.step);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "step", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                break;
+        case ExtSlice_kind:
+                result = PyType_GenericNew(ExtSlice_type, NULL, NULL);
+                if (!result) goto failed;
+                value = ast2obj_list(o->v.ExtSlice.dims, ast2obj_slice);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "dims", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                break;
+        case Index_kind:
+                result = PyType_GenericNew(Index_type, NULL, NULL);
+                if (!result) goto failed;
+                value = ast2obj_expr(o->v.Index.value);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "value", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                break;
+        }
+        return result;
+failed:
+        Py_XDECREF(value);
+        Py_XDECREF(result);
+        return NULL;
+}
+
+PyObject* ast2obj_boolop(boolop_ty o)
+{
+        switch(o) {
+                case And:
+                        Py_INCREF(And_singleton);
+                        return And_singleton;
+                case Or:
+                        Py_INCREF(Or_singleton);
+                        return Or_singleton;
+                default:
+                        /* should never happen, but just in case ... */
+                        PyErr_Format(PyExc_SystemError, "unknown boolop found");
+                        return NULL;
+        }
+}
+PyObject* ast2obj_operator(operator_ty o)
+{
+        switch(o) {
+                case Add:
+                        Py_INCREF(Add_singleton);
+                        return Add_singleton;
+                case Sub:
+                        Py_INCREF(Sub_singleton);
+                        return Sub_singleton;
+                case Mult:
+                        Py_INCREF(Mult_singleton);
+                        return Mult_singleton;
+                case Div:
+                        Py_INCREF(Div_singleton);
+                        return Div_singleton;
+                case Mod:
+                        Py_INCREF(Mod_singleton);
+                        return Mod_singleton;
+                case Pow:
+                        Py_INCREF(Pow_singleton);
+                        return Pow_singleton;
+                case LShift:
+                        Py_INCREF(LShift_singleton);
+                        return LShift_singleton;
+                case RShift:
+                        Py_INCREF(RShift_singleton);
+                        return RShift_singleton;
+                case BitOr:
+                        Py_INCREF(BitOr_singleton);
+                        return BitOr_singleton;
+                case BitXor:
+                        Py_INCREF(BitXor_singleton);
+                        return BitXor_singleton;
+                case BitAnd:
+                        Py_INCREF(BitAnd_singleton);
+                        return BitAnd_singleton;
+                case FloorDiv:
+                        Py_INCREF(FloorDiv_singleton);
+                        return FloorDiv_singleton;
+                default:
+                        /* should never happen, but just in case ... */
+                        PyErr_Format(PyExc_SystemError, "unknown operator found");
+                        return NULL;
+        }
+}
+PyObject* ast2obj_unaryop(unaryop_ty o)
+{
+        switch(o) {
+                case Invert:
+                        Py_INCREF(Invert_singleton);
+                        return Invert_singleton;
+                case Not:
+                        Py_INCREF(Not_singleton);
+                        return Not_singleton;
+                case UAdd:
+                        Py_INCREF(UAdd_singleton);
+                        return UAdd_singleton;
+                case USub:
+                        Py_INCREF(USub_singleton);
+                        return USub_singleton;
+                default:
+                        /* should never happen, but just in case ... */
+                        PyErr_Format(PyExc_SystemError, "unknown unaryop found");
+                        return NULL;
+        }
+}
+PyObject* ast2obj_cmpop(cmpop_ty o)
+{
+        switch(o) {
+                case Eq:
+                        Py_INCREF(Eq_singleton);
+                        return Eq_singleton;
+                case NotEq:
+                        Py_INCREF(NotEq_singleton);
+                        return NotEq_singleton;
+                case Lt:
+                        Py_INCREF(Lt_singleton);
+                        return Lt_singleton;
+                case LtE:
+                        Py_INCREF(LtE_singleton);
+                        return LtE_singleton;
+                case Gt:
+                        Py_INCREF(Gt_singleton);
+                        return Gt_singleton;
+                case GtE:
+                        Py_INCREF(GtE_singleton);
+                        return GtE_singleton;
+                case Is:
+                        Py_INCREF(Is_singleton);
+                        return Is_singleton;
+                case IsNot:
+                        Py_INCREF(IsNot_singleton);
+                        return IsNot_singleton;
+                case In:
+                        Py_INCREF(In_singleton);
+                        return In_singleton;
+                case NotIn:
+                        Py_INCREF(NotIn_singleton);
+                        return NotIn_singleton;
+                default:
+                        /* should never happen, but just in case ... */
+                        PyErr_Format(PyExc_SystemError, "unknown cmpop found");
+                        return NULL;
+        }
+}
+PyObject*
+ast2obj_comprehension(void* _o)
+{
+        comprehension_ty o = (comprehension_ty)_o;
+        PyObject *result = NULL, *value = NULL;
+        if (!o) {
+                Py_INCREF(Py_None);
+                return Py_None;
+        }
+
+        result = PyType_GenericNew(comprehension_type, NULL, NULL);
+        if (!result) return NULL;
+        value = ast2obj_expr(o->target);
+        if (!value) goto failed;
+        if (PyObject_SetAttrString(result, "target", value) == -1)
+                goto failed;
+        Py_DECREF(value);
+        value = ast2obj_expr(o->iter);
+        if (!value) goto failed;
+        if (PyObject_SetAttrString(result, "iter", value) == -1)
+                goto failed;
+        Py_DECREF(value);
+        value = ast2obj_list(o->ifs, ast2obj_expr);
+        if (!value) goto failed;
+        if (PyObject_SetAttrString(result, "ifs", value) == -1)
+                goto failed;
+        Py_DECREF(value);
+        return result;
+failed:
+        Py_XDECREF(value);
+        Py_XDECREF(result);
+        return NULL;
+}
+
+PyObject*
+ast2obj_excepthandler(void* _o)
+{
+        excepthandler_ty o = (excepthandler_ty)_o;
+        PyObject *result = NULL, *value = NULL;
+        if (!o) {
+                Py_INCREF(Py_None);
+                return Py_None;
+        }
+
+        switch (o->kind) {
+        case ExceptHandler_kind:
+                result = PyType_GenericNew(ExceptHandler_type, NULL, NULL);
+                if (!result) goto failed;
+                value = ast2obj_expr(o->v.ExceptHandler.type);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "type", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                value = ast2obj_expr(o->v.ExceptHandler.name);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "name", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                value = ast2obj_list(o->v.ExceptHandler.body, ast2obj_stmt);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "body", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                break;
+        }
+        value = ast2obj_int(o->lineno);
+        if (!value) goto failed;
+        if (PyObject_SetAttrString(result, "lineno", value) < 0)
+                goto failed;
+        Py_DECREF(value);
+        value = ast2obj_int(o->col_offset);
+        if (!value) goto failed;
+        if (PyObject_SetAttrString(result, "col_offset", value) < 0)
+                goto failed;
+        Py_DECREF(value);
+        return result;
+failed:
+        Py_XDECREF(value);
+        Py_XDECREF(result);
+        return NULL;
+}
+
+PyObject*
+ast2obj_arguments(void* _o)
+{
+        arguments_ty o = (arguments_ty)_o;
+        PyObject *result = NULL, *value = NULL;
+        if (!o) {
+                Py_INCREF(Py_None);
+                return Py_None;
+        }
+
+        result = PyType_GenericNew(arguments_type, NULL, NULL);
+        if (!result) return NULL;
+        value = ast2obj_list(o->args, ast2obj_expr);
+        if (!value) goto failed;
+        if (PyObject_SetAttrString(result, "args", value) == -1)
+                goto failed;
+        Py_DECREF(value);
+        value = ast2obj_identifier(o->vararg);
+        if (!value) goto failed;
+        if (PyObject_SetAttrString(result, "vararg", value) == -1)
+                goto failed;
+        Py_DECREF(value);
+        value = ast2obj_identifier(o->kwarg);
+        if (!value) goto failed;
+        if (PyObject_SetAttrString(result, "kwarg", value) == -1)
+                goto failed;
+        Py_DECREF(value);
+        value = ast2obj_list(o->defaults, ast2obj_expr);
+        if (!value) goto failed;
+        if (PyObject_SetAttrString(result, "defaults", value) == -1)
+                goto failed;
+        Py_DECREF(value);
+        value = ast2obj_list(o->type_comments, ast2obj_string);
+        if (!value) goto failed;
+        if (PyObject_SetAttrString(result, "type_comments", value) == -1)
+                goto failed;
+        Py_DECREF(value);
+        return result;
+failed:
+        Py_XDECREF(value);
+        Py_XDECREF(result);
+        return NULL;
+}
+
+PyObject*
+ast2obj_keyword(void* _o)
+{
+        keyword_ty o = (keyword_ty)_o;
+        PyObject *result = NULL, *value = NULL;
+        if (!o) {
+                Py_INCREF(Py_None);
+                return Py_None;
+        }
+
+        result = PyType_GenericNew(keyword_type, NULL, NULL);
+        if (!result) return NULL;
+        value = ast2obj_identifier(o->arg);
+        if (!value) goto failed;
+        if (PyObject_SetAttrString(result, "arg", value) == -1)
+                goto failed;
+        Py_DECREF(value);
+        value = ast2obj_expr(o->value);
+        if (!value) goto failed;
+        if (PyObject_SetAttrString(result, "value", value) == -1)
+                goto failed;
+        Py_DECREF(value);
+        return result;
+failed:
+        Py_XDECREF(value);
+        Py_XDECREF(result);
+        return NULL;
+}
+
+PyObject*
+ast2obj_alias(void* _o)
+{
+        alias_ty o = (alias_ty)_o;
+        PyObject *result = NULL, *value = NULL;
+        if (!o) {
+                Py_INCREF(Py_None);
+                return Py_None;
+        }
+
+        result = PyType_GenericNew(alias_type, NULL, NULL);
+        if (!result) return NULL;
+        value = ast2obj_identifier(o->name);
+        if (!value) goto failed;
+        if (PyObject_SetAttrString(result, "name", value) == -1)
+                goto failed;
+        Py_DECREF(value);
+        value = ast2obj_identifier(o->asname);
+        if (!value) goto failed;
+        if (PyObject_SetAttrString(result, "asname", value) == -1)
+                goto failed;
+        Py_DECREF(value);
+        return result;
+failed:
+        Py_XDECREF(value);
+        Py_XDECREF(result);
+        return NULL;
+}
+
+PyObject*
+ast2obj_type_ignore(void* _o)
+{
+        type_ignore_ty o = (type_ignore_ty)_o;
+        PyObject *result = NULL, *value = NULL;
+        if (!o) {
+                Py_INCREF(Py_None);
+                return Py_None;
+        }
+
+        switch (o->kind) {
+        case TypeIgnore_kind:
+                result = PyType_GenericNew(TypeIgnore_type, NULL, NULL);
+                if (!result) goto failed;
+                value = ast2obj_int(o->v.TypeIgnore.lineno);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "lineno", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                break;
+        }
+        return result;
+failed:
+        Py_XDECREF(value);
+        Py_XDECREF(result);
+        return NULL;
+}
+
+
+int
+obj2ast_mod(PyObject* obj, mod_ty* out, PyArena* arena)
+{
+        PyObject* tmp = NULL;
+        int isinstance;
+
+
+        if (obj == Py_None) {
+                *out = NULL;
+                return 0;
+        }
+        isinstance = PyObject_IsInstance(obj, (PyObject*)Module_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+                asdl_seq* body;
+                asdl_seq* type_ignores;
+
+                if (PyObject_HasAttrString(obj, "body")) {
+                        int res;
+                        Py_ssize_t len;
+                        Py_ssize_t i;
+                        tmp = PyObject_GetAttrString(obj, "body");
+                        if (tmp == NULL) goto failed;
+                        if (!PyList_Check(tmp)) {
+                                PyErr_Format(PyExc_TypeError, "Module field \"body\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                                goto failed;
+                        }
+                        len = PyList_GET_SIZE(tmp);
+                        body = asdl_seq_new(len, arena);
+                        if (body == NULL) goto failed;
+                        for (i = 0; i < len; i++) {
+                                stmt_ty value;
+                                res = obj2ast_stmt(PyList_GET_ITEM(tmp, i), &value, arena);
+                                if (res != 0) goto failed;
+                                asdl_seq_SET(body, i, value);
+                        }
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"body\" missing from Module");
+                        return 1;
+                }
+                if (PyObject_HasAttrString(obj, "type_ignores")) {
+                        int res;
+                        Py_ssize_t len;
+                        Py_ssize_t i;
+                        tmp = PyObject_GetAttrString(obj, "type_ignores");
+                        if (tmp == NULL) goto failed;
+                        if (!PyList_Check(tmp)) {
+                                PyErr_Format(PyExc_TypeError, "Module field \"type_ignores\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                                goto failed;
+                        }
+                        len = PyList_GET_SIZE(tmp);
+                        type_ignores = asdl_seq_new(len, arena);
+                        if (type_ignores == NULL) goto failed;
+                        for (i = 0; i < len; i++) {
+                                type_ignore_ty value;
+                                res = obj2ast_type_ignore(PyList_GET_ITEM(tmp, i), &value, arena);
+                                if (res != 0) goto failed;
+                                asdl_seq_SET(type_ignores, i, value);
+                        }
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"type_ignores\" missing from Module");
+                        return 1;
+                }
+                *out = Module(body, type_ignores, arena);
+                if (*out == NULL) goto failed;
+                return 0;
+        }
+        isinstance = PyObject_IsInstance(obj, (PyObject*)Interactive_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+                asdl_seq* body;
+
+                if (PyObject_HasAttrString(obj, "body")) {
+                        int res;
+                        Py_ssize_t len;
+                        Py_ssize_t i;
+                        tmp = PyObject_GetAttrString(obj, "body");
+                        if (tmp == NULL) goto failed;
+                        if (!PyList_Check(tmp)) {
+                                PyErr_Format(PyExc_TypeError, "Interactive field \"body\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                                goto failed;
+                        }
+                        len = PyList_GET_SIZE(tmp);
+                        body = asdl_seq_new(len, arena);
+                        if (body == NULL) goto failed;
+                        for (i = 0; i < len; i++) {
+                                stmt_ty value;
+                                res = obj2ast_stmt(PyList_GET_ITEM(tmp, i), &value, arena);
+                                if (res != 0) goto failed;
+                                asdl_seq_SET(body, i, value);
+                        }
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"body\" missing from Interactive");
+                        return 1;
+                }
+                *out = Interactive(body, arena);
+                if (*out == NULL) goto failed;
+                return 0;
+        }
+        isinstance = PyObject_IsInstance(obj, (PyObject*)Expression_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+                expr_ty body;
+
+                if (PyObject_HasAttrString(obj, "body")) {
+                        int res;
+                        tmp = PyObject_GetAttrString(obj, "body");
+                        if (tmp == NULL) goto failed;
+                        res = obj2ast_expr(tmp, &body, arena);
+                        if (res != 0) goto failed;
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"body\" missing from Expression");
+                        return 1;
+                }
+                *out = Expression(body, arena);
+                if (*out == NULL) goto failed;
+                return 0;
+        }
+        isinstance = PyObject_IsInstance(obj, (PyObject*)FunctionType_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+                asdl_seq* argtypes;
+                expr_ty returns;
+
+                if (PyObject_HasAttrString(obj, "argtypes")) {
+                        int res;
+                        Py_ssize_t len;
+                        Py_ssize_t i;
+                        tmp = PyObject_GetAttrString(obj, "argtypes");
+                        if (tmp == NULL) goto failed;
+                        if (!PyList_Check(tmp)) {
+                                PyErr_Format(PyExc_TypeError, "FunctionType field \"argtypes\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                                goto failed;
+                        }
+                        len = PyList_GET_SIZE(tmp);
+                        argtypes = asdl_seq_new(len, arena);
+                        if (argtypes == NULL) goto failed;
+                        for (i = 0; i < len; i++) {
+                                expr_ty value;
+                                res = obj2ast_expr(PyList_GET_ITEM(tmp, i), &value, arena);
+                                if (res != 0) goto failed;
+                                asdl_seq_SET(argtypes, i, value);
+                        }
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"argtypes\" missing from FunctionType");
+                        return 1;
+                }
+                if (PyObject_HasAttrString(obj, "returns")) {
+                        int res;
+                        tmp = PyObject_GetAttrString(obj, "returns");
+                        if (tmp == NULL) goto failed;
+                        res = obj2ast_expr(tmp, &returns, arena);
+                        if (res != 0) goto failed;
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"returns\" missing from FunctionType");
+                        return 1;
+                }
+                *out = FunctionType(argtypes, returns, arena);
+                if (*out == NULL) goto failed;
+                return 0;
+        }
+        isinstance = PyObject_IsInstance(obj, (PyObject*)Suite_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+                asdl_seq* body;
+
+                if (PyObject_HasAttrString(obj, "body")) {
+                        int res;
+                        Py_ssize_t len;
+                        Py_ssize_t i;
+                        tmp = PyObject_GetAttrString(obj, "body");
+                        if (tmp == NULL) goto failed;
+                        if (!PyList_Check(tmp)) {
+                                PyErr_Format(PyExc_TypeError, "Suite field \"body\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                                goto failed;
+                        }
+                        len = PyList_GET_SIZE(tmp);
+                        body = asdl_seq_new(len, arena);
+                        if (body == NULL) goto failed;
+                        for (i = 0; i < len; i++) {
+                                stmt_ty value;
+                                res = obj2ast_stmt(PyList_GET_ITEM(tmp, i), &value, arena);
+                                if (res != 0) goto failed;
+                                asdl_seq_SET(body, i, value);
+                        }
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"body\" missing from Suite");
+                        return 1;
+                }
+                *out = Suite(body, arena);
+                if (*out == NULL) goto failed;
+                return 0;
+        }
+
+        tmp = PyObject_Repr(obj);
+        if (tmp == NULL) goto failed;
+        PyErr_Format(PyExc_TypeError, "expected some sort of mod, but got %.400s", _PyUnicode_AsString(tmp));
+failed:
+        Py_XDECREF(tmp);
+        return 1;
+}
+
+int
+obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena)
+{
+        PyObject* tmp = NULL;
+        int isinstance;
+
+        int lineno;
+        int col_offset;
+
+        if (obj == Py_None) {
+                *out = NULL;
+                return 0;
+        }
+        if (PyObject_HasAttrString(obj, "lineno")) {
+                int res;
+                tmp = PyObject_GetAttrString(obj, "lineno");
+                if (tmp == NULL) goto failed;
+                res = obj2ast_int(tmp, &lineno, arena);
+                if (res != 0) goto failed;
+                Py_XDECREF(tmp);
+                tmp = NULL;
+        } else {
+                PyErr_SetString(PyExc_TypeError, "required field \"lineno\" missing from stmt");
+                return 1;
+        }
+        if (PyObject_HasAttrString(obj, "col_offset")) {
+                int res;
+                tmp = PyObject_GetAttrString(obj, "col_offset");
+                if (tmp == NULL) goto failed;
+                res = obj2ast_int(tmp, &col_offset, arena);
+                if (res != 0) goto failed;
+                Py_XDECREF(tmp);
+                tmp = NULL;
+        } else {
+                PyErr_SetString(PyExc_TypeError, "required field \"col_offset\" missing from stmt");
+                return 1;
+        }
+        isinstance = PyObject_IsInstance(obj, (PyObject*)FunctionDef_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+                identifier name;
+                arguments_ty args;
+                asdl_seq* body;
+                asdl_seq* decorator_list;
+                string type_comment;
+
+                if (PyObject_HasAttrString(obj, "name")) {
+                        int res;
+                        tmp = PyObject_GetAttrString(obj, "name");
+                        if (tmp == NULL) goto failed;
+                        res = obj2ast_identifier(tmp, &name, arena);
+                        if (res != 0) goto failed;
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"name\" missing from FunctionDef");
+                        return 1;
+                }
+                if (PyObject_HasAttrString(obj, "args")) {
+                        int res;
+                        tmp = PyObject_GetAttrString(obj, "args");
+                        if (tmp == NULL) goto failed;
+                        res = obj2ast_arguments(tmp, &args, arena);
+                        if (res != 0) goto failed;
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"args\" missing from FunctionDef");
+                        return 1;
+                }
+                if (PyObject_HasAttrString(obj, "body")) {
+                        int res;
+                        Py_ssize_t len;
+                        Py_ssize_t i;
+                        tmp = PyObject_GetAttrString(obj, "body");
+                        if (tmp == NULL) goto failed;
+                        if (!PyList_Check(tmp)) {
+                                PyErr_Format(PyExc_TypeError, "FunctionDef field \"body\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                                goto failed;
+                        }
+                        len = PyList_GET_SIZE(tmp);
+                        body = asdl_seq_new(len, arena);
+                        if (body == NULL) goto failed;
+                        for (i = 0; i < len; i++) {
+                                stmt_ty value;
+                                res = obj2ast_stmt(PyList_GET_ITEM(tmp, i), &value, arena);
+                                if (res != 0) goto failed;
+                                asdl_seq_SET(body, i, value);
+                        }
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"body\" missing from FunctionDef");
+                        return 1;
+                }
+                if (PyObject_HasAttrString(obj, "decorator_list")) {
+                        int res;
+                        Py_ssize_t len;
+                        Py_ssize_t i;
+                        tmp = PyObject_GetAttrString(obj, "decorator_list");
+                        if (tmp == NULL) goto failed;
+                        if (!PyList_Check(tmp)) {
+                                PyErr_Format(PyExc_TypeError, "FunctionDef field \"decorator_list\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                                goto failed;
+                        }
+                        len = PyList_GET_SIZE(tmp);
+                        decorator_list = asdl_seq_new(len, arena);
+                        if (decorator_list == NULL) goto failed;
+                        for (i = 0; i < len; i++) {
+                                expr_ty value;
+                                res = obj2ast_expr(PyList_GET_ITEM(tmp, i), &value, arena);
+                                if (res != 0) goto failed;
+                                asdl_seq_SET(decorator_list, i, value);
+                        }
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"decorator_list\" missing from FunctionDef");
+                        return 1;
+                }
+                if (PyObject_HasAttrString(obj, "type_comment")) {
+                        int res;
+                        tmp = PyObject_GetAttrString(obj, "type_comment");
+                        if (tmp == NULL) goto failed;
+                        res = obj2ast_string(tmp, &type_comment, arena);
+                        if (res != 0) goto failed;
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        type_comment = NULL;
+                }
+                *out = FunctionDef(name, args, body, decorator_list, type_comment, lineno,
+                                   col_offset, arena);
+                if (*out == NULL) goto failed;
+                return 0;
+        }
+        isinstance = PyObject_IsInstance(obj, (PyObject*)ClassDef_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+                identifier name;
+                asdl_seq* bases;
+                asdl_seq* body;
+                asdl_seq* decorator_list;
+
+                if (PyObject_HasAttrString(obj, "name")) {
+                        int res;
+                        tmp = PyObject_GetAttrString(obj, "name");
+                        if (tmp == NULL) goto failed;
+                        res = obj2ast_identifier(tmp, &name, arena);
+                        if (res != 0) goto failed;
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"name\" missing from ClassDef");
+                        return 1;
+                }
+                if (PyObject_HasAttrString(obj, "bases")) {
+                        int res;
+                        Py_ssize_t len;
+                        Py_ssize_t i;
+                        tmp = PyObject_GetAttrString(obj, "bases");
+                        if (tmp == NULL) goto failed;
+                        if (!PyList_Check(tmp)) {
+                                PyErr_Format(PyExc_TypeError, "ClassDef field \"bases\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                                goto failed;
+                        }
+                        len = PyList_GET_SIZE(tmp);
+                        bases = asdl_seq_new(len, arena);
+                        if (bases == NULL) goto failed;
+                        for (i = 0; i < len; i++) {
+                                expr_ty value;
+                                res = obj2ast_expr(PyList_GET_ITEM(tmp, i), &value, arena);
+                                if (res != 0) goto failed;
+                                asdl_seq_SET(bases, i, value);
+                        }
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"bases\" missing from ClassDef");
+                        return 1;
+                }
+                if (PyObject_HasAttrString(obj, "body")) {
+                        int res;
+                        Py_ssize_t len;
+                        Py_ssize_t i;
+                        tmp = PyObject_GetAttrString(obj, "body");
+                        if (tmp == NULL) goto failed;
+                        if (!PyList_Check(tmp)) {
+                                PyErr_Format(PyExc_TypeError, "ClassDef field \"body\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                                goto failed;
+                        }
+                        len = PyList_GET_SIZE(tmp);
+                        body = asdl_seq_new(len, arena);
+                        if (body == NULL) goto failed;
+                        for (i = 0; i < len; i++) {
+                                stmt_ty value;
+                                res = obj2ast_stmt(PyList_GET_ITEM(tmp, i), &value, arena);
+                                if (res != 0) goto failed;
+                                asdl_seq_SET(body, i, value);
+                        }
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"body\" missing from ClassDef");
+                        return 1;
+                }
+                if (PyObject_HasAttrString(obj, "decorator_list")) {
+                        int res;
+                        Py_ssize_t len;
+                        Py_ssize_t i;
+                        tmp = PyObject_GetAttrString(obj, "decorator_list");
+                        if (tmp == NULL) goto failed;
+                        if (!PyList_Check(tmp)) {
+                                PyErr_Format(PyExc_TypeError, "ClassDef field \"decorator_list\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                                goto failed;
+                        }
+                        len = PyList_GET_SIZE(tmp);
+                        decorator_list = asdl_seq_new(len, arena);
+                        if (decorator_list == NULL) goto failed;
+                        for (i = 0; i < len; i++) {
+                                expr_ty value;
+                                res = obj2ast_expr(PyList_GET_ITEM(tmp, i), &value, arena);
+                                if (res != 0) goto failed;
+                                asdl_seq_SET(decorator_list, i, value);
+                        }
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"decorator_list\" missing from ClassDef");
+                        return 1;
+                }
+                *out = ClassDef(name, bases, body, decorator_list, lineno, col_offset, arena);
+                if (*out == NULL) goto failed;
+                return 0;
+        }
+        isinstance = PyObject_IsInstance(obj, (PyObject*)Return_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+                expr_ty value;
+
+                if (PyObject_HasAttrString(obj, "value")) {
+                        int res;
+                        tmp = PyObject_GetAttrString(obj, "value");
+                        if (tmp == NULL) goto failed;
+                        res = obj2ast_expr(tmp, &value, arena);
+                        if (res != 0) goto failed;
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        value = NULL;
+                }
+                *out = Return(value, lineno, col_offset, arena);
+                if (*out == NULL) goto failed;
+                return 0;
+        }
+        isinstance = PyObject_IsInstance(obj, (PyObject*)Delete_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+                asdl_seq* targets;
+
+                if (PyObject_HasAttrString(obj, "targets")) {
+                        int res;
+                        Py_ssize_t len;
+                        Py_ssize_t i;
+                        tmp = PyObject_GetAttrString(obj, "targets");
+                        if (tmp == NULL) goto failed;
+                        if (!PyList_Check(tmp)) {
+                                PyErr_Format(PyExc_TypeError, "Delete field \"targets\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                                goto failed;
+                        }
+                        len = PyList_GET_SIZE(tmp);
+                        targets = asdl_seq_new(len, arena);
+                        if (targets == NULL) goto failed;
+                        for (i = 0; i < len; i++) {
+                                expr_ty value;
+                                res = obj2ast_expr(PyList_GET_ITEM(tmp, i), &value, arena);
+                                if (res != 0) goto failed;
+                                asdl_seq_SET(targets, i, value);
+                        }
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"targets\" missing from Delete");
+                        return 1;
+                }
+                *out = Delete(targets, lineno, col_offset, arena);
+                if (*out == NULL) goto failed;
+                return 0;
+        }
+        isinstance = PyObject_IsInstance(obj, (PyObject*)Assign_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+                asdl_seq* targets;
+                expr_ty value;
+                string type_comment;
+
+                if (PyObject_HasAttrString(obj, "targets")) {
+                        int res;
+                        Py_ssize_t len;
+                        Py_ssize_t i;
+                        tmp = PyObject_GetAttrString(obj, "targets");
+                        if (tmp == NULL) goto failed;
+                        if (!PyList_Check(tmp)) {
+                                PyErr_Format(PyExc_TypeError, "Assign field \"targets\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                                goto failed;
+                        }
+                        len = PyList_GET_SIZE(tmp);
+                        targets = asdl_seq_new(len, arena);
+                        if (targets == NULL) goto failed;
+                        for (i = 0; i < len; i++) {
+                                expr_ty value;
+                                res = obj2ast_expr(PyList_GET_ITEM(tmp, i), &value, arena);
+                                if (res != 0) goto failed;
+                                asdl_seq_SET(targets, i, value);
+                        }
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"targets\" missing from Assign");
+                        return 1;
+                }
+                if (PyObject_HasAttrString(obj, "value")) {
+                        int res;
+                        tmp = PyObject_GetAttrString(obj, "value");
+                        if (tmp == NULL) goto failed;
+                        res = obj2ast_expr(tmp, &value, arena);
+                        if (res != 0) goto failed;
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"value\" missing from Assign");
+                        return 1;
+                }
+                if (PyObject_HasAttrString(obj, "type_comment")) {
+                        int res;
+                        tmp = PyObject_GetAttrString(obj, "type_comment");
+                        if (tmp == NULL) goto failed;
+                        res = obj2ast_string(tmp, &type_comment, arena);
+                        if (res != 0) goto failed;
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        type_comment = NULL;
+                }
+                *out = Assign(targets, value, type_comment, lineno, col_offset, arena);
+                if (*out == NULL) goto failed;
+                return 0;
+        }
+        isinstance = PyObject_IsInstance(obj, (PyObject*)AugAssign_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+                expr_ty target;
+                operator_ty op;
+                expr_ty value;
+
+                if (PyObject_HasAttrString(obj, "target")) {
+                        int res;
+                        tmp = PyObject_GetAttrString(obj, "target");
+                        if (tmp == NULL) goto failed;
+                        res = obj2ast_expr(tmp, &target, arena);
+                        if (res != 0) goto failed;
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"target\" missing from AugAssign");
+                        return 1;
+                }
+                if (PyObject_HasAttrString(obj, "op")) {
+                        int res;
+                        tmp = PyObject_GetAttrString(obj, "op");
+                        if (tmp == NULL) goto failed;
+                        res = obj2ast_operator(tmp, &op, arena);
+                        if (res != 0) goto failed;
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"op\" missing from AugAssign");
+                        return 1;
+                }
+                if (PyObject_HasAttrString(obj, "value")) {
+                        int res;
+                        tmp = PyObject_GetAttrString(obj, "value");
+                        if (tmp == NULL) goto failed;
+                        res = obj2ast_expr(tmp, &value, arena);
+                        if (res != 0) goto failed;
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"value\" missing from AugAssign");
+                        return 1;
+                }
+                *out = AugAssign(target, op, value, lineno, col_offset, arena);
+                if (*out == NULL) goto failed;
+                return 0;
+        }
+        isinstance = PyObject_IsInstance(obj, (PyObject*)Print_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+                expr_ty dest;
+                asdl_seq* values;
+                bool nl;
+
+                if (PyObject_HasAttrString(obj, "dest")) {
+                        int res;
+                        tmp = PyObject_GetAttrString(obj, "dest");
+                        if (tmp == NULL) goto failed;
+                        res = obj2ast_expr(tmp, &dest, arena);
+                        if (res != 0) goto failed;
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        dest = NULL;
+                }
+                if (PyObject_HasAttrString(obj, "values")) {
+                        int res;
+                        Py_ssize_t len;
+                        Py_ssize_t i;
+                        tmp = PyObject_GetAttrString(obj, "values");
+                        if (tmp == NULL) goto failed;
+                        if (!PyList_Check(tmp)) {
+                                PyErr_Format(PyExc_TypeError, "Print field \"values\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                                goto failed;
+                        }
+                        len = PyList_GET_SIZE(tmp);
+                        values = asdl_seq_new(len, arena);
+                        if (values == NULL) goto failed;
+                        for (i = 0; i < len; i++) {
+                                expr_ty value;
+                                res = obj2ast_expr(PyList_GET_ITEM(tmp, i), &value, arena);
+                                if (res != 0) goto failed;
+                                asdl_seq_SET(values, i, value);
+                        }
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"values\" missing from Print");
+                        return 1;
+                }
+                if (PyObject_HasAttrString(obj, "nl")) {
+                        int res;
+                        tmp = PyObject_GetAttrString(obj, "nl");
+                        if (tmp == NULL) goto failed;
+                        res = obj2ast_bool(tmp, &nl, arena);
+                        if (res != 0) goto failed;
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"nl\" missing from Print");
+                        return 1;
+                }
+                *out = Print(dest, values, nl, lineno, col_offset, arena);
+                if (*out == NULL) goto failed;
+                return 0;
+        }
+        isinstance = PyObject_IsInstance(obj, (PyObject*)For_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+                expr_ty target;
+                expr_ty iter;
+                asdl_seq* body;
+                asdl_seq* orelse;
+                string type_comment;
+
+                if (PyObject_HasAttrString(obj, "target")) {
+                        int res;
+                        tmp = PyObject_GetAttrString(obj, "target");
+                        if (tmp == NULL) goto failed;
+                        res = obj2ast_expr(tmp, &target, arena);
+                        if (res != 0) goto failed;
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"target\" missing from For");
+                        return 1;
+                }
+                if (PyObject_HasAttrString(obj, "iter")) {
+                        int res;
+                        tmp = PyObject_GetAttrString(obj, "iter");
+                        if (tmp == NULL) goto failed;
+                        res = obj2ast_expr(tmp, &iter, arena);
+                        if (res != 0) goto failed;
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"iter\" missing from For");
+                        return 1;
+                }
+                if (PyObject_HasAttrString(obj, "body")) {
+                        int res;
+                        Py_ssize_t len;
+                        Py_ssize_t i;
+                        tmp = PyObject_GetAttrString(obj, "body");
+                        if (tmp == NULL) goto failed;
+                        if (!PyList_Check(tmp)) {
+                                PyErr_Format(PyExc_TypeError, "For field \"body\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                                goto failed;
+                        }
+                        len = PyList_GET_SIZE(tmp);
+                        body = asdl_seq_new(len, arena);
+                        if (body == NULL) goto failed;
+                        for (i = 0; i < len; i++) {
+                                stmt_ty value;
+                                res = obj2ast_stmt(PyList_GET_ITEM(tmp, i), &value, arena);
+                                if (res != 0) goto failed;
+                                asdl_seq_SET(body, i, value);
+                        }
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"body\" missing from For");
+                        return 1;
+                }
+                if (PyObject_HasAttrString(obj, "orelse")) {
+                        int res;
+                        Py_ssize_t len;
+                        Py_ssize_t i;
+                        tmp = PyObject_GetAttrString(obj, "orelse");
+                        if (tmp == NULL) goto failed;
+                        if (!PyList_Check(tmp)) {
+                                PyErr_Format(PyExc_TypeError, "For field \"orelse\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                                goto failed;
+                        }
+                        len = PyList_GET_SIZE(tmp);
+                        orelse = asdl_seq_new(len, arena);
+                        if (orelse == NULL) goto failed;
+                        for (i = 0; i < len; i++) {
+                                stmt_ty value;
+                                res = obj2ast_stmt(PyList_GET_ITEM(tmp, i), &value, arena);
+                                if (res != 0) goto failed;
+                                asdl_seq_SET(orelse, i, value);
+                        }
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"orelse\" missing from For");
+                        return 1;
+                }
+                if (PyObject_HasAttrString(obj, "type_comment")) {
+                        int res;
+                        tmp = PyObject_GetAttrString(obj, "type_comment");
+                        if (tmp == NULL) goto failed;
+                        res = obj2ast_string(tmp, &type_comment, arena);
+                        if (res != 0) goto failed;
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        type_comment = NULL;
+                }
+                *out = For(target, iter, body, orelse, type_comment, lineno, col_offset, arena);
+                if (*out == NULL) goto failed;
+                return 0;
+        }
+        isinstance = PyObject_IsInstance(obj, (PyObject*)While_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+                expr_ty test;
+                asdl_seq* body;
+                asdl_seq* orelse;
+
+                if (PyObject_HasAttrString(obj, "test")) {
+                        int res;
+                        tmp = PyObject_GetAttrString(obj, "test");
+                        if (tmp == NULL) goto failed;
+                        res = obj2ast_expr(tmp, &test, arena);
+                        if (res != 0) goto failed;
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"test\" missing from While");
+                        return 1;
+                }
+                if (PyObject_HasAttrString(obj, "body")) {
+                        int res;
+                        Py_ssize_t len;
+                        Py_ssize_t i;
+                        tmp = PyObject_GetAttrString(obj, "body");
+                        if (tmp == NULL) goto failed;
+                        if (!PyList_Check(tmp)) {
+                                PyErr_Format(PyExc_TypeError, "While field \"body\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                                goto failed;
+                        }
+                        len = PyList_GET_SIZE(tmp);
+                        body = asdl_seq_new(len, arena);
+                        if (body == NULL) goto failed;
+                        for (i = 0; i < len; i++) {
+                                stmt_ty value;
+                                res = obj2ast_stmt(PyList_GET_ITEM(tmp, i), &value, arena);
+                                if (res != 0) goto failed;
+                                asdl_seq_SET(body, i, value);
+                        }
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"body\" missing from While");
+                        return 1;
+                }
+                if (PyObject_HasAttrString(obj, "orelse")) {
+                        int res;
+                        Py_ssize_t len;
+                        Py_ssize_t i;
+                        tmp = PyObject_GetAttrString(obj, "orelse");
+                        if (tmp == NULL) goto failed;
+                        if (!PyList_Check(tmp)) {
+                                PyErr_Format(PyExc_TypeError, "While field \"orelse\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                                goto failed;
+                        }
+                        len = PyList_GET_SIZE(tmp);
+                        orelse = asdl_seq_new(len, arena);
+                        if (orelse == NULL) goto failed;
+                        for (i = 0; i < len; i++) {
+                                stmt_ty value;
+                                res = obj2ast_stmt(PyList_GET_ITEM(tmp, i), &value, arena);
+                                if (res != 0) goto failed;
+                                asdl_seq_SET(orelse, i, value);
+                        }
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"orelse\" missing from While");
+                        return 1;
+                }
+                *out = While(test, body, orelse, lineno, col_offset, arena);
+                if (*out == NULL) goto failed;
+                return 0;
+        }
+        isinstance = PyObject_IsInstance(obj, (PyObject*)If_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+                expr_ty test;
+                asdl_seq* body;
+                asdl_seq* orelse;
+
+                if (PyObject_HasAttrString(obj, "test")) {
+                        int res;
+                        tmp = PyObject_GetAttrString(obj, "test");
+                        if (tmp == NULL) goto failed;
+                        res = obj2ast_expr(tmp, &test, arena);
+                        if (res != 0) goto failed;
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"test\" missing from If");
+                        return 1;
+                }
+                if (PyObject_HasAttrString(obj, "body")) {
+                        int res;
+                        Py_ssize_t len;
+                        Py_ssize_t i;
+                        tmp = PyObject_GetAttrString(obj, "body");
+                        if (tmp == NULL) goto failed;
+                        if (!PyList_Check(tmp)) {
+                                PyErr_Format(PyExc_TypeError, "If field \"body\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                                goto failed;
+                        }
+                        len = PyList_GET_SIZE(tmp);
+                        body = asdl_seq_new(len, arena);
+                        if (body == NULL) goto failed;
+                        for (i = 0; i < len; i++) {
+                                stmt_ty value;
+                                res = obj2ast_stmt(PyList_GET_ITEM(tmp, i), &value, arena);
+                                if (res != 0) goto failed;
+                                asdl_seq_SET(body, i, value);
+                        }
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"body\" missing from If");
+                        return 1;
+                }
+                if (PyObject_HasAttrString(obj, "orelse")) {
+                        int res;
+                        Py_ssize_t len;
+                        Py_ssize_t i;
+                        tmp = PyObject_GetAttrString(obj, "orelse");
+                        if (tmp == NULL) goto failed;
+                        if (!PyList_Check(tmp)) {
+                                PyErr_Format(PyExc_TypeError, "If field \"orelse\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                                goto failed;
+                        }
+                        len = PyList_GET_SIZE(tmp);
+                        orelse = asdl_seq_new(len, arena);
+                        if (orelse == NULL) goto failed;
+                        for (i = 0; i < len; i++) {
+                                stmt_ty value;
+                                res = obj2ast_stmt(PyList_GET_ITEM(tmp, i), &value, arena);
+                                if (res != 0) goto failed;
+                                asdl_seq_SET(orelse, i, value);
+                        }
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"orelse\" missing from If");
+                        return 1;
+                }
+                *out = If(test, body, orelse, lineno, col_offset, arena);
+                if (*out == NULL) goto failed;
+                return 0;
+        }
+        isinstance = PyObject_IsInstance(obj, (PyObject*)With_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+                expr_ty context_expr;
+                expr_ty optional_vars;
+                asdl_seq* body;
+                string type_comment;
+
+                if (PyObject_HasAttrString(obj, "context_expr")) {
+                        int res;
+                        tmp = PyObject_GetAttrString(obj, "context_expr");
+                        if (tmp == NULL) goto failed;
+                        res = obj2ast_expr(tmp, &context_expr, arena);
+                        if (res != 0) goto failed;
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"context_expr\" missing from With");
+                        return 1;
+                }
+                if (PyObject_HasAttrString(obj, "optional_vars")) {
+                        int res;
+                        tmp = PyObject_GetAttrString(obj, "optional_vars");
+                        if (tmp == NULL) goto failed;
+                        res = obj2ast_expr(tmp, &optional_vars, arena);
+                        if (res != 0) goto failed;
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        optional_vars = NULL;
+                }
+                if (PyObject_HasAttrString(obj, "body")) {
+                        int res;
+                        Py_ssize_t len;
+                        Py_ssize_t i;
+                        tmp = PyObject_GetAttrString(obj, "body");
+                        if (tmp == NULL) goto failed;
+                        if (!PyList_Check(tmp)) {
+                                PyErr_Format(PyExc_TypeError, "With field \"body\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                                goto failed;
+                        }
+                        len = PyList_GET_SIZE(tmp);
+                        body = asdl_seq_new(len, arena);
+                        if (body == NULL) goto failed;
+                        for (i = 0; i < len; i++) {
+                                stmt_ty value;
+                                res = obj2ast_stmt(PyList_GET_ITEM(tmp, i), &value, arena);
+                                if (res != 0) goto failed;
+                                asdl_seq_SET(body, i, value);
+                        }
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"body\" missing from With");
+                        return 1;
+                }
+                if (PyObject_HasAttrString(obj, "type_comment")) {
+                        int res;
+                        tmp = PyObject_GetAttrString(obj, "type_comment");
+                        if (tmp == NULL) goto failed;
+                        res = obj2ast_string(tmp, &type_comment, arena);
+                        if (res != 0) goto failed;
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        type_comment = NULL;
+                }
+                *out = With(context_expr, optional_vars, body, type_comment, lineno, col_offset,
+                            arena);
+                if (*out == NULL) goto failed;
+                return 0;
+        }
+        isinstance = PyObject_IsInstance(obj, (PyObject*)Raise_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+                expr_ty type;
+                expr_ty inst;
+                expr_ty tback;
+
+                if (PyObject_HasAttrString(obj, "type")) {
+                        int res;
+                        tmp = PyObject_GetAttrString(obj, "type");
+                        if (tmp == NULL) goto failed;
+                        res = obj2ast_expr(tmp, &type, arena);
+                        if (res != 0) goto failed;
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        type = NULL;
+                }
+                if (PyObject_HasAttrString(obj, "inst")) {
+                        int res;
+                        tmp = PyObject_GetAttrString(obj, "inst");
+                        if (tmp == NULL) goto failed;
+                        res = obj2ast_expr(tmp, &inst, arena);
+                        if (res != 0) goto failed;
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        inst = NULL;
+                }
+                if (PyObject_HasAttrString(obj, "tback")) {
+                        int res;
+                        tmp = PyObject_GetAttrString(obj, "tback");
+                        if (tmp == NULL) goto failed;
+                        res = obj2ast_expr(tmp, &tback, arena);
+                        if (res != 0) goto failed;
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        tback = NULL;
+                }
+                *out = Raise(type, inst, tback, lineno, col_offset, arena);
+                if (*out == NULL) goto failed;
+                return 0;
+        }
+        isinstance = PyObject_IsInstance(obj, (PyObject*)TryExcept_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+                asdl_seq* body;
+                asdl_seq* handlers;
+                asdl_seq* orelse;
+
+                if (PyObject_HasAttrString(obj, "body")) {
+                        int res;
+                        Py_ssize_t len;
+                        Py_ssize_t i;
+                        tmp = PyObject_GetAttrString(obj, "body");
+                        if (tmp == NULL) goto failed;
+                        if (!PyList_Check(tmp)) {
+                                PyErr_Format(PyExc_TypeError, "TryExcept field \"body\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                                goto failed;
+                        }
+                        len = PyList_GET_SIZE(tmp);
+                        body = asdl_seq_new(len, arena);
+                        if (body == NULL) goto failed;
+                        for (i = 0; i < len; i++) {
+                                stmt_ty value;
+                                res = obj2ast_stmt(PyList_GET_ITEM(tmp, i), &value, arena);
+                                if (res != 0) goto failed;
+                                asdl_seq_SET(body, i, value);
+                        }
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"body\" missing from TryExcept");
+                        return 1;
+                }
+                if (PyObject_HasAttrString(obj, "handlers")) {
+                        int res;
+                        Py_ssize_t len;
+                        Py_ssize_t i;
+                        tmp = PyObject_GetAttrString(obj, "handlers");
+                        if (tmp == NULL) goto failed;
+                        if (!PyList_Check(tmp)) {
+                                PyErr_Format(PyExc_TypeError, "TryExcept field \"handlers\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                                goto failed;
+                        }
+                        len = PyList_GET_SIZE(tmp);
+                        handlers = asdl_seq_new(len, arena);
+                        if (handlers == NULL) goto failed;
+                        for (i = 0; i < len; i++) {
+                                excepthandler_ty value;
+                                res = obj2ast_excepthandler(PyList_GET_ITEM(tmp, i), &value, arena);
+                                if (res != 0) goto failed;
+                                asdl_seq_SET(handlers, i, value);
+                        }
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"handlers\" missing from TryExcept");
+                        return 1;
+                }
+                if (PyObject_HasAttrString(obj, "orelse")) {
+                        int res;
+                        Py_ssize_t len;
+                        Py_ssize_t i;
+                        tmp = PyObject_GetAttrString(obj, "orelse");
+                        if (tmp == NULL) goto failed;
+                        if (!PyList_Check(tmp)) {
+                                PyErr_Format(PyExc_TypeError, "TryExcept field \"orelse\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                                goto failed;
+                        }
+                        len = PyList_GET_SIZE(tmp);
+                        orelse = asdl_seq_new(len, arena);
+                        if (orelse == NULL) goto failed;
+                        for (i = 0; i < len; i++) {
+                                stmt_ty value;
+                                res = obj2ast_stmt(PyList_GET_ITEM(tmp, i), &value, arena);
+                                if (res != 0) goto failed;
+                                asdl_seq_SET(orelse, i, value);
+                        }
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"orelse\" missing from TryExcept");
+                        return 1;
+                }
+                *out = TryExcept(body, handlers, orelse, lineno, col_offset, arena);
+                if (*out == NULL) goto failed;
+                return 0;
+        }
+        isinstance = PyObject_IsInstance(obj, (PyObject*)TryFinally_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+                asdl_seq* body;
+                asdl_seq* finalbody;
+
+                if (PyObject_HasAttrString(obj, "body")) {
+                        int res;
+                        Py_ssize_t len;
+                        Py_ssize_t i;
+                        tmp = PyObject_GetAttrString(obj, "body");
+                        if (tmp == NULL) goto failed;
+                        if (!PyList_Check(tmp)) {
+                                PyErr_Format(PyExc_TypeError, "TryFinally field \"body\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                                goto failed;
+                        }
+                        len = PyList_GET_SIZE(tmp);
+                        body = asdl_seq_new(len, arena);
+                        if (body == NULL) goto failed;
+                        for (i = 0; i < len; i++) {
+                                stmt_ty value;
+                                res = obj2ast_stmt(PyList_GET_ITEM(tmp, i), &value, arena);
+                                if (res != 0) goto failed;
+                                asdl_seq_SET(body, i, value);
+                        }
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"body\" missing from TryFinally");
+                        return 1;
+                }
+                if (PyObject_HasAttrString(obj, "finalbody")) {
+                        int res;
+                        Py_ssize_t len;
+                        Py_ssize_t i;
+                        tmp = PyObject_GetAttrString(obj, "finalbody");
+                        if (tmp == NULL) goto failed;
+                        if (!PyList_Check(tmp)) {
+                                PyErr_Format(PyExc_TypeError, "TryFinally field \"finalbody\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                                goto failed;
+                        }
+                        len = PyList_GET_SIZE(tmp);
+                        finalbody = asdl_seq_new(len, arena);
+                        if (finalbody == NULL) goto failed;
+                        for (i = 0; i < len; i++) {
+                                stmt_ty value;
+                                res = obj2ast_stmt(PyList_GET_ITEM(tmp, i), &value, arena);
+                                if (res != 0) goto failed;
+                                asdl_seq_SET(finalbody, i, value);
+                        }
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"finalbody\" missing from TryFinally");
+                        return 1;
+                }
+                *out = TryFinally(body, finalbody, lineno, col_offset, arena);
+                if (*out == NULL) goto failed;
+                return 0;
+        }
+        isinstance = PyObject_IsInstance(obj, (PyObject*)Assert_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+                expr_ty test;
+                expr_ty msg;
+
+                if (PyObject_HasAttrString(obj, "test")) {
+                        int res;
+                        tmp = PyObject_GetAttrString(obj, "test");
+                        if (tmp == NULL) goto failed;
+                        res = obj2ast_expr(tmp, &test, arena);
+                        if (res != 0) goto failed;
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"test\" missing from Assert");
+                        return 1;
+                }
+                if (PyObject_HasAttrString(obj, "msg")) {
+                        int res;
+                        tmp = PyObject_GetAttrString(obj, "msg");
+                        if (tmp == NULL) goto failed;
+                        res = obj2ast_expr(tmp, &msg, arena);
+                        if (res != 0) goto failed;
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        msg = NULL;
+                }
+                *out = Assert(test, msg, lineno, col_offset, arena);
+                if (*out == NULL) goto failed;
+                return 0;
+        }
+        isinstance = PyObject_IsInstance(obj, (PyObject*)Import_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+                asdl_seq* names;
+
+                if (PyObject_HasAttrString(obj, "names")) {
+                        int res;
+                        Py_ssize_t len;
+                        Py_ssize_t i;
+                        tmp = PyObject_GetAttrString(obj, "names");
+                        if (tmp == NULL) goto failed;
+                        if (!PyList_Check(tmp)) {
+                                PyErr_Format(PyExc_TypeError, "Import field \"names\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                                goto failed;
+                        }
+                        len = PyList_GET_SIZE(tmp);
+                        names = asdl_seq_new(len, arena);
+                        if (names == NULL) goto failed;
+                        for (i = 0; i < len; i++) {
+                                alias_ty value;
+                                res = obj2ast_alias(PyList_GET_ITEM(tmp, i), &value, arena);
+                                if (res != 0) goto failed;
+                                asdl_seq_SET(names, i, value);
+                        }
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"names\" missing from Import");
+                        return 1;
+                }
+                *out = Import(names, lineno, col_offset, arena);
+                if (*out == NULL) goto failed;
+                return 0;
+        }
+        isinstance = PyObject_IsInstance(obj, (PyObject*)ImportFrom_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+                identifier module;
+                asdl_seq* names;
+                int level;
+
+                if (PyObject_HasAttrString(obj, "module")) {
+                        int res;
+                        tmp = PyObject_GetAttrString(obj, "module");
+                        if (tmp == NULL) goto failed;
+                        res = obj2ast_identifier(tmp, &module, arena);
+                        if (res != 0) goto failed;
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        module = NULL;
+                }
+                if (PyObject_HasAttrString(obj, "names")) {
+                        int res;
+                        Py_ssize_t len;
+                        Py_ssize_t i;
+                        tmp = PyObject_GetAttrString(obj, "names");
+                        if (tmp == NULL) goto failed;
+                        if (!PyList_Check(tmp)) {
+                                PyErr_Format(PyExc_TypeError, "ImportFrom field \"names\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                                goto failed;
+                        }
+                        len = PyList_GET_SIZE(tmp);
+                        names = asdl_seq_new(len, arena);
+                        if (names == NULL) goto failed;
+                        for (i = 0; i < len; i++) {
+                                alias_ty value;
+                                res = obj2ast_alias(PyList_GET_ITEM(tmp, i), &value, arena);
+                                if (res != 0) goto failed;
+                                asdl_seq_SET(names, i, value);
+                        }
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"names\" missing from ImportFrom");
+                        return 1;
+                }
+                if (PyObject_HasAttrString(obj, "level")) {
+                        int res;
+                        tmp = PyObject_GetAttrString(obj, "level");
+                        if (tmp == NULL) goto failed;
+                        res = obj2ast_int(tmp, &level, arena);
+                        if (res != 0) goto failed;
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        level = 0;
+                }
+                *out = ImportFrom(module, names, level, lineno, col_offset, arena);
+                if (*out == NULL) goto failed;
+                return 0;
+        }
+        isinstance = PyObject_IsInstance(obj, (PyObject*)Exec_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+                expr_ty body;
+                expr_ty globals;
+                expr_ty locals;
+
+                if (PyObject_HasAttrString(obj, "body")) {
+                        int res;
+                        tmp = PyObject_GetAttrString(obj, "body");
+                        if (tmp == NULL) goto failed;
+                        res = obj2ast_expr(tmp, &body, arena);
+                        if (res != 0) goto failed;
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"body\" missing from Exec");
+                        return 1;
+                }
+                if (PyObject_HasAttrString(obj, "globals")) {
+                        int res;
+                        tmp = PyObject_GetAttrString(obj, "globals");
+                        if (tmp == NULL) goto failed;
+                        res = obj2ast_expr(tmp, &globals, arena);
+                        if (res != 0) goto failed;
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        globals = NULL;
+                }
+                if (PyObject_HasAttrString(obj, "locals")) {
+                        int res;
+                        tmp = PyObject_GetAttrString(obj, "locals");
+                        if (tmp == NULL) goto failed;
+                        res = obj2ast_expr(tmp, &locals, arena);
+                        if (res != 0) goto failed;
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        locals = NULL;
+                }
+                *out = Exec(body, globals, locals, lineno, col_offset, arena);
+                if (*out == NULL) goto failed;
+                return 0;
+        }
+        isinstance = PyObject_IsInstance(obj, (PyObject*)Global_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+                asdl_seq* names;
+
+                if (PyObject_HasAttrString(obj, "names")) {
+                        int res;
+                        Py_ssize_t len;
+                        Py_ssize_t i;
+                        tmp = PyObject_GetAttrString(obj, "names");
+                        if (tmp == NULL) goto failed;
+                        if (!PyList_Check(tmp)) {
+                                PyErr_Format(PyExc_TypeError, "Global field \"names\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                                goto failed;
+                        }
+                        len = PyList_GET_SIZE(tmp);
+                        names = asdl_seq_new(len, arena);
+                        if (names == NULL) goto failed;
+                        for (i = 0; i < len; i++) {
+                                identifier value;
+                                res = obj2ast_identifier(PyList_GET_ITEM(tmp, i), &value, arena);
+                                if (res != 0) goto failed;
+                                asdl_seq_SET(names, i, value);
+                        }
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"names\" missing from Global");
+                        return 1;
+                }
+                *out = Global(names, lineno, col_offset, arena);
+                if (*out == NULL) goto failed;
+                return 0;
+        }
+        isinstance = PyObject_IsInstance(obj, (PyObject*)Expr_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+                expr_ty value;
+
+                if (PyObject_HasAttrString(obj, "value")) {
+                        int res;
+                        tmp = PyObject_GetAttrString(obj, "value");
+                        if (tmp == NULL) goto failed;
+                        res = obj2ast_expr(tmp, &value, arena);
+                        if (res != 0) goto failed;
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"value\" missing from Expr");
+                        return 1;
+                }
+                *out = Expr(value, lineno, col_offset, arena);
+                if (*out == NULL) goto failed;
+                return 0;
+        }
+        isinstance = PyObject_IsInstance(obj, (PyObject*)Pass_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+
+                *out = Pass(lineno, col_offset, arena);
+                if (*out == NULL) goto failed;
+                return 0;
+        }
+        isinstance = PyObject_IsInstance(obj, (PyObject*)Break_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+
+                *out = Break(lineno, col_offset, arena);
+                if (*out == NULL) goto failed;
+                return 0;
+        }
+        isinstance = PyObject_IsInstance(obj, (PyObject*)Continue_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+
+                *out = Continue(lineno, col_offset, arena);
+                if (*out == NULL) goto failed;
+                return 0;
+        }
+
+        tmp = PyObject_Repr(obj);
+        if (tmp == NULL) goto failed;
+        PyErr_Format(PyExc_TypeError, "expected some sort of stmt, but got %.400s", _PyUnicode_AsString(tmp));
+failed:
+        Py_XDECREF(tmp);
+        return 1;
+}
+
+int
+obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena)
+{
+        PyObject* tmp = NULL;
+        int isinstance;
+
+        int lineno;
+        int col_offset;
+
+        if (obj == Py_None) {
+                *out = NULL;
+                return 0;
+        }
+        if (PyObject_HasAttrString(obj, "lineno")) {
+                int res;
+                tmp = PyObject_GetAttrString(obj, "lineno");
+                if (tmp == NULL) goto failed;
+                res = obj2ast_int(tmp, &lineno, arena);
+                if (res != 0) goto failed;
+                Py_XDECREF(tmp);
+                tmp = NULL;
+        } else {
+                PyErr_SetString(PyExc_TypeError, "required field \"lineno\" missing from expr");
+                return 1;
+        }
+        if (PyObject_HasAttrString(obj, "col_offset")) {
+                int res;
+                tmp = PyObject_GetAttrString(obj, "col_offset");
+                if (tmp == NULL) goto failed;
+                res = obj2ast_int(tmp, &col_offset, arena);
+                if (res != 0) goto failed;
+                Py_XDECREF(tmp);
+                tmp = NULL;
+        } else {
+                PyErr_SetString(PyExc_TypeError, "required field \"col_offset\" missing from expr");
+                return 1;
+        }
+        isinstance = PyObject_IsInstance(obj, (PyObject*)BoolOp_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+                boolop_ty op;
+                asdl_seq* values;
+
+                if (PyObject_HasAttrString(obj, "op")) {
+                        int res;
+                        tmp = PyObject_GetAttrString(obj, "op");
+                        if (tmp == NULL) goto failed;
+                        res = obj2ast_boolop(tmp, &op, arena);
+                        if (res != 0) goto failed;
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"op\" missing from BoolOp");
+                        return 1;
+                }
+                if (PyObject_HasAttrString(obj, "values")) {
+                        int res;
+                        Py_ssize_t len;
+                        Py_ssize_t i;
+                        tmp = PyObject_GetAttrString(obj, "values");
+                        if (tmp == NULL) goto failed;
+                        if (!PyList_Check(tmp)) {
+                                PyErr_Format(PyExc_TypeError, "BoolOp field \"values\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                                goto failed;
+                        }
+                        len = PyList_GET_SIZE(tmp);
+                        values = asdl_seq_new(len, arena);
+                        if (values == NULL) goto failed;
+                        for (i = 0; i < len; i++) {
+                                expr_ty value;
+                                res = obj2ast_expr(PyList_GET_ITEM(tmp, i), &value, arena);
+                                if (res != 0) goto failed;
+                                asdl_seq_SET(values, i, value);
+                        }
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"values\" missing from BoolOp");
+                        return 1;
+                }
+                *out = BoolOp(op, values, lineno, col_offset, arena);
+                if (*out == NULL) goto failed;
+                return 0;
+        }
+        isinstance = PyObject_IsInstance(obj, (PyObject*)BinOp_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+                expr_ty left;
+                operator_ty op;
+                expr_ty right;
+
+                if (PyObject_HasAttrString(obj, "left")) {
+                        int res;
+                        tmp = PyObject_GetAttrString(obj, "left");
+                        if (tmp == NULL) goto failed;
+                        res = obj2ast_expr(tmp, &left, arena);
+                        if (res != 0) goto failed;
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"left\" missing from BinOp");
+                        return 1;
+                }
+                if (PyObject_HasAttrString(obj, "op")) {
+                        int res;
+                        tmp = PyObject_GetAttrString(obj, "op");
+                        if (tmp == NULL) goto failed;
+                        res = obj2ast_operator(tmp, &op, arena);
+                        if (res != 0) goto failed;
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"op\" missing from BinOp");
+                        return 1;
+                }
+                if (PyObject_HasAttrString(obj, "right")) {
+                        int res;
+                        tmp = PyObject_GetAttrString(obj, "right");
+                        if (tmp == NULL) goto failed;
+                        res = obj2ast_expr(tmp, &right, arena);
+                        if (res != 0) goto failed;
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"right\" missing from BinOp");
+                        return 1;
+                }
+                *out = BinOp(left, op, right, lineno, col_offset, arena);
+                if (*out == NULL) goto failed;
+                return 0;
+        }
+        isinstance = PyObject_IsInstance(obj, (PyObject*)UnaryOp_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+                unaryop_ty op;
+                expr_ty operand;
+
+                if (PyObject_HasAttrString(obj, "op")) {
+                        int res;
+                        tmp = PyObject_GetAttrString(obj, "op");
+                        if (tmp == NULL) goto failed;
+                        res = obj2ast_unaryop(tmp, &op, arena);
+                        if (res != 0) goto failed;
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"op\" missing from UnaryOp");
+                        return 1;
+                }
+                if (PyObject_HasAttrString(obj, "operand")) {
+                        int res;
+                        tmp = PyObject_GetAttrString(obj, "operand");
+                        if (tmp == NULL) goto failed;
+                        res = obj2ast_expr(tmp, &operand, arena);
+                        if (res != 0) goto failed;
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"operand\" missing from UnaryOp");
+                        return 1;
+                }
+                *out = UnaryOp(op, operand, lineno, col_offset, arena);
+                if (*out == NULL) goto failed;
+                return 0;
+        }
+        isinstance = PyObject_IsInstance(obj, (PyObject*)Lambda_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+                arguments_ty args;
+                expr_ty body;
+
+                if (PyObject_HasAttrString(obj, "args")) {
+                        int res;
+                        tmp = PyObject_GetAttrString(obj, "args");
+                        if (tmp == NULL) goto failed;
+                        res = obj2ast_arguments(tmp, &args, arena);
+                        if (res != 0) goto failed;
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"args\" missing from Lambda");
+                        return 1;
+                }
+                if (PyObject_HasAttrString(obj, "body")) {
+                        int res;
+                        tmp = PyObject_GetAttrString(obj, "body");
+                        if (tmp == NULL) goto failed;
+                        res = obj2ast_expr(tmp, &body, arena);
+                        if (res != 0) goto failed;
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"body\" missing from Lambda");
+                        return 1;
+                }
+                *out = Lambda(args, body, lineno, col_offset, arena);
+                if (*out == NULL) goto failed;
+                return 0;
+        }
+        isinstance = PyObject_IsInstance(obj, (PyObject*)IfExp_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+                expr_ty test;
+                expr_ty body;
+                expr_ty orelse;
+
+                if (PyObject_HasAttrString(obj, "test")) {
+                        int res;
+                        tmp = PyObject_GetAttrString(obj, "test");
+                        if (tmp == NULL) goto failed;
+                        res = obj2ast_expr(tmp, &test, arena);
+                        if (res != 0) goto failed;
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"test\" missing from IfExp");
+                        return 1;
+                }
+                if (PyObject_HasAttrString(obj, "body")) {
+                        int res;
+                        tmp = PyObject_GetAttrString(obj, "body");
+                        if (tmp == NULL) goto failed;
+                        res = obj2ast_expr(tmp, &body, arena);
+                        if (res != 0) goto failed;
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"body\" missing from IfExp");
+                        return 1;
+                }
+                if (PyObject_HasAttrString(obj, "orelse")) {
+                        int res;
+                        tmp = PyObject_GetAttrString(obj, "orelse");
+                        if (tmp == NULL) goto failed;
+                        res = obj2ast_expr(tmp, &orelse, arena);
+                        if (res != 0) goto failed;
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"orelse\" missing from IfExp");
+                        return 1;
+                }
+                *out = IfExp(test, body, orelse, lineno, col_offset, arena);
+                if (*out == NULL) goto failed;
+                return 0;
+        }
+        isinstance = PyObject_IsInstance(obj, (PyObject*)Dict_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+                asdl_seq* keys;
+                asdl_seq* values;
+
+                if (PyObject_HasAttrString(obj, "keys")) {
+                        int res;
+                        Py_ssize_t len;
+                        Py_ssize_t i;
+                        tmp = PyObject_GetAttrString(obj, "keys");
+                        if (tmp == NULL) goto failed;
+                        if (!PyList_Check(tmp)) {
+                                PyErr_Format(PyExc_TypeError, "Dict field \"keys\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                                goto failed;
+                        }
+                        len = PyList_GET_SIZE(tmp);
+                        keys = asdl_seq_new(len, arena);
+                        if (keys == NULL) goto failed;
+                        for (i = 0; i < len; i++) {
+                                expr_ty value;
+                                res = obj2ast_expr(PyList_GET_ITEM(tmp, i), &value, arena);
+                                if (res != 0) goto failed;
+                                asdl_seq_SET(keys, i, value);
+                        }
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"keys\" missing from Dict");
+                        return 1;
+                }
+                if (PyObject_HasAttrString(obj, "values")) {
+                        int res;
+                        Py_ssize_t len;
+                        Py_ssize_t i;
+                        tmp = PyObject_GetAttrString(obj, "values");
+                        if (tmp == NULL) goto failed;
+                        if (!PyList_Check(tmp)) {
+                                PyErr_Format(PyExc_TypeError, "Dict field \"values\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                                goto failed;
+                        }
+                        len = PyList_GET_SIZE(tmp);
+                        values = asdl_seq_new(len, arena);
+                        if (values == NULL) goto failed;
+                        for (i = 0; i < len; i++) {
+                                expr_ty value;
+                                res = obj2ast_expr(PyList_GET_ITEM(tmp, i), &value, arena);
+                                if (res != 0) goto failed;
+                                asdl_seq_SET(values, i, value);
+                        }
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"values\" missing from Dict");
+                        return 1;
+                }
+                *out = Dict(keys, values, lineno, col_offset, arena);
+                if (*out == NULL) goto failed;
+                return 0;
+        }
+        isinstance = PyObject_IsInstance(obj, (PyObject*)Set_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+                asdl_seq* elts;
+
+                if (PyObject_HasAttrString(obj, "elts")) {
+                        int res;
+                        Py_ssize_t len;
+                        Py_ssize_t i;
+                        tmp = PyObject_GetAttrString(obj, "elts");
+                        if (tmp == NULL) goto failed;
+                        if (!PyList_Check(tmp)) {
+                                PyErr_Format(PyExc_TypeError, "Set field \"elts\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                                goto failed;
+                        }
+                        len = PyList_GET_SIZE(tmp);
+                        elts = asdl_seq_new(len, arena);
+                        if (elts == NULL) goto failed;
+                        for (i = 0; i < len; i++) {
+                                expr_ty value;
+                                res = obj2ast_expr(PyList_GET_ITEM(tmp, i), &value, arena);
+                                if (res != 0) goto failed;
+                                asdl_seq_SET(elts, i, value);
+                        }
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"elts\" missing from Set");
+                        return 1;
+                }
+                *out = Set(elts, lineno, col_offset, arena);
+                if (*out == NULL) goto failed;
+                return 0;
+        }
+        isinstance = PyObject_IsInstance(obj, (PyObject*)ListComp_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+                expr_ty elt;
+                asdl_seq* generators;
+
+                if (PyObject_HasAttrString(obj, "elt")) {
+                        int res;
+                        tmp = PyObject_GetAttrString(obj, "elt");
+                        if (tmp == NULL) goto failed;
+                        res = obj2ast_expr(tmp, &elt, arena);
+                        if (res != 0) goto failed;
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"elt\" missing from ListComp");
+                        return 1;
+                }
+                if (PyObject_HasAttrString(obj, "generators")) {
+                        int res;
+                        Py_ssize_t len;
+                        Py_ssize_t i;
+                        tmp = PyObject_GetAttrString(obj, "generators");
+                        if (tmp == NULL) goto failed;
+                        if (!PyList_Check(tmp)) {
+                                PyErr_Format(PyExc_TypeError, "ListComp field \"generators\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                                goto failed;
+                        }
+                        len = PyList_GET_SIZE(tmp);
+                        generators = asdl_seq_new(len, arena);
+                        if (generators == NULL) goto failed;
+                        for (i = 0; i < len; i++) {
+                                comprehension_ty value;
+                                res = obj2ast_comprehension(PyList_GET_ITEM(tmp, i), &value, arena);
+                                if (res != 0) goto failed;
+                                asdl_seq_SET(generators, i, value);
+                        }
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"generators\" missing from ListComp");
+                        return 1;
+                }
+                *out = ListComp(elt, generators, lineno, col_offset, arena);
+                if (*out == NULL) goto failed;
+                return 0;
+        }
+        isinstance = PyObject_IsInstance(obj, (PyObject*)SetComp_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+                expr_ty elt;
+                asdl_seq* generators;
+
+                if (PyObject_HasAttrString(obj, "elt")) {
+                        int res;
+                        tmp = PyObject_GetAttrString(obj, "elt");
+                        if (tmp == NULL) goto failed;
+                        res = obj2ast_expr(tmp, &elt, arena);
+                        if (res != 0) goto failed;
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"elt\" missing from SetComp");
+                        return 1;
+                }
+                if (PyObject_HasAttrString(obj, "generators")) {
+                        int res;
+                        Py_ssize_t len;
+                        Py_ssize_t i;
+                        tmp = PyObject_GetAttrString(obj, "generators");
+                        if (tmp == NULL) goto failed;
+                        if (!PyList_Check(tmp)) {
+                                PyErr_Format(PyExc_TypeError, "SetComp field \"generators\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                                goto failed;
+                        }
+                        len = PyList_GET_SIZE(tmp);
+                        generators = asdl_seq_new(len, arena);
+                        if (generators == NULL) goto failed;
+                        for (i = 0; i < len; i++) {
+                                comprehension_ty value;
+                                res = obj2ast_comprehension(PyList_GET_ITEM(tmp, i), &value, arena);
+                                if (res != 0) goto failed;
+                                asdl_seq_SET(generators, i, value);
+                        }
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"generators\" missing from SetComp");
+                        return 1;
+                }
+                *out = SetComp(elt, generators, lineno, col_offset, arena);
+                if (*out == NULL) goto failed;
+                return 0;
+        }
+        isinstance = PyObject_IsInstance(obj, (PyObject*)DictComp_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+                expr_ty key;
+                expr_ty value;
+                asdl_seq* generators;
+
+                if (PyObject_HasAttrString(obj, "key")) {
+                        int res;
+                        tmp = PyObject_GetAttrString(obj, "key");
+                        if (tmp == NULL) goto failed;
+                        res = obj2ast_expr(tmp, &key, arena);
+                        if (res != 0) goto failed;
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"key\" missing from DictComp");
+                        return 1;
+                }
+                if (PyObject_HasAttrString(obj, "value")) {
+                        int res;
+                        tmp = PyObject_GetAttrString(obj, "value");
+                        if (tmp == NULL) goto failed;
+                        res = obj2ast_expr(tmp, &value, arena);
+                        if (res != 0) goto failed;
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"value\" missing from DictComp");
+                        return 1;
+                }
+                if (PyObject_HasAttrString(obj, "generators")) {
+                        int res;
+                        Py_ssize_t len;
+                        Py_ssize_t i;
+                        tmp = PyObject_GetAttrString(obj, "generators");
+                        if (tmp == NULL) goto failed;
+                        if (!PyList_Check(tmp)) {
+                                PyErr_Format(PyExc_TypeError, "DictComp field \"generators\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                                goto failed;
+                        }
+                        len = PyList_GET_SIZE(tmp);
+                        generators = asdl_seq_new(len, arena);
+                        if (generators == NULL) goto failed;
+                        for (i = 0; i < len; i++) {
+                                comprehension_ty value;
+                                res = obj2ast_comprehension(PyList_GET_ITEM(tmp, i), &value, arena);
+                                if (res != 0) goto failed;
+                                asdl_seq_SET(generators, i, value);
+                        }
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"generators\" missing from DictComp");
+                        return 1;
+                }
+                *out = DictComp(key, value, generators, lineno, col_offset, arena);
+                if (*out == NULL) goto failed;
+                return 0;
+        }
+        isinstance = PyObject_IsInstance(obj, (PyObject*)GeneratorExp_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+                expr_ty elt;
+                asdl_seq* generators;
+
+                if (PyObject_HasAttrString(obj, "elt")) {
+                        int res;
+                        tmp = PyObject_GetAttrString(obj, "elt");
+                        if (tmp == NULL) goto failed;
+                        res = obj2ast_expr(tmp, &elt, arena);
+                        if (res != 0) goto failed;
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"elt\" missing from GeneratorExp");
+                        return 1;
+                }
+                if (PyObject_HasAttrString(obj, "generators")) {
+                        int res;
+                        Py_ssize_t len;
+                        Py_ssize_t i;
+                        tmp = PyObject_GetAttrString(obj, "generators");
+                        if (tmp == NULL) goto failed;
+                        if (!PyList_Check(tmp)) {
+                                PyErr_Format(PyExc_TypeError, "GeneratorExp field \"generators\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                                goto failed;
+                        }
+                        len = PyList_GET_SIZE(tmp);
+                        generators = asdl_seq_new(len, arena);
+                        if (generators == NULL) goto failed;
+                        for (i = 0; i < len; i++) {
+                                comprehension_ty value;
+                                res = obj2ast_comprehension(PyList_GET_ITEM(tmp, i), &value, arena);
+                                if (res != 0) goto failed;
+                                asdl_seq_SET(generators, i, value);
+                        }
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"generators\" missing from GeneratorExp");
+                        return 1;
+                }
+                *out = GeneratorExp(elt, generators, lineno, col_offset, arena);
+                if (*out == NULL) goto failed;
+                return 0;
+        }
+        isinstance = PyObject_IsInstance(obj, (PyObject*)Yield_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+                expr_ty value;
+
+                if (PyObject_HasAttrString(obj, "value")) {
+                        int res;
+                        tmp = PyObject_GetAttrString(obj, "value");
+                        if (tmp == NULL) goto failed;
+                        res = obj2ast_expr(tmp, &value, arena);
+                        if (res != 0) goto failed;
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        value = NULL;
+                }
+                *out = Yield(value, lineno, col_offset, arena);
+                if (*out == NULL) goto failed;
+                return 0;
+        }
+        isinstance = PyObject_IsInstance(obj, (PyObject*)Compare_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+                expr_ty left;
+                asdl_int_seq* ops;
+                asdl_seq* comparators;
+
+                if (PyObject_HasAttrString(obj, "left")) {
+                        int res;
+                        tmp = PyObject_GetAttrString(obj, "left");
+                        if (tmp == NULL) goto failed;
+                        res = obj2ast_expr(tmp, &left, arena);
+                        if (res != 0) goto failed;
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"left\" missing from Compare");
+                        return 1;
+                }
+                if (PyObject_HasAttrString(obj, "ops")) {
+                        int res;
+                        Py_ssize_t len;
+                        Py_ssize_t i;
+                        tmp = PyObject_GetAttrString(obj, "ops");
+                        if (tmp == NULL) goto failed;
+                        if (!PyList_Check(tmp)) {
+                                PyErr_Format(PyExc_TypeError, "Compare field \"ops\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                                goto failed;
+                        }
+                        len = PyList_GET_SIZE(tmp);
+                        ops = asdl_int_seq_new(len, arena);
+                        if (ops == NULL) goto failed;
+                        for (i = 0; i < len; i++) {
+                                cmpop_ty value;
+                                res = obj2ast_cmpop(PyList_GET_ITEM(tmp, i), &value, arena);
+                                if (res != 0) goto failed;
+                                asdl_seq_SET(ops, i, value);
+                        }
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"ops\" missing from Compare");
+                        return 1;
+                }
+                if (PyObject_HasAttrString(obj, "comparators")) {
+                        int res;
+                        Py_ssize_t len;
+                        Py_ssize_t i;
+                        tmp = PyObject_GetAttrString(obj, "comparators");
+                        if (tmp == NULL) goto failed;
+                        if (!PyList_Check(tmp)) {
+                                PyErr_Format(PyExc_TypeError, "Compare field \"comparators\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                                goto failed;
+                        }
+                        len = PyList_GET_SIZE(tmp);
+                        comparators = asdl_seq_new(len, arena);
+                        if (comparators == NULL) goto failed;
+                        for (i = 0; i < len; i++) {
+                                expr_ty value;
+                                res = obj2ast_expr(PyList_GET_ITEM(tmp, i), &value, arena);
+                                if (res != 0) goto failed;
+                                asdl_seq_SET(comparators, i, value);
+                        }
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"comparators\" missing from Compare");
+                        return 1;
+                }
+                *out = Compare(left, ops, comparators, lineno, col_offset, arena);
+                if (*out == NULL) goto failed;
+                return 0;
+        }
+        isinstance = PyObject_IsInstance(obj, (PyObject*)Call_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+                expr_ty func;
+                asdl_seq* args;
+                asdl_seq* keywords;
+                expr_ty starargs;
+                expr_ty kwargs;
+
+                if (PyObject_HasAttrString(obj, "func")) {
+                        int res;
+                        tmp = PyObject_GetAttrString(obj, "func");
+                        if (tmp == NULL) goto failed;
+                        res = obj2ast_expr(tmp, &func, arena);
+                        if (res != 0) goto failed;
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"func\" missing from Call");
+                        return 1;
+                }
+                if (PyObject_HasAttrString(obj, "args")) {
+                        int res;
+                        Py_ssize_t len;
+                        Py_ssize_t i;
+                        tmp = PyObject_GetAttrString(obj, "args");
+                        if (tmp == NULL) goto failed;
+                        if (!PyList_Check(tmp)) {
+                                PyErr_Format(PyExc_TypeError, "Call field \"args\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                                goto failed;
+                        }
+                        len = PyList_GET_SIZE(tmp);
+                        args = asdl_seq_new(len, arena);
+                        if (args == NULL) goto failed;
+                        for (i = 0; i < len; i++) {
+                                expr_ty value;
+                                res = obj2ast_expr(PyList_GET_ITEM(tmp, i), &value, arena);
+                                if (res != 0) goto failed;
+                                asdl_seq_SET(args, i, value);
+                        }
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"args\" missing from Call");
+                        return 1;
+                }
+                if (PyObject_HasAttrString(obj, "keywords")) {
+                        int res;
+                        Py_ssize_t len;
+                        Py_ssize_t i;
+                        tmp = PyObject_GetAttrString(obj, "keywords");
+                        if (tmp == NULL) goto failed;
+                        if (!PyList_Check(tmp)) {
+                                PyErr_Format(PyExc_TypeError, "Call field \"keywords\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                                goto failed;
+                        }
+                        len = PyList_GET_SIZE(tmp);
+                        keywords = asdl_seq_new(len, arena);
+                        if (keywords == NULL) goto failed;
+                        for (i = 0; i < len; i++) {
+                                keyword_ty value;
+                                res = obj2ast_keyword(PyList_GET_ITEM(tmp, i), &value, arena);
+                                if (res != 0) goto failed;
+                                asdl_seq_SET(keywords, i, value);
+                        }
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"keywords\" missing from Call");
+                        return 1;
+                }
+                if (PyObject_HasAttrString(obj, "starargs")) {
+                        int res;
+                        tmp = PyObject_GetAttrString(obj, "starargs");
+                        if (tmp == NULL) goto failed;
+                        res = obj2ast_expr(tmp, &starargs, arena);
+                        if (res != 0) goto failed;
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        starargs = NULL;
+                }
+                if (PyObject_HasAttrString(obj, "kwargs")) {
+                        int res;
+                        tmp = PyObject_GetAttrString(obj, "kwargs");
+                        if (tmp == NULL) goto failed;
+                        res = obj2ast_expr(tmp, &kwargs, arena);
+                        if (res != 0) goto failed;
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        kwargs = NULL;
+                }
+                *out = Call(func, args, keywords, starargs, kwargs, lineno, col_offset, arena);
+                if (*out == NULL) goto failed;
+                return 0;
+        }
+        isinstance = PyObject_IsInstance(obj, (PyObject*)Repr_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+                expr_ty value;
+
+                if (PyObject_HasAttrString(obj, "value")) {
+                        int res;
+                        tmp = PyObject_GetAttrString(obj, "value");
+                        if (tmp == NULL) goto failed;
+                        res = obj2ast_expr(tmp, &value, arena);
+                        if (res != 0) goto failed;
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"value\" missing from Repr");
+                        return 1;
+                }
+                *out = Repr(value, lineno, col_offset, arena);
+                if (*out == NULL) goto failed;
+                return 0;
+        }
+        isinstance = PyObject_IsInstance(obj, (PyObject*)Num_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+                object n;
+
+                if (PyObject_HasAttrString(obj, "n")) {
+                        int res;
+                        tmp = PyObject_GetAttrString(obj, "n");
+                        if (tmp == NULL) goto failed;
+                        res = obj2ast_object(tmp, &n, arena);
+                        if (res != 0) goto failed;
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"n\" missing from Num");
+                        return 1;
+                }
+                *out = Num(n, lineno, col_offset, arena);
+                if (*out == NULL) goto failed;
+                return 0;
+        }
+        isinstance = PyObject_IsInstance(obj, (PyObject*)Str_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+                string s;
+
+                if (PyObject_HasAttrString(obj, "s")) {
+                        int res;
+                        tmp = PyObject_GetAttrString(obj, "s");
+                        if (tmp == NULL) goto failed;
+                        res = obj2ast_string(tmp, &s, arena);
+                        if (res != 0) goto failed;
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"s\" missing from Str");
+                        return 1;
+                }
+                *out = Str(s, lineno, col_offset, arena);
+                if (*out == NULL) goto failed;
+                return 0;
+        }
+        isinstance = PyObject_IsInstance(obj, (PyObject*)Attribute_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+                expr_ty value;
+                identifier attr;
+                expr_context_ty ctx;
+
+                if (PyObject_HasAttrString(obj, "value")) {
+                        int res;
+                        tmp = PyObject_GetAttrString(obj, "value");
+                        if (tmp == NULL) goto failed;
+                        res = obj2ast_expr(tmp, &value, arena);
+                        if (res != 0) goto failed;
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"value\" missing from Attribute");
+                        return 1;
+                }
+                if (PyObject_HasAttrString(obj, "attr")) {
+                        int res;
+                        tmp = PyObject_GetAttrString(obj, "attr");
+                        if (tmp == NULL) goto failed;
+                        res = obj2ast_identifier(tmp, &attr, arena);
+                        if (res != 0) goto failed;
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"attr\" missing from Attribute");
+                        return 1;
+                }
+                if (PyObject_HasAttrString(obj, "ctx")) {
+                        int res;
+                        tmp = PyObject_GetAttrString(obj, "ctx");
+                        if (tmp == NULL) goto failed;
+                        res = obj2ast_expr_context(tmp, &ctx, arena);
+                        if (res != 0) goto failed;
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"ctx\" missing from Attribute");
+                        return 1;
+                }
+                *out = Attribute(value, attr, ctx, lineno, col_offset, arena);
+                if (*out == NULL) goto failed;
+                return 0;
+        }
+        isinstance = PyObject_IsInstance(obj, (PyObject*)Subscript_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+                expr_ty value;
+                slice_ty slice;
+                expr_context_ty ctx;
+
+                if (PyObject_HasAttrString(obj, "value")) {
+                        int res;
+                        tmp = PyObject_GetAttrString(obj, "value");
+                        if (tmp == NULL) goto failed;
+                        res = obj2ast_expr(tmp, &value, arena);
+                        if (res != 0) goto failed;
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"value\" missing from Subscript");
+                        return 1;
+                }
+                if (PyObject_HasAttrString(obj, "slice")) {
+                        int res;
+                        tmp = PyObject_GetAttrString(obj, "slice");
+                        if (tmp == NULL) goto failed;
+                        res = obj2ast_slice(tmp, &slice, arena);
+                        if (res != 0) goto failed;
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"slice\" missing from Subscript");
+                        return 1;
+                }
+                if (PyObject_HasAttrString(obj, "ctx")) {
+                        int res;
+                        tmp = PyObject_GetAttrString(obj, "ctx");
+                        if (tmp == NULL) goto failed;
+                        res = obj2ast_expr_context(tmp, &ctx, arena);
+                        if (res != 0) goto failed;
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"ctx\" missing from Subscript");
+                        return 1;
+                }
+                *out = Subscript(value, slice, ctx, lineno, col_offset, arena);
+                if (*out == NULL) goto failed;
+                return 0;
+        }
+        isinstance = PyObject_IsInstance(obj, (PyObject*)Name_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+                identifier id;
+                expr_context_ty ctx;
+
+                if (PyObject_HasAttrString(obj, "id")) {
+                        int res;
+                        tmp = PyObject_GetAttrString(obj, "id");
+                        if (tmp == NULL) goto failed;
+                        res = obj2ast_identifier(tmp, &id, arena);
+                        if (res != 0) goto failed;
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"id\" missing from Name");
+                        return 1;
+                }
+                if (PyObject_HasAttrString(obj, "ctx")) {
+                        int res;
+                        tmp = PyObject_GetAttrString(obj, "ctx");
+                        if (tmp == NULL) goto failed;
+                        res = obj2ast_expr_context(tmp, &ctx, arena);
+                        if (res != 0) goto failed;
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"ctx\" missing from Name");
+                        return 1;
+                }
+                *out = Name(id, ctx, lineno, col_offset, arena);
+                if (*out == NULL) goto failed;
+                return 0;
+        }
+        isinstance = PyObject_IsInstance(obj, (PyObject*)List_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+                asdl_seq* elts;
+                expr_context_ty ctx;
+
+                if (PyObject_HasAttrString(obj, "elts")) {
+                        int res;
+                        Py_ssize_t len;
+                        Py_ssize_t i;
+                        tmp = PyObject_GetAttrString(obj, "elts");
+                        if (tmp == NULL) goto failed;
+                        if (!PyList_Check(tmp)) {
+                                PyErr_Format(PyExc_TypeError, "List field \"elts\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                                goto failed;
+                        }
+                        len = PyList_GET_SIZE(tmp);
+                        elts = asdl_seq_new(len, arena);
+                        if (elts == NULL) goto failed;
+                        for (i = 0; i < len; i++) {
+                                expr_ty value;
+                                res = obj2ast_expr(PyList_GET_ITEM(tmp, i), &value, arena);
+                                if (res != 0) goto failed;
+                                asdl_seq_SET(elts, i, value);
+                        }
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"elts\" missing from List");
+                        return 1;
+                }
+                if (PyObject_HasAttrString(obj, "ctx")) {
+                        int res;
+                        tmp = PyObject_GetAttrString(obj, "ctx");
+                        if (tmp == NULL) goto failed;
+                        res = obj2ast_expr_context(tmp, &ctx, arena);
+                        if (res != 0) goto failed;
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"ctx\" missing from List");
+                        return 1;
+                }
+                *out = List(elts, ctx, lineno, col_offset, arena);
+                if (*out == NULL) goto failed;
+                return 0;
+        }
+        isinstance = PyObject_IsInstance(obj, (PyObject*)Tuple_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+                asdl_seq* elts;
+                expr_context_ty ctx;
+
+                if (PyObject_HasAttrString(obj, "elts")) {
+                        int res;
+                        Py_ssize_t len;
+                        Py_ssize_t i;
+                        tmp = PyObject_GetAttrString(obj, "elts");
+                        if (tmp == NULL) goto failed;
+                        if (!PyList_Check(tmp)) {
+                                PyErr_Format(PyExc_TypeError, "Tuple field \"elts\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                                goto failed;
+                        }
+                        len = PyList_GET_SIZE(tmp);
+                        elts = asdl_seq_new(len, arena);
+                        if (elts == NULL) goto failed;
+                        for (i = 0; i < len; i++) {
+                                expr_ty value;
+                                res = obj2ast_expr(PyList_GET_ITEM(tmp, i), &value, arena);
+                                if (res != 0) goto failed;
+                                asdl_seq_SET(elts, i, value);
+                        }
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"elts\" missing from Tuple");
+                        return 1;
+                }
+                if (PyObject_HasAttrString(obj, "ctx")) {
+                        int res;
+                        tmp = PyObject_GetAttrString(obj, "ctx");
+                        if (tmp == NULL) goto failed;
+                        res = obj2ast_expr_context(tmp, &ctx, arena);
+                        if (res != 0) goto failed;
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"ctx\" missing from Tuple");
+                        return 1;
+                }
+                *out = Tuple(elts, ctx, lineno, col_offset, arena);
+                if (*out == NULL) goto failed;
+                return 0;
+        }
+
+        tmp = PyObject_Repr(obj);
+        if (tmp == NULL) goto failed;
+        PyErr_Format(PyExc_TypeError, "expected some sort of expr, but got %.400s", _PyUnicode_AsString(tmp));
+failed:
+        Py_XDECREF(tmp);
+        return 1;
+}
+
+int
+obj2ast_expr_context(PyObject* obj, expr_context_ty* out, PyArena* arena)
+{
+        PyObject* tmp = NULL;
+        int isinstance;
+
+        isinstance = PyObject_IsInstance(obj, (PyObject *)Load_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+                *out = Load;
+                return 0;
+        }
+        isinstance = PyObject_IsInstance(obj, (PyObject *)Store_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+                *out = Store;
+                return 0;
+        }
+        isinstance = PyObject_IsInstance(obj, (PyObject *)Del_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+                *out = Del;
+                return 0;
+        }
+        isinstance = PyObject_IsInstance(obj, (PyObject *)AugLoad_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+                *out = AugLoad;
+                return 0;
+        }
+        isinstance = PyObject_IsInstance(obj, (PyObject *)AugStore_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+                *out = AugStore;
+                return 0;
+        }
+        isinstance = PyObject_IsInstance(obj, (PyObject *)Param_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+                *out = Param;
+                return 0;
+        }
+
+        tmp = PyObject_Repr(obj);
+        if (tmp == NULL) goto failed;
+        PyErr_Format(PyExc_TypeError, "expected some sort of expr_context, but got %.400s", _PyUnicode_AsString(tmp));
+failed:
+        Py_XDECREF(tmp);
+        return 1;
+}
+
+int
+obj2ast_slice(PyObject* obj, slice_ty* out, PyArena* arena)
+{
+        PyObject* tmp = NULL;
+        int isinstance;
+
+
+        if (obj == Py_None) {
+                *out = NULL;
+                return 0;
+        }
+        isinstance = PyObject_IsInstance(obj, (PyObject*)Ellipsis_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+
+                *out = Ellipsis(arena);
+                if (*out == NULL) goto failed;
+                return 0;
+        }
+        isinstance = PyObject_IsInstance(obj, (PyObject*)Slice_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+                expr_ty lower;
+                expr_ty upper;
+                expr_ty step;
+
+                if (PyObject_HasAttrString(obj, "lower")) {
+                        int res;
+                        tmp = PyObject_GetAttrString(obj, "lower");
+                        if (tmp == NULL) goto failed;
+                        res = obj2ast_expr(tmp, &lower, arena);
+                        if (res != 0) goto failed;
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        lower = NULL;
+                }
+                if (PyObject_HasAttrString(obj, "upper")) {
+                        int res;
+                        tmp = PyObject_GetAttrString(obj, "upper");
+                        if (tmp == NULL) goto failed;
+                        res = obj2ast_expr(tmp, &upper, arena);
+                        if (res != 0) goto failed;
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        upper = NULL;
+                }
+                if (PyObject_HasAttrString(obj, "step")) {
+                        int res;
+                        tmp = PyObject_GetAttrString(obj, "step");
+                        if (tmp == NULL) goto failed;
+                        res = obj2ast_expr(tmp, &step, arena);
+                        if (res != 0) goto failed;
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        step = NULL;
+                }
+                *out = Slice(lower, upper, step, arena);
+                if (*out == NULL) goto failed;
+                return 0;
+        }
+        isinstance = PyObject_IsInstance(obj, (PyObject*)ExtSlice_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+                asdl_seq* dims;
+
+                if (PyObject_HasAttrString(obj, "dims")) {
+                        int res;
+                        Py_ssize_t len;
+                        Py_ssize_t i;
+                        tmp = PyObject_GetAttrString(obj, "dims");
+                        if (tmp == NULL) goto failed;
+                        if (!PyList_Check(tmp)) {
+                                PyErr_Format(PyExc_TypeError, "ExtSlice field \"dims\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                                goto failed;
+                        }
+                        len = PyList_GET_SIZE(tmp);
+                        dims = asdl_seq_new(len, arena);
+                        if (dims == NULL) goto failed;
+                        for (i = 0; i < len; i++) {
+                                slice_ty value;
+                                res = obj2ast_slice(PyList_GET_ITEM(tmp, i), &value, arena);
+                                if (res != 0) goto failed;
+                                asdl_seq_SET(dims, i, value);
+                        }
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"dims\" missing from ExtSlice");
+                        return 1;
+                }
+                *out = ExtSlice(dims, arena);
+                if (*out == NULL) goto failed;
+                return 0;
+        }
+        isinstance = PyObject_IsInstance(obj, (PyObject*)Index_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+                expr_ty value;
+
+                if (PyObject_HasAttrString(obj, "value")) {
+                        int res;
+                        tmp = PyObject_GetAttrString(obj, "value");
+                        if (tmp == NULL) goto failed;
+                        res = obj2ast_expr(tmp, &value, arena);
+                        if (res != 0) goto failed;
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"value\" missing from Index");
+                        return 1;
+                }
+                *out = Index(value, arena);
+                if (*out == NULL) goto failed;
+                return 0;
+        }
+
+        tmp = PyObject_Repr(obj);
+        if (tmp == NULL) goto failed;
+        PyErr_Format(PyExc_TypeError, "expected some sort of slice, but got %.400s", _PyUnicode_AsString(tmp));
+failed:
+        Py_XDECREF(tmp);
+        return 1;
+}
+
+int
+obj2ast_boolop(PyObject* obj, boolop_ty* out, PyArena* arena)
+{
+        PyObject* tmp = NULL;
+        int isinstance;
+
+        isinstance = PyObject_IsInstance(obj, (PyObject *)And_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+                *out = And;
+                return 0;
+        }
+        isinstance = PyObject_IsInstance(obj, (PyObject *)Or_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+                *out = Or;
+                return 0;
+        }
+
+        tmp = PyObject_Repr(obj);
+        if (tmp == NULL) goto failed;
+        PyErr_Format(PyExc_TypeError, "expected some sort of boolop, but got %.400s", _PyUnicode_AsString(tmp));
+failed:
+        Py_XDECREF(tmp);
+        return 1;
+}
+
+int
+obj2ast_operator(PyObject* obj, operator_ty* out, PyArena* arena)
+{
+        PyObject* tmp = NULL;
+        int isinstance;
+
+        isinstance = PyObject_IsInstance(obj, (PyObject *)Add_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+                *out = Add;
+                return 0;
+        }
+        isinstance = PyObject_IsInstance(obj, (PyObject *)Sub_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+                *out = Sub;
+                return 0;
+        }
+        isinstance = PyObject_IsInstance(obj, (PyObject *)Mult_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+                *out = Mult;
+                return 0;
+        }
+        isinstance = PyObject_IsInstance(obj, (PyObject *)Div_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+                *out = Div;
+                return 0;
+        }
+        isinstance = PyObject_IsInstance(obj, (PyObject *)Mod_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+                *out = Mod;
+                return 0;
+        }
+        isinstance = PyObject_IsInstance(obj, (PyObject *)Pow_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+                *out = Pow;
+                return 0;
+        }
+        isinstance = PyObject_IsInstance(obj, (PyObject *)LShift_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+                *out = LShift;
+                return 0;
+        }
+        isinstance = PyObject_IsInstance(obj, (PyObject *)RShift_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+                *out = RShift;
+                return 0;
+        }
+        isinstance = PyObject_IsInstance(obj, (PyObject *)BitOr_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+                *out = BitOr;
+                return 0;
+        }
+        isinstance = PyObject_IsInstance(obj, (PyObject *)BitXor_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+                *out = BitXor;
+                return 0;
+        }
+        isinstance = PyObject_IsInstance(obj, (PyObject *)BitAnd_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+                *out = BitAnd;
+                return 0;
+        }
+        isinstance = PyObject_IsInstance(obj, (PyObject *)FloorDiv_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+                *out = FloorDiv;
+                return 0;
+        }
+
+        tmp = PyObject_Repr(obj);
+        if (tmp == NULL) goto failed;
+        PyErr_Format(PyExc_TypeError, "expected some sort of operator, but got %.400s", _PyUnicode_AsString(tmp));
+failed:
+        Py_XDECREF(tmp);
+        return 1;
+}
+
+int
+obj2ast_unaryop(PyObject* obj, unaryop_ty* out, PyArena* arena)
+{
+        PyObject* tmp = NULL;
+        int isinstance;
+
+        isinstance = PyObject_IsInstance(obj, (PyObject *)Invert_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+                *out = Invert;
+                return 0;
+        }
+        isinstance = PyObject_IsInstance(obj, (PyObject *)Not_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+                *out = Not;
+                return 0;
+        }
+        isinstance = PyObject_IsInstance(obj, (PyObject *)UAdd_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+                *out = UAdd;
+                return 0;
+        }
+        isinstance = PyObject_IsInstance(obj, (PyObject *)USub_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+                *out = USub;
+                return 0;
+        }
+
+        tmp = PyObject_Repr(obj);
+        if (tmp == NULL) goto failed;
+        PyErr_Format(PyExc_TypeError, "expected some sort of unaryop, but got %.400s", _PyUnicode_AsString(tmp));
+failed:
+        Py_XDECREF(tmp);
+        return 1;
+}
+
+int
+obj2ast_cmpop(PyObject* obj, cmpop_ty* out, PyArena* arena)
+{
+        PyObject* tmp = NULL;
+        int isinstance;
+
+        isinstance = PyObject_IsInstance(obj, (PyObject *)Eq_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+                *out = Eq;
+                return 0;
+        }
+        isinstance = PyObject_IsInstance(obj, (PyObject *)NotEq_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+                *out = NotEq;
+                return 0;
+        }
+        isinstance = PyObject_IsInstance(obj, (PyObject *)Lt_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+                *out = Lt;
+                return 0;
+        }
+        isinstance = PyObject_IsInstance(obj, (PyObject *)LtE_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+                *out = LtE;
+                return 0;
+        }
+        isinstance = PyObject_IsInstance(obj, (PyObject *)Gt_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+                *out = Gt;
+                return 0;
+        }
+        isinstance = PyObject_IsInstance(obj, (PyObject *)GtE_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+                *out = GtE;
+                return 0;
+        }
+        isinstance = PyObject_IsInstance(obj, (PyObject *)Is_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+                *out = Is;
+                return 0;
+        }
+        isinstance = PyObject_IsInstance(obj, (PyObject *)IsNot_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+                *out = IsNot;
+                return 0;
+        }
+        isinstance = PyObject_IsInstance(obj, (PyObject *)In_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+                *out = In;
+                return 0;
+        }
+        isinstance = PyObject_IsInstance(obj, (PyObject *)NotIn_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+                *out = NotIn;
+                return 0;
+        }
+
+        tmp = PyObject_Repr(obj);
+        if (tmp == NULL) goto failed;
+        PyErr_Format(PyExc_TypeError, "expected some sort of cmpop, but got %.400s", _PyUnicode_AsString(tmp));
+failed:
+        Py_XDECREF(tmp);
+        return 1;
+}
+
+int
+obj2ast_comprehension(PyObject* obj, comprehension_ty* out, PyArena* arena)
+{
+        PyObject* tmp = NULL;
+        expr_ty target;
+        expr_ty iter;
+        asdl_seq* ifs;
+
+        if (PyObject_HasAttrString(obj, "target")) {
+                int res;
+                tmp = PyObject_GetAttrString(obj, "target");
+                if (tmp == NULL) goto failed;
+                res = obj2ast_expr(tmp, &target, arena);
+                if (res != 0) goto failed;
+                Py_XDECREF(tmp);
+                tmp = NULL;
+        } else {
+                PyErr_SetString(PyExc_TypeError, "required field \"target\" missing from comprehension");
+                return 1;
+        }
+        if (PyObject_HasAttrString(obj, "iter")) {
+                int res;
+                tmp = PyObject_GetAttrString(obj, "iter");
+                if (tmp == NULL) goto failed;
+                res = obj2ast_expr(tmp, &iter, arena);
+                if (res != 0) goto failed;
+                Py_XDECREF(tmp);
+                tmp = NULL;
+        } else {
+                PyErr_SetString(PyExc_TypeError, "required field \"iter\" missing from comprehension");
+                return 1;
+        }
+        if (PyObject_HasAttrString(obj, "ifs")) {
+                int res;
+                Py_ssize_t len;
+                Py_ssize_t i;
+                tmp = PyObject_GetAttrString(obj, "ifs");
+                if (tmp == NULL) goto failed;
+                if (!PyList_Check(tmp)) {
+                        PyErr_Format(PyExc_TypeError, "comprehension field \"ifs\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                        goto failed;
+                }
+                len = PyList_GET_SIZE(tmp);
+                ifs = asdl_seq_new(len, arena);
+                if (ifs == NULL) goto failed;
+                for (i = 0; i < len; i++) {
+                        expr_ty value;
+                        res = obj2ast_expr(PyList_GET_ITEM(tmp, i), &value, arena);
+                        if (res != 0) goto failed;
+                        asdl_seq_SET(ifs, i, value);
+                }
+                Py_XDECREF(tmp);
+                tmp = NULL;
+        } else {
+                PyErr_SetString(PyExc_TypeError, "required field \"ifs\" missing from comprehension");
+                return 1;
+        }
+        *out = comprehension(target, iter, ifs, arena);
+        return 0;
+failed:
+        Py_XDECREF(tmp);
+        return 1;
+}
+
+int
+obj2ast_excepthandler(PyObject* obj, excepthandler_ty* out, PyArena* arena)
+{
+        PyObject* tmp = NULL;
+        int isinstance;
+
+        int lineno;
+        int col_offset;
+
+        if (obj == Py_None) {
+                *out = NULL;
+                return 0;
+        }
+        if (PyObject_HasAttrString(obj, "lineno")) {
+                int res;
+                tmp = PyObject_GetAttrString(obj, "lineno");
+                if (tmp == NULL) goto failed;
+                res = obj2ast_int(tmp, &lineno, arena);
+                if (res != 0) goto failed;
+                Py_XDECREF(tmp);
+                tmp = NULL;
+        } else {
+                PyErr_SetString(PyExc_TypeError, "required field \"lineno\" missing from excepthandler");
+                return 1;
+        }
+        if (PyObject_HasAttrString(obj, "col_offset")) {
+                int res;
+                tmp = PyObject_GetAttrString(obj, "col_offset");
+                if (tmp == NULL) goto failed;
+                res = obj2ast_int(tmp, &col_offset, arena);
+                if (res != 0) goto failed;
+                Py_XDECREF(tmp);
+                tmp = NULL;
+        } else {
+                PyErr_SetString(PyExc_TypeError, "required field \"col_offset\" missing from excepthandler");
+                return 1;
+        }
+        isinstance = PyObject_IsInstance(obj, (PyObject*)ExceptHandler_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+                expr_ty type;
+                expr_ty name;
+                asdl_seq* body;
+
+                if (PyObject_HasAttrString(obj, "type")) {
+                        int res;
+                        tmp = PyObject_GetAttrString(obj, "type");
+                        if (tmp == NULL) goto failed;
+                        res = obj2ast_expr(tmp, &type, arena);
+                        if (res != 0) goto failed;
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        type = NULL;
+                }
+                if (PyObject_HasAttrString(obj, "name")) {
+                        int res;
+                        tmp = PyObject_GetAttrString(obj, "name");
+                        if (tmp == NULL) goto failed;
+                        res = obj2ast_expr(tmp, &name, arena);
+                        if (res != 0) goto failed;
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        name = NULL;
+                }
+                if (PyObject_HasAttrString(obj, "body")) {
+                        int res;
+                        Py_ssize_t len;
+                        Py_ssize_t i;
+                        tmp = PyObject_GetAttrString(obj, "body");
+                        if (tmp == NULL) goto failed;
+                        if (!PyList_Check(tmp)) {
+                                PyErr_Format(PyExc_TypeError, "ExceptHandler field \"body\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                                goto failed;
+                        }
+                        len = PyList_GET_SIZE(tmp);
+                        body = asdl_seq_new(len, arena);
+                        if (body == NULL) goto failed;
+                        for (i = 0; i < len; i++) {
+                                stmt_ty value;
+                                res = obj2ast_stmt(PyList_GET_ITEM(tmp, i), &value, arena);
+                                if (res != 0) goto failed;
+                                asdl_seq_SET(body, i, value);
+                        }
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"body\" missing from ExceptHandler");
+                        return 1;
+                }
+                *out = ExceptHandler(type, name, body, lineno, col_offset, arena);
+                if (*out == NULL) goto failed;
+                return 0;
+        }
+
+        tmp = PyObject_Repr(obj);
+        if (tmp == NULL) goto failed;
+        PyErr_Format(PyExc_TypeError, "expected some sort of excepthandler, but got %.400s", _PyUnicode_AsString(tmp));
+failed:
+        Py_XDECREF(tmp);
+        return 1;
+}
+
+int
+obj2ast_arguments(PyObject* obj, arguments_ty* out, PyArena* arena)
+{
+        PyObject* tmp = NULL;
+        asdl_seq* args;
+        identifier vararg;
+        identifier kwarg;
+        asdl_seq* defaults;
+        asdl_seq* type_comments;
+
+        if (PyObject_HasAttrString(obj, "args")) {
+                int res;
+                Py_ssize_t len;
+                Py_ssize_t i;
+                tmp = PyObject_GetAttrString(obj, "args");
+                if (tmp == NULL) goto failed;
+                if (!PyList_Check(tmp)) {
+                        PyErr_Format(PyExc_TypeError, "arguments field \"args\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                        goto failed;
+                }
+                len = PyList_GET_SIZE(tmp);
+                args = asdl_seq_new(len, arena);
+                if (args == NULL) goto failed;
+                for (i = 0; i < len; i++) {
+                        expr_ty value;
+                        res = obj2ast_expr(PyList_GET_ITEM(tmp, i), &value, arena);
+                        if (res != 0) goto failed;
+                        asdl_seq_SET(args, i, value);
+                }
+                Py_XDECREF(tmp);
+                tmp = NULL;
+        } else {
+                PyErr_SetString(PyExc_TypeError, "required field \"args\" missing from arguments");
+                return 1;
+        }
+        if (PyObject_HasAttrString(obj, "vararg")) {
+                int res;
+                tmp = PyObject_GetAttrString(obj, "vararg");
+                if (tmp == NULL) goto failed;
+                res = obj2ast_identifier(tmp, &vararg, arena);
+                if (res != 0) goto failed;
+                Py_XDECREF(tmp);
+                tmp = NULL;
+        } else {
+                vararg = NULL;
+        }
+        if (PyObject_HasAttrString(obj, "kwarg")) {
+                int res;
+                tmp = PyObject_GetAttrString(obj, "kwarg");
+                if (tmp == NULL) goto failed;
+                res = obj2ast_identifier(tmp, &kwarg, arena);
+                if (res != 0) goto failed;
+                Py_XDECREF(tmp);
+                tmp = NULL;
+        } else {
+                kwarg = NULL;
+        }
+        if (PyObject_HasAttrString(obj, "defaults")) {
+                int res;
+                Py_ssize_t len;
+                Py_ssize_t i;
+                tmp = PyObject_GetAttrString(obj, "defaults");
+                if (tmp == NULL) goto failed;
+                if (!PyList_Check(tmp)) {
+                        PyErr_Format(PyExc_TypeError, "arguments field \"defaults\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                        goto failed;
+                }
+                len = PyList_GET_SIZE(tmp);
+                defaults = asdl_seq_new(len, arena);
+                if (defaults == NULL) goto failed;
+                for (i = 0; i < len; i++) {
+                        expr_ty value;
+                        res = obj2ast_expr(PyList_GET_ITEM(tmp, i), &value, arena);
+                        if (res != 0) goto failed;
+                        asdl_seq_SET(defaults, i, value);
+                }
+                Py_XDECREF(tmp);
+                tmp = NULL;
+        } else {
+                PyErr_SetString(PyExc_TypeError, "required field \"defaults\" missing from arguments");
+                return 1;
+        }
+        if (PyObject_HasAttrString(obj, "type_comments")) {
+                int res;
+                Py_ssize_t len;
+                Py_ssize_t i;
+                tmp = PyObject_GetAttrString(obj, "type_comments");
+                if (tmp == NULL) goto failed;
+                if (!PyList_Check(tmp)) {
+                        PyErr_Format(PyExc_TypeError, "arguments field \"type_comments\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                        goto failed;
+                }
+                len = PyList_GET_SIZE(tmp);
+                type_comments = asdl_seq_new(len, arena);
+                if (type_comments == NULL) goto failed;
+                for (i = 0; i < len; i++) {
+                        string value;
+                        res = obj2ast_string(PyList_GET_ITEM(tmp, i), &value, arena);
+                        if (res != 0) goto failed;
+                        asdl_seq_SET(type_comments, i, value);
+                }
+                Py_XDECREF(tmp);
+                tmp = NULL;
+        } else {
+                PyErr_SetString(PyExc_TypeError, "required field \"type_comments\" missing from arguments");
+                return 1;
+        }
+        *out = arguments(args, vararg, kwarg, defaults, type_comments, arena);
+        return 0;
+failed:
+        Py_XDECREF(tmp);
+        return 1;
+}
+
+int
+obj2ast_keyword(PyObject* obj, keyword_ty* out, PyArena* arena)
+{
+        PyObject* tmp = NULL;
+        identifier arg;
+        expr_ty value;
+
+        if (PyObject_HasAttrString(obj, "arg")) {
+                int res;
+                tmp = PyObject_GetAttrString(obj, "arg");
+                if (tmp == NULL) goto failed;
+                res = obj2ast_identifier(tmp, &arg, arena);
+                if (res != 0) goto failed;
+                Py_XDECREF(tmp);
+                tmp = NULL;
+        } else {
+                PyErr_SetString(PyExc_TypeError, "required field \"arg\" missing from keyword");
+                return 1;
+        }
+        if (PyObject_HasAttrString(obj, "value")) {
+                int res;
+                tmp = PyObject_GetAttrString(obj, "value");
+                if (tmp == NULL) goto failed;
+                res = obj2ast_expr(tmp, &value, arena);
+                if (res != 0) goto failed;
+                Py_XDECREF(tmp);
+                tmp = NULL;
+        } else {
+                PyErr_SetString(PyExc_TypeError, "required field \"value\" missing from keyword");
+                return 1;
+        }
+        *out = keyword(arg, value, arena);
+        return 0;
+failed:
+        Py_XDECREF(tmp);
+        return 1;
+}
+
+int
+obj2ast_alias(PyObject* obj, alias_ty* out, PyArena* arena)
+{
+        PyObject* tmp = NULL;
+        identifier name;
+        identifier asname;
+
+        if (PyObject_HasAttrString(obj, "name")) {
+                int res;
+                tmp = PyObject_GetAttrString(obj, "name");
+                if (tmp == NULL) goto failed;
+                res = obj2ast_identifier(tmp, &name, arena);
+                if (res != 0) goto failed;
+                Py_XDECREF(tmp);
+                tmp = NULL;
+        } else {
+                PyErr_SetString(PyExc_TypeError, "required field \"name\" missing from alias");
+                return 1;
+        }
+        if (PyObject_HasAttrString(obj, "asname")) {
+                int res;
+                tmp = PyObject_GetAttrString(obj, "asname");
+                if (tmp == NULL) goto failed;
+                res = obj2ast_identifier(tmp, &asname, arena);
+                if (res != 0) goto failed;
+                Py_XDECREF(tmp);
+                tmp = NULL;
+        } else {
+                asname = NULL;
+        }
+        *out = alias(name, asname, arena);
+        return 0;
+failed:
+        Py_XDECREF(tmp);
+        return 1;
+}
+
+int
+obj2ast_type_ignore(PyObject* obj, type_ignore_ty* out, PyArena* arena)
+{
+        PyObject* tmp = NULL;
+        int isinstance;
+
+
+        if (obj == Py_None) {
+                *out = NULL;
+                return 0;
+        }
+        isinstance = PyObject_IsInstance(obj, (PyObject*)TypeIgnore_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+                int lineno;
+
+                if (PyObject_HasAttrString(obj, "lineno")) {
+                        int res;
+                        tmp = PyObject_GetAttrString(obj, "lineno");
+                        if (tmp == NULL) goto failed;
+                        res = obj2ast_int(tmp, &lineno, arena);
+                        if (res != 0) goto failed;
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"lineno\" missing from TypeIgnore");
+                        return 1;
+                }
+                *out = TypeIgnore(lineno, arena);
+                if (*out == NULL) goto failed;
+                return 0;
+        }
+
+        tmp = PyObject_Repr(obj);
+        if (tmp == NULL) goto failed;
+        PyErr_Format(PyExc_TypeError, "expected some sort of type_ignore, but got %.400s", _PyUnicode_AsString(tmp));
+failed:
+        Py_XDECREF(tmp);
+        return 1;
+}
+
+
+PyObject *ast27_parse(PyObject *self, PyObject *args);
+static PyMethodDef ast27_methods[] = {
+        {"parse",  ast27_parse, METH_VARARGS, "Parse string into typed AST."},
+        {NULL, NULL, 0, NULL}
+};
+static struct PyModuleDef _astmodule27 = {
+  PyModuleDef_HEAD_INIT, "_ast27", NULL, 0, ast27_methods
+};
+PyMODINIT_FUNC
+PyInit__ast27(void)
+{
+        PyObject *m, *d;
+        if (!init_types()) return NULL;
+        m = PyModule_Create(&_astmodule27);
+        if (!m) return NULL;
+        d = PyModule_GetDict(m);
+        if (PyDict_SetItemString(d, "AST", (PyObject*)&AST_type) < 0) return NULL;
+        if (PyModule_AddIntMacro(m, PyCF_ONLY_AST) < 0)
+                return NULL;
+        if (PyDict_SetItemString(d, "mod", (PyObject*)mod_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "Module", (PyObject*)Module_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "Interactive", (PyObject*)Interactive_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "Expression", (PyObject*)Expression_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "FunctionType", (PyObject*)FunctionType_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "Suite", (PyObject*)Suite_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "stmt", (PyObject*)stmt_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "FunctionDef", (PyObject*)FunctionDef_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "ClassDef", (PyObject*)ClassDef_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "Return", (PyObject*)Return_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "Delete", (PyObject*)Delete_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "Assign", (PyObject*)Assign_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "AugAssign", (PyObject*)AugAssign_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "Print", (PyObject*)Print_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "For", (PyObject*)For_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "While", (PyObject*)While_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "If", (PyObject*)If_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "With", (PyObject*)With_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "Raise", (PyObject*)Raise_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "TryExcept", (PyObject*)TryExcept_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "TryFinally", (PyObject*)TryFinally_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "Assert", (PyObject*)Assert_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "Import", (PyObject*)Import_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "ImportFrom", (PyObject*)ImportFrom_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "Exec", (PyObject*)Exec_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "Global", (PyObject*)Global_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "Expr", (PyObject*)Expr_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "Pass", (PyObject*)Pass_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "Break", (PyObject*)Break_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "Continue", (PyObject*)Continue_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "expr", (PyObject*)expr_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "BoolOp", (PyObject*)BoolOp_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "BinOp", (PyObject*)BinOp_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "UnaryOp", (PyObject*)UnaryOp_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "Lambda", (PyObject*)Lambda_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "IfExp", (PyObject*)IfExp_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "Dict", (PyObject*)Dict_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "Set", (PyObject*)Set_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "ListComp", (PyObject*)ListComp_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "SetComp", (PyObject*)SetComp_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "DictComp", (PyObject*)DictComp_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "GeneratorExp", (PyObject*)GeneratorExp_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "Yield", (PyObject*)Yield_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "Compare", (PyObject*)Compare_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "Call", (PyObject*)Call_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "Repr", (PyObject*)Repr_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "Num", (PyObject*)Num_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "Str", (PyObject*)Str_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "Attribute", (PyObject*)Attribute_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "Subscript", (PyObject*)Subscript_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "Name", (PyObject*)Name_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "List", (PyObject*)List_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "Tuple", (PyObject*)Tuple_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "expr_context", (PyObject*)expr_context_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "Load", (PyObject*)Load_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "Store", (PyObject*)Store_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "Del", (PyObject*)Del_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "AugLoad", (PyObject*)AugLoad_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "AugStore", (PyObject*)AugStore_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "Param", (PyObject*)Param_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "slice", (PyObject*)slice_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "Ellipsis", (PyObject*)Ellipsis_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "Slice", (PyObject*)Slice_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "ExtSlice", (PyObject*)ExtSlice_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "Index", (PyObject*)Index_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "boolop", (PyObject*)boolop_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "And", (PyObject*)And_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "Or", (PyObject*)Or_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "operator", (PyObject*)operator_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "Add", (PyObject*)Add_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "Sub", (PyObject*)Sub_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "Mult", (PyObject*)Mult_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "Div", (PyObject*)Div_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "Mod", (PyObject*)Mod_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "Pow", (PyObject*)Pow_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "LShift", (PyObject*)LShift_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "RShift", (PyObject*)RShift_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "BitOr", (PyObject*)BitOr_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "BitXor", (PyObject*)BitXor_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "BitAnd", (PyObject*)BitAnd_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "FloorDiv", (PyObject*)FloorDiv_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "unaryop", (PyObject*)unaryop_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "Invert", (PyObject*)Invert_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "Not", (PyObject*)Not_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "UAdd", (PyObject*)UAdd_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "USub", (PyObject*)USub_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "cmpop", (PyObject*)cmpop_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "Eq", (PyObject*)Eq_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "NotEq", (PyObject*)NotEq_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "Lt", (PyObject*)Lt_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "LtE", (PyObject*)LtE_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "Gt", (PyObject*)Gt_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "GtE", (PyObject*)GtE_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "Is", (PyObject*)Is_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "IsNot", (PyObject*)IsNot_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "In", (PyObject*)In_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "NotIn", (PyObject*)NotIn_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "comprehension", (PyObject*)comprehension_type) < 0) return
+            NULL;
+        if (PyDict_SetItemString(d, "excepthandler", (PyObject*)excepthandler_type) < 0) return
+            NULL;
+        if (PyDict_SetItemString(d, "ExceptHandler", (PyObject*)ExceptHandler_type) < 0) return
+            NULL;
+        if (PyDict_SetItemString(d, "arguments", (PyObject*)arguments_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "keyword", (PyObject*)keyword_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "alias", (PyObject*)alias_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "type_ignore", (PyObject*)type_ignore_type) < 0) return NULL;
+        if (PyDict_SetItemString(d, "TypeIgnore", (PyObject*)TypeIgnore_type) < 0) return NULL;
+        return m;
+}
+
+
+PyObject* Ta27AST_mod2obj(mod_ty t)
+{
+    init_types();
+    return ast2obj_mod(t);
+}
+
+/* mode is 0 for "exec", 1 for "eval" and 2 for "single" input */
+mod_ty Ta27AST_obj2mod(PyObject* ast, PyArena* arena, int mode)
+{
+    mod_ty res;
+    PyObject *req_type[3];
+    char *req_name[3];
+    int isinstance;
+
+    req_type[0] = (PyObject*)Module_type;
+    req_type[1] = (PyObject*)Expression_type;
+    req_type[2] = (PyObject*)Interactive_type;
+
+    req_name[0] = "Module";
+    req_name[1] = "Expression";
+    req_name[2] = "Interactive";
+
+    assert(0 <= mode && mode <= 2);
+
+    init_types();
+
+    isinstance = PyObject_IsInstance(ast, req_type[mode]);
+    if (isinstance == -1)
+        return NULL;
+    if (!isinstance) {
+        PyErr_Format(PyExc_TypeError, "expected %s node, got %.400s",
+                     req_name[mode], Py_TYPE(ast)->tp_name);
+        return NULL;
+    }
+    if (obj2ast_mod(ast, &res, arena) != 0)
+        return NULL;
+    else
+        return res;
+}
+
+int Ta27AST_Check(PyObject* obj)
+{
+    init_types();
+    return PyObject_IsInstance(obj, (PyObject*)&AST_type);
+}
+
+
diff --git a/ast27/Python/ast.c b/ast27/Python/ast.c
new file mode 100644
index 0000000..50a3b07
--- /dev/null
+++ b/ast27/Python/ast.c
@@ -0,0 +1,3784 @@
+/*
+ * This file includes functions to transform a concrete syntax tree (CST) to
+ * an abstract syntax tree (AST).  The main function is Ta27AST_FromNode().
+ *
+ */
+#include "Python.h"
+#include "Python-ast.h"
+#include "grammar.h"
+#include "node.h"
+#include "pyarena.h"
+#include "ast.h"
+#include "token.h"
+#include "parsetok.h"
+#include "graminit.h"
+#include "unicodeobject.h"
+
+#include <assert.h>
+
+/* Data structure used internally */
+struct compiling {
+    char *c_encoding; /* source encoding */
+    int c_future_unicode; /* __future__ unicode literals flag */
+    PyArena *c_arena; /* arena for allocating memeory */
+    const char *c_filename; /* filename */
+};
+
+static asdl_seq *seq_for_testlist(struct compiling *, const node *);
+static expr_ty ast_for_expr(struct compiling *, const node *);
+static stmt_ty ast_for_stmt(struct compiling *, const node *);
+static asdl_seq *ast_for_suite(struct compiling *, const node *);
+static asdl_seq *ast_for_exprlist(struct compiling *, const node *,
+                                  expr_context_ty);
+static expr_ty ast_for_testlist(struct compiling *, const node *);
+static stmt_ty ast_for_classdef(struct compiling *, const node *, asdl_seq *);
+static expr_ty ast_for_testlist_comp(struct compiling *, const node *);
+
+/* Note different signature for ast_for_call */
+static expr_ty ast_for_call(struct compiling *, const node *, expr_ty);
+
+static PyObject *parsenumber(struct compiling *, const char *);
+static PyObject *parsestr(struct compiling *, const node *n, const char *);
+static PyObject *parsestrplus(struct compiling *, const node *n);
+
+static int Py_Py3kWarningFlag = 0;
+static int Py_UnicodeFlag = 0;
+
+extern long Ta27OS_strtol(char *str, char **ptr, int base);
+
+#ifndef LINENO
+#define LINENO(n)       ((n)->n_lineno)
+#endif
+
+#define COMP_GENEXP 0
+#define COMP_SETCOMP  1
+
+static identifier
+new_identifier(const char* n, PyArena *arena) {
+    PyObject* id = PyUnicode_InternFromString(n);
+    if (id != NULL)
+        PyArena_AddPyObject(arena, id);
+    return id;
+}
+
+#define NEW_IDENTIFIER(n) new_identifier(STR(n), c->c_arena)
+
+static string
+new_type_comment(const char *s, struct compiling *c)
+{
+  return PyUnicode_DecodeUTF8(s, strlen(s), NULL);
+}
+#define NEW_TYPE_COMMENT(n) new_type_comment(STR(n), c)
+
+
+/* This routine provides an invalid object for the syntax error.
+   The outermost routine must unpack this error and create the
+   proper object.  We do this so that we don't have to pass
+   the filename to everything function.
+
+   XXX Maybe we should just pass the filename...
+*/
+
+static int
+ast_error(const node *n, const char *errstr)
+{
+    PyObject *u = Py_BuildValue("zi", errstr, LINENO(n));
+    if (!u)
+        return 0;
+    PyErr_SetObject(PyExc_SyntaxError, u);
+    Py_DECREF(u);
+    return 0;
+}
+
+static void
+ast_error_finish(const char *filename)
+{
+    PyObject *type, *value, *tback, *errstr, *loc, *tmp;
+    long lineno;
+
+    assert(PyErr_Occurred());
+    if (!PyErr_ExceptionMatches(PyExc_SyntaxError))
+        return;
+
+    PyErr_Fetch(&type, &value, &tback);
+    errstr = PyTuple_GetItem(value, 0);
+    if (!errstr)
+        return;
+    Py_INCREF(errstr);
+    lineno = PyLong_AsLong(PyTuple_GetItem(value, 1));
+    if (lineno == -1) {
+        Py_DECREF(errstr);
+        return;
+    }
+    Py_DECREF(value);
+
+    loc = PyErr_ProgramText(filename, lineno);
+    if (!loc) {
+        Py_INCREF(Py_None);
+        loc = Py_None;
+    }
+    tmp = Py_BuildValue("(zlOO)", filename, lineno, Py_None, loc);
+    Py_DECREF(loc);
+    if (!tmp) {
+        Py_DECREF(errstr);
+        return;
+    }
+    value = PyTuple_Pack(2, errstr, tmp);
+    Py_DECREF(errstr);
+    Py_DECREF(tmp);
+    if (!value)
+        return;
+    PyErr_Restore(type, value, tback);
+}
+
+static int
+ast_warn(struct compiling *c, const node *n, char *msg)
+{
+    if (PyErr_WarnExplicit(PyExc_SyntaxWarning, msg, c->c_filename, LINENO(n),
+                           NULL, NULL) < 0) {
+        /* if -Werr, change it to a SyntaxError */
+        if (PyErr_Occurred() && PyErr_ExceptionMatches(PyExc_SyntaxWarning))
+            ast_error(n, msg);
+        return 0;
+    }
+    return 1;
+}
+
+static int
+forbidden_check(struct compiling *c, const node *n, const char *x)
+{
+    if (!strcmp(x, "None"))
+        return ast_error(n, "cannot assign to None");
+    if (!strcmp(x, "__debug__"))
+        return ast_error(n, "cannot assign to __debug__");
+    if (Py_Py3kWarningFlag) {
+        if (!(strcmp(x, "True") && strcmp(x, "False")) &&
+            !ast_warn(c, n, "assignment to True or False is forbidden in 3.x"))
+            return 0;
+        if (!strcmp(x, "nonlocal") &&
+            !ast_warn(c, n, "nonlocal is a keyword in 3.x"))
+            return 0;
+    }
+    return 1;
+}
+
+/* num_stmts() returns number of contained statements.
+
+   Use this routine to determine how big a sequence is needed for
+   the statements in a parse tree.  Its raison d'etre is this bit of
+   grammar:
+
+   stmt: simple_stmt | compound_stmt
+   simple_stmt: small_stmt (';' small_stmt)* [';'] NEWLINE
+
+   A simple_stmt can contain multiple small_stmt elements joined
+   by semicolons.  If the arg is a simple_stmt, the number of
+   small_stmt elements is returned.
+*/
+
+static int
+num_stmts(const node *n)
+{
+    int i, l;
+    node *ch;
+
+    switch (TYPE(n)) {
+        case single_input:
+            if (TYPE(CHILD(n, 0)) == NEWLINE)
+                return 0;
+            else
+                return num_stmts(CHILD(n, 0));
+        case file_input:
+            l = 0;
+            for (i = 0; i < NCH(n); i++) {
+                ch = CHILD(n, i);
+                if (TYPE(ch) == stmt)
+                    l += num_stmts(ch);
+            }
+            return l;
+        case stmt:
+            return num_stmts(CHILD(n, 0));
+        case compound_stmt:
+            return 1;
+        case simple_stmt:
+            return NCH(n) / 2; /* Divide by 2 to remove count of semi-colons */
+        case suite:
+            /* suite: simple_stmt | NEWLINE [TYPE_COMMENT NEWLINE] INDENT stmt+ DEDENT */
+            if (NCH(n) == 1)
+                return num_stmts(CHILD(n, 0));
+            else {
+                i = 2;
+                l = 0;
+                if (TYPE(CHILD(n, 1)) == TYPE_COMMENT)
+                    i += 2;
+                for (; i < (NCH(n) - 1); i++)
+                    l += num_stmts(CHILD(n, i));
+                return l;
+            }
+        default: {
+            char buf[128];
+
+            sprintf(buf, "Non-statement found: %d %d",
+                    TYPE(n), NCH(n));
+            Py_FatalError(buf);
+        }
+    }
+    assert(0);
+    return 0;
+}
+
+/* Transform the CST rooted at node * to the appropriate AST
+*/
+
+mod_ty
+Ta27AST_FromNode(const node *n, PyCompilerFlags *flags, const char *filename,
+               PyArena *arena)
+{
+    int i, j, k, num;
+    asdl_seq *stmts = NULL;
+    asdl_seq *type_ignores = NULL;
+    stmt_ty s;
+    node *ch;
+    struct compiling c;
+    asdl_seq *argtypes = NULL;
+    expr_ty ret, arg;
+
+    if (flags && flags->cf_flags & PyCF_SOURCE_IS_UTF8) {
+        c.c_encoding = "utf-8";
+        if (TYPE(n) == encoding_decl) {
+            ast_error(n, "encoding declaration in Unicode string");
+            goto error;
+        }
+    } else if (TYPE(n) == encoding_decl) {
+        c.c_encoding = STR(n);
+        n = CHILD(n, 0);
+    } else {
+        c.c_encoding = NULL;
+    }
+    c.c_future_unicode = flags && flags->cf_flags & CO_FUTURE_UNICODE_LITERALS;
+    c.c_arena = arena;
+    c.c_filename = filename;
+
+    k = 0;
+    switch (TYPE(n)) {
+        case file_input:
+            stmts = asdl_seq_new(num_stmts(n), arena);
+            if (!stmts)
+                return NULL;
+            for (i = 0; i < NCH(n) - 1; i++) {
+                ch = CHILD(n, i);
+                if (TYPE(ch) == NEWLINE)
+                    continue;
+                REQ(ch, stmt);
+                num = num_stmts(ch);
+                if (num == 1) {
+                    s = ast_for_stmt(&c, ch);
+                    if (!s)
+                        goto error;
+                    asdl_seq_SET(stmts, k++, s);
+                }
+                else {
+                    ch = CHILD(ch, 0);
+                    REQ(ch, simple_stmt);
+                    for (j = 0; j < num; j++) {
+                        s = ast_for_stmt(&c, CHILD(ch, j * 2));
+                        if (!s)
+                            goto error;
+                        asdl_seq_SET(stmts, k++, s);
+                    }
+                }
+            }
+            /* Type ignores are stored under the ENDMARKER in file_input. */
+            ch = CHILD(n, NCH(n) - 1);
+            REQ(ch, ENDMARKER);
+            num = NCH(ch);
+            type_ignores = _Py_asdl_seq_new(num, arena);
+            if (!type_ignores)
+                goto error;
+
+            for (i = 0; i < num; i++) {
+                type_ignore_ty ti = TypeIgnore(LINENO(CHILD(ch, i)), arena);
+                if (!ti)
+                    goto error;
+                asdl_seq_SET(type_ignores, i, ti);
+            }
+
+            return Module(stmts, type_ignores, arena);
+        case eval_input: {
+            expr_ty testlist_ast;
+
+            /* XXX Why not comp_for here? */
+            testlist_ast = ast_for_testlist(&c, CHILD(n, 0));
+            if (!testlist_ast)
+                goto error;
+            return Expression(testlist_ast, arena);
+        }
+        case single_input:
+            if (TYPE(CHILD(n, 0)) == NEWLINE) {
+                stmts = asdl_seq_new(1, arena);
+                if (!stmts)
+                    goto error;
+                asdl_seq_SET(stmts, 0, Pass(n->n_lineno, n->n_col_offset,
+                                            arena));
+                if (!asdl_seq_GET(stmts, 0))
+                    goto error;
+                return Interactive(stmts, arena);
+            }
+            else {
+                n = CHILD(n, 0);
+                num = num_stmts(n);
+                stmts = asdl_seq_new(num, arena);
+                if (!stmts)
+                    goto error;
+                if (num == 1) {
+                    s = ast_for_stmt(&c, n);
+                    if (!s)
+                        goto error;
+                    asdl_seq_SET(stmts, 0, s);
+                }
+                else {
+                    /* Only a simple_stmt can contain multiple statements. */
+                    REQ(n, simple_stmt);
+                    for (i = 0; i < NCH(n); i += 2) {
+                        if (TYPE(CHILD(n, i)) == NEWLINE)
+                            break;
+                        s = ast_for_stmt(&c, CHILD(n, i));
+                        if (!s)
+                            goto error;
+                        asdl_seq_SET(stmts, i / 2, s);
+                    }
+                }
+
+                return Interactive(stmts, arena);
+            }
+        case func_type_input:
+            n = CHILD(n, 0);
+            REQ(n, func_type);
+
+            if (TYPE(CHILD(n, 1)) == typelist) {
+                ch = CHILD(n, 1);
+                /* this is overly permissive -- we don't pay any attention to
+                 * stars on the args -- just parse them into an ordered list */
+                num = 0;
+                for (i = 0; i < NCH(ch); i++) {
+                    if (TYPE(CHILD(ch, i)) == test)
+                        num++;
+                }
+
+                argtypes = _Py_asdl_seq_new(num, arena);
+
+                j = 0;
+                for (i = 0; i < NCH(ch); i++) {
+                    if (TYPE(CHILD(ch, i)) == test) {
+                        arg = ast_for_expr(&c, CHILD(ch, i));
+                        if (!arg)
+                            goto error;
+                        asdl_seq_SET(argtypes, j++, arg);
+                    }
+                }
+            }
+            else
+                argtypes = _Py_asdl_seq_new(0, arena);
+
+            ret = ast_for_expr(&c, CHILD(n, NCH(n) - 1));
+            if (!ret)
+                goto error;
+            return FunctionType(argtypes, ret, arena);
+        default:
+            PyErr_Format(PyExc_SystemError,
+                         "invalid node %d for Ta27AST_FromNode", TYPE(n));
+            goto error;
+    }
+ error:
+    ast_error_finish(filename);
+    return NULL;
+}
+
+/* Return the AST repr. of the operator represented as syntax (|, ^, etc.)
+*/
+
+static operator_ty
+get_operator(const node *n)
+{
+    switch (TYPE(n)) {
+        case VBAR:
+            return BitOr;
+        case CIRCUMFLEX:
+            return BitXor;
+        case AMPER:
+            return BitAnd;
+        case LEFTSHIFT:
+            return LShift;
+        case RIGHTSHIFT:
+            return RShift;
+        case PLUS:
+            return Add;
+        case MINUS:
+            return Sub;
+        case STAR:
+            return Mult;
+        case SLASH:
+            return Div;
+        case DOUBLESLASH:
+            return FloorDiv;
+        case PERCENT:
+            return Mod;
+        default:
+            return (operator_ty)0;
+    }
+}
+
+/* Set the context ctx for expr_ty e, recursively traversing e.
+
+   Only sets context for expr kinds that "can appear in assignment context"
+   (according to ../Parser/Python.asdl).  For other expr kinds, it sets
+   an appropriate syntax error and returns false.
+*/
+
+static int
+set_context(struct compiling *c, expr_ty e, expr_context_ty ctx, const node *n)
+{
+    asdl_seq *s = NULL;
+    /* If a particular expression type can't be used for assign / delete,
+       set expr_name to its name and an error message will be generated.
+    */
+    const char* expr_name = NULL;
+
+    /* The ast defines augmented store and load contexts, but the
+       implementation here doesn't actually use them.  The code may be
+       a little more complex than necessary as a result.  It also means
+       that expressions in an augmented assignment have a Store context.
+       Consider restructuring so that augmented assignment uses
+       set_context(), too.
+    */
+    assert(ctx != AugStore && ctx != AugLoad);
+
+    switch (e->kind) {
+        case Attribute_kind:
+            if (ctx == Store && !forbidden_check(c, n,
+                                PyBytes_AS_STRING(e->v.Attribute.attr)))
+                    return 0;
+            e->v.Attribute.ctx = ctx;
+            break;
+        case Subscript_kind:
+            e->v.Subscript.ctx = ctx;
+            break;
+        case Name_kind:
+            if (ctx == Store && !forbidden_check(c, n,
+                                PyBytes_AS_STRING(e->v.Name.id)))
+                    return 0;
+            e->v.Name.ctx = ctx;
+            break;
+        case List_kind:
+            e->v.List.ctx = ctx;
+            s = e->v.List.elts;
+            break;
+        case Tuple_kind:
+            if (asdl_seq_LEN(e->v.Tuple.elts))  {
+                e->v.Tuple.ctx = ctx;
+                s = e->v.Tuple.elts;
+            }
+            else {
+                expr_name = "()";
+            }
+            break;
+        case Lambda_kind:
+            expr_name = "lambda";
+            break;
+        case Call_kind:
+            expr_name = "function call";
+            break;
+        case BoolOp_kind:
+        case BinOp_kind:
+        case UnaryOp_kind:
+            expr_name = "operator";
+            break;
+        case GeneratorExp_kind:
+            expr_name = "generator expression";
+            break;
+        case Yield_kind:
+            expr_name = "yield expression";
+            break;
+        case ListComp_kind:
+            expr_name = "list comprehension";
+            break;
+        case SetComp_kind:
+            expr_name = "set comprehension";
+            break;
+        case DictComp_kind:
+            expr_name = "dict comprehension";
+            break;
+        case Dict_kind:
+        case Set_kind:
+        case Num_kind:
+        case Str_kind:
+            expr_name = "literal";
+            break;
+        case Compare_kind:
+            expr_name = "comparison";
+            break;
+        case Repr_kind:
+            expr_name = "repr";
+            break;
+        case IfExp_kind:
+            expr_name = "conditional expression";
+            break;
+        default:
+            PyErr_Format(PyExc_SystemError,
+                         "unexpected expression in assignment %d (line %d)",
+                         e->kind, e->lineno);
+            return 0;
+    }
+    /* Check for error string set by switch */
+    if (expr_name) {
+        char buf[300];
+        PyOS_snprintf(buf, sizeof(buf),
+                      "can't %s %s",
+                      ctx == Store ? "assign to" : "delete",
+                      expr_name);
+        return ast_error(n, buf);
+    }
+
+    /* If the LHS is a list or tuple, we need to set the assignment
+       context for all the contained elements.
+    */
+    if (s) {
+        int i;
+
+        for (i = 0; i < asdl_seq_LEN(s); i++) {
+            if (!set_context(c, (expr_ty)asdl_seq_GET(s, i), ctx, n))
+                return 0;
+        }
+    }
+    return 1;
+}
+
+static operator_ty
+ast_for_augassign(struct compiling *c, const node *n)
+{
+    REQ(n, augassign);
+    n = CHILD(n, 0);
+    switch (STR(n)[0]) {
+        case '+':
+            return Add;
+        case '-':
+            return Sub;
+        case '/':
+            if (STR(n)[1] == '/')
+                return FloorDiv;
+            else
+                return Div;
+        case '%':
+            return Mod;
+        case '<':
+            return LShift;
+        case '>':
+            return RShift;
+        case '&':
+            return BitAnd;
+        case '^':
+            return BitXor;
+        case '|':
+            return BitOr;
+        case '*':
+            if (STR(n)[1] == '*')
+                return Pow;
+            else
+                return Mult;
+        default:
+            PyErr_Format(PyExc_SystemError, "invalid augassign: %s", STR(n));
+            return (operator_ty)0;
+    }
+}
+
+static cmpop_ty
+ast_for_comp_op(struct compiling *c, const node *n)
+{
+    /* comp_op: '<'|'>'|'=='|'>='|'<='|'<>'|'!='|'in'|'not' 'in'|'is'
+               |'is' 'not'
+    */
+    REQ(n, comp_op);
+    if (NCH(n) == 1) {
+        n = CHILD(n, 0);
+        switch (TYPE(n)) {
+            case LESS:
+                return Lt;
+            case GREATER:
+                return Gt;
+            case EQEQUAL:                       /* == */
+                return Eq;
+            case LESSEQUAL:
+                return LtE;
+            case GREATEREQUAL:
+                return GtE;
+            case NOTEQUAL:
+                return NotEq;
+            case NAME:
+                if (strcmp(STR(n), "in") == 0)
+                    return In;
+                if (strcmp(STR(n), "is") == 0)
+                    return Is;
+            default:
+                PyErr_Format(PyExc_SystemError, "invalid comp_op: %s",
+                             STR(n));
+                return (cmpop_ty)0;
+        }
+    }
+    else if (NCH(n) == 2) {
+        /* handle "not in" and "is not" */
+        switch (TYPE(CHILD(n, 0))) {
+            case NAME:
+                if (strcmp(STR(CHILD(n, 1)), "in") == 0)
+                    return NotIn;
+                if (strcmp(STR(CHILD(n, 0)), "is") == 0)
+                    return IsNot;
+            default:
+                PyErr_Format(PyExc_SystemError, "invalid comp_op: %s %s",
+                             STR(CHILD(n, 0)), STR(CHILD(n, 1)));
+                return (cmpop_ty)0;
+        }
+    }
+    PyErr_Format(PyExc_SystemError, "invalid comp_op: has %d children",
+                 NCH(n));
+    return (cmpop_ty)0;
+}
+
+static asdl_seq *
+seq_for_testlist(struct compiling *c, const node *n)
+{
+    /* testlist: test (',' test)* [','] */
+    asdl_seq *seq;
+    expr_ty expression;
+    int i;
+    assert(TYPE(n) == testlist ||
+           TYPE(n) == listmaker ||
+           TYPE(n) == testlist_comp ||
+           TYPE(n) == testlist_safe ||
+           TYPE(n) == testlist1);
+
+    seq = asdl_seq_new((NCH(n) + 1) / 2, c->c_arena);
+    if (!seq)
+        return NULL;
+
+    for (i = 0; i < NCH(n); i += 2) {
+        assert(TYPE(CHILD(n, i)) == test || TYPE(CHILD(n, i)) == old_test);
+
+        expression = ast_for_expr(c, CHILD(n, i));
+        if (!expression)
+            return NULL;
+
+        assert(i / 2 < seq->size);
+        asdl_seq_SET(seq, i / 2, expression);
+    }
+    return seq;
+}
+
+static expr_ty
+compiler_complex_args(struct compiling *c, const node *n)
+{
+    int i, len = (NCH(n) + 1) / 2;
+    expr_ty result;
+    asdl_seq *args = asdl_seq_new(len, c->c_arena);
+    if (!args)
+        return NULL;
+
+    /* fpdef: NAME | '(' fplist ')'
+       fplist: fpdef (',' fpdef)* [',']
+    */
+    REQ(n, fplist);
+    for (i = 0; i < len; i++) {
+        PyObject *arg_id;
+        const node *fpdef_node = CHILD(n, 2*i);
+        const node *child;
+        expr_ty arg;
+set_name:
+        /* fpdef_node is either a NAME or an fplist */
+        child = CHILD(fpdef_node, 0);
+        if (TYPE(child) == NAME) {
+            if (!forbidden_check(c, n, STR(child)))
+                return NULL;
+            arg_id = NEW_IDENTIFIER(child);
+            if (!arg_id)
+                return NULL;
+            arg = Name(arg_id, Store, LINENO(child), child->n_col_offset,
+                       c->c_arena);
+        }
+        else {
+            assert(TYPE(fpdef_node) == fpdef);
+            /* fpdef_node[0] is not a name, so it must be '(', get CHILD[1] */
+            child = CHILD(fpdef_node, 1);
+            assert(TYPE(child) == fplist);
+            /* NCH == 1 means we have (x), we need to elide the extra parens */
+            if (NCH(child) == 1) {
+                fpdef_node = CHILD(child, 0);
+                assert(TYPE(fpdef_node) == fpdef);
+                goto set_name;
+            }
+            arg = compiler_complex_args(c, child);
+        }
+        asdl_seq_SET(args, i, arg);
+    }
+
+    result = Tuple(args, Store, LINENO(n), n->n_col_offset, c->c_arena);
+    if (!set_context(c, result, Store, n))
+        return NULL;
+    return result;
+}
+
+
+/* Create AST for argument list. */
+
+static arguments_ty
+ast_for_arguments(struct compiling *c, const node *n)
+{
+    /* parameters: '(' [varargslist] ')'
+       varargslist: ((fpdef ['=' test] ',' [TYPE_COMMENT])*
+                     ('*' NAME [',' [TYPE_COMMENT]  '**' NAME] [TYPE_COMMENT] | '**' NAME [TYPE_COMMENT]) |
+                     fpdef ['=' test] (',' [TYPE_COMMENT] fpdef ['=' test])* [','] [TYPE_COMMENT])
+    */
+    int i, j, k, l, n_args = 0, n_all_args = 0, n_defaults = 0, found_default = 0;
+    asdl_seq *args, *defaults, *type_comments = NULL;
+    identifier vararg = NULL, kwarg = NULL;
+    node *ch;
+
+    if (TYPE(n) == parameters) {
+        if (NCH(n) == 2) /* () as argument list */
+            return arguments(NULL, NULL, NULL, NULL, NULL, c->c_arena);
+        n = CHILD(n, 1);
+    }
+    REQ(n, varargslist);
+
+    /* first count the number of normal args & defaults */
+    for (i = 0; i < NCH(n); i++) {
+        ch = CHILD(n, i);
+        if (TYPE(ch) == fpdef)
+            n_args++;
+        if (TYPE(ch) == EQUAL)
+            n_defaults++;
+        if (TYPE(ch) == STAR || TYPE(ch) == DOUBLESTAR)
+            n_all_args++;
+    }
+    n_all_args += n_args;
+    args = (n_args ? asdl_seq_new(n_args, c->c_arena) : NULL);
+    if (!args && n_args)
+        return NULL;
+    defaults = (n_defaults ? asdl_seq_new(n_defaults, c->c_arena) : NULL);
+    if (!defaults && n_defaults)
+        return NULL;
+    /* type_comments will be lazily initialized if needed.  If there are no
+       per-argument type comments, it will remain NULL.  Otherwise, it will be
+       an asdl_seq with length equal to the number of args (including varargs
+       and kwargs, if present) and with members set to the string of each arg's
+       type comment, if present, or NULL otherwise.
+     */
+
+    /* fpdef: NAME | '(' fplist ')'
+       fplist: fpdef (',' fpdef)* [',']
+    */
+    i = 0;
+    j = 0;  /* index for defaults */
+    k = 0;  /* index for args */
+    l = 0;  /* index for type comments */
+    while (i < NCH(n)) {
+        ch = CHILD(n, i);
+        switch (TYPE(ch)) {
+            case fpdef: {
+                int complex_args = 0, parenthesized = 0;
+            handle_fpdef:
+                /* XXX Need to worry about checking if TYPE(CHILD(n, i+1)) is
+                   anything other than EQUAL or a comma? */
+                /* XXX Should NCH(n) check be made a separate check? */
+                if (i + 1 < NCH(n) && TYPE(CHILD(n, i + 1)) == EQUAL) {
+                    expr_ty expression = ast_for_expr(c, CHILD(n, i + 2));
+                    if (!expression)
+                        return NULL;
+                    assert(defaults != NULL);
+                    asdl_seq_SET(defaults, j++, expression);
+                    i += 2;
+                    found_default = 1;
+                }
+                else if (found_default) {
+                    /* def f((x)=4): pass should raise an error.
+                       def f((x, (y))): pass will just incur the tuple unpacking warning. */
+                    if (parenthesized && !complex_args) {
+                        ast_error(n, "parenthesized arg with default");
+                        return NULL;
+                    }
+                    ast_error(n,
+                             "non-default argument follows default argument");
+                    return NULL;
+                }
+                if (NCH(ch) == 3) {
+                    ch = CHILD(ch, 1);
+                    /* def foo((x)): is not complex, special case. */
+                    if (NCH(ch) != 1) {
+                        /* We have complex arguments, setup for unpacking. */
+                        if (Py_Py3kWarningFlag && !ast_warn(c, ch,
+                            "tuple parameter unpacking has been removed in 3.x"))
+                            return NULL;
+                        complex_args = 1;
+                        asdl_seq_SET(args, k++, compiler_complex_args(c, ch));
+                        if (!asdl_seq_GET(args, k-1))
+                                return NULL;
+                    } else {
+                        /* def foo((x)): setup for checking NAME below. */
+                        /* Loop because there can be many parens and tuple
+                           unpacking mixed in. */
+                        parenthesized = 1;
+                        ch = CHILD(ch, 0);
+                        assert(TYPE(ch) == fpdef);
+                        goto handle_fpdef;
+                    }
+                }
+                if (TYPE(CHILD(ch, 0)) == NAME) {
+                    PyObject *id;
+                    expr_ty name;
+                    if (!forbidden_check(c, n, STR(CHILD(ch, 0))))
+                        return NULL;
+                    id = NEW_IDENTIFIER(CHILD(ch, 0));
+                    if (!id)
+                        return NULL;
+                    name = Name(id, Param, LINENO(ch), ch->n_col_offset,
+                                c->c_arena);
+                    if (!name)
+                        return NULL;
+                    asdl_seq_SET(args, k++, name);
+
+                }
+                i += 1; /* the name */
+                if (TYPE(CHILD(n, i)) == COMMA)
+                    i += 1; /* the comma, if present */
+                if (parenthesized && Py_Py3kWarningFlag &&
+                    !ast_warn(c, ch, "parenthesized argument names "
+                              "are invalid in 3.x"))
+                    return NULL;
+
+                break;
+            }
+            case STAR:
+                if (!forbidden_check(c, CHILD(n, i+1), STR(CHILD(n, i+1))))
+                    return NULL;
+                vararg = NEW_IDENTIFIER(CHILD(n, i+1));
+                if (!vararg)
+                    return NULL;
+                i += 2; /* the star and the name */
+                if (TYPE(CHILD(n, i)) == COMMA)
+                    i += 1; /* the comma, if present */
+                break;
+            case DOUBLESTAR:
+                if (!forbidden_check(c, CHILD(n, i+1), STR(CHILD(n, i+1))))
+                    return NULL;
+                kwarg = NEW_IDENTIFIER(CHILD(n, i+1));
+                if (!kwarg)
+                    return NULL;
+                i += 2; /* the double star and the name */
+                if (TYPE(CHILD(n, i)) == COMMA)
+                    i += 1; /* the comma, if present */
+                break;
+            case TYPE_COMMENT:
+                assert(l < k + !!vararg + !!kwarg);
+
+                if (!type_comments) {
+                    /* lazily allocate the type_comments seq for perf reasons */
+                    type_comments = asdl_seq_new(n_all_args, c->c_arena);
+                    if (!type_comments)
+                        return NULL;
+                }
+
+                while (l < k + !!vararg + !!kwarg - 1) {
+                    asdl_seq_SET(type_comments, l++, NULL);
+                }
+
+                asdl_seq_SET(type_comments, l++, NEW_TYPE_COMMENT(ch));
+                i += 1;
+                break;
+            default:
+                PyErr_Format(PyExc_SystemError,
+                             "unexpected node in varargslist: %d @ %d",
+                             TYPE(ch), i);
+                return NULL;
+        }
+    }
+
+    if (type_comments) {
+        while (l < n_all_args) {
+            asdl_seq_SET(type_comments, l++, NULL);
+        }
+    }
+
+    return arguments(args, vararg, kwarg, defaults, type_comments, c->c_arena);
+}
+
+static expr_ty
+ast_for_dotted_name(struct compiling *c, const node *n)
+{
+    expr_ty e;
+    identifier id;
+    int lineno, col_offset;
+    int i;
+
+    REQ(n, dotted_name);
+
+    lineno = LINENO(n);
+    col_offset = n->n_col_offset;
+
+    id = NEW_IDENTIFIER(CHILD(n, 0));
+    if (!id)
+        return NULL;
+    e = Name(id, Load, lineno, col_offset, c->c_arena);
+    if (!e)
+        return NULL;
+
+    for (i = 2; i < NCH(n); i+=2) {
+        id = NEW_IDENTIFIER(CHILD(n, i));
+        if (!id)
+            return NULL;
+        e = Attribute(e, id, Load, lineno, col_offset, c->c_arena);
+        if (!e)
+            return NULL;
+    }
+
+    return e;
+}
+
+static expr_ty
+ast_for_decorator(struct compiling *c, const node *n)
+{
+    /* decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE */
+    expr_ty d = NULL;
+    expr_ty name_expr;
+
+    REQ(n, decorator);
+    REQ(CHILD(n, 0), AT);
+    REQ(RCHILD(n, -1), NEWLINE);
+
+    name_expr = ast_for_dotted_name(c, CHILD(n, 1));
+    if (!name_expr)
+        return NULL;
+
+    if (NCH(n) == 3) { /* No arguments */
+        d = name_expr;
+        name_expr = NULL;
+    }
+    else if (NCH(n) == 5) { /* Call with no arguments */
+        d = Call(name_expr, NULL, NULL, NULL, NULL, LINENO(n),
+                 n->n_col_offset, c->c_arena);
+        if (!d)
+            return NULL;
+        name_expr = NULL;
+    }
+    else {
+        d = ast_for_call(c, CHILD(n, 3), name_expr);
+        if (!d)
+            return NULL;
+        name_expr = NULL;
+    }
+
+    return d;
+}
+
+static asdl_seq*
+ast_for_decorators(struct compiling *c, const node *n)
+{
+    asdl_seq* decorator_seq;
+    expr_ty d;
+    int i;
+
+    REQ(n, decorators);
+    decorator_seq = asdl_seq_new(NCH(n), c->c_arena);
+    if (!decorator_seq)
+        return NULL;
+
+    for (i = 0; i < NCH(n); i++) {
+        d = ast_for_decorator(c, CHILD(n, i));
+        if (!d)
+            return NULL;
+        asdl_seq_SET(decorator_seq, i, d);
+    }
+    return decorator_seq;
+}
+
+static stmt_ty
+ast_for_funcdef(struct compiling *c, const node *n, asdl_seq *decorator_seq)
+{
+    /* funcdef: 'def' NAME parameters ':' [TYPE_COMMENT] suite */
+    identifier name;
+    arguments_ty args;
+    asdl_seq *body;
+    int name_i = 1;
+    node *tc;
+    string type_comment = NULL;
+
+    REQ(n, funcdef);
+
+    name = NEW_IDENTIFIER(CHILD(n, name_i));
+    if (!name)
+        return NULL;
+    else if (!forbidden_check(c, CHILD(n, name_i), STR(CHILD(n, name_i))))
+        return NULL;
+    args = ast_for_arguments(c, CHILD(n, name_i + 1));
+    if (!args)
+        return NULL;
+    if (TYPE(CHILD(n, name_i + 3)) == TYPE_COMMENT) {
+        type_comment = NEW_TYPE_COMMENT(CHILD(n, name_i + 3));
+        name_i += 1;
+    }
+    body = ast_for_suite(c, CHILD(n, name_i + 3));
+    if (!body)
+        return NULL;
+
+    if (!type_comment && NCH(CHILD(n, name_i + 3)) > 1) {
+        /* If the function doesn't have a type comment on the same line, check
+         * if the suite has a type comment in it. */
+        tc = CHILD(CHILD(n, name_i + 3), 1);
+
+        if (TYPE(tc) == TYPE_COMMENT)
+            type_comment = NEW_TYPE_COMMENT(tc);
+    }
+
+    return FunctionDef(name, args, body, decorator_seq, type_comment, LINENO(n),
+                       n->n_col_offset, c->c_arena);
+}
+
+static stmt_ty
+ast_for_decorated(struct compiling *c, const node *n)
+{
+    /* decorated: decorators (classdef | funcdef) */
+    stmt_ty thing = NULL;
+    asdl_seq *decorator_seq = NULL;
+
+    REQ(n, decorated);
+
+    decorator_seq = ast_for_decorators(c, CHILD(n, 0));
+    if (!decorator_seq)
+      return NULL;
+
+    assert(TYPE(CHILD(n, 1)) == funcdef ||
+           TYPE(CHILD(n, 1)) == classdef);
+
+    if (TYPE(CHILD(n, 1)) == funcdef) {
+      thing = ast_for_funcdef(c, CHILD(n, 1), decorator_seq);
+    } else if (TYPE(CHILD(n, 1)) == classdef) {
+      thing = ast_for_classdef(c, CHILD(n, 1), decorator_seq);
+    }
+    /* we count the decorators in when talking about the class' or
+       function's line number */
+    if (thing) {
+        thing->lineno = LINENO(n);
+        thing->col_offset = n->n_col_offset;
+    }
+    return thing;
+}
+
+static expr_ty
+ast_for_lambdef(struct compiling *c, const node *n)
+{
+    /* lambdef: 'lambda' [varargslist] ':' test */
+    arguments_ty args;
+    expr_ty expression;
+
+    if (NCH(n) == 3) {
+        args = arguments(NULL, NULL, NULL, NULL, NULL, c->c_arena);
+        if (!args)
+            return NULL;
+        expression = ast_for_expr(c, CHILD(n, 2));
+        if (!expression)
+            return NULL;
+    }
+    else {
+        args = ast_for_arguments(c, CHILD(n, 1));
+        if (!args)
+            return NULL;
+        expression = ast_for_expr(c, CHILD(n, 3));
+        if (!expression)
+            return NULL;
+    }
+
+    return Lambda(args, expression, LINENO(n), n->n_col_offset, c->c_arena);
+}
+
+static expr_ty
+ast_for_ifexpr(struct compiling *c, const node *n)
+{
+    /* test: or_test 'if' or_test 'else' test */
+    expr_ty expression, body, orelse;
+
+    assert(NCH(n) == 5);
+    body = ast_for_expr(c, CHILD(n, 0));
+    if (!body)
+        return NULL;
+    expression = ast_for_expr(c, CHILD(n, 2));
+    if (!expression)
+        return NULL;
+    orelse = ast_for_expr(c, CHILD(n, 4));
+    if (!orelse)
+        return NULL;
+    return IfExp(expression, body, orelse, LINENO(n), n->n_col_offset,
+                 c->c_arena);
+}
+
+/* XXX(nnorwitz): the listcomp and genexpr code should be refactored
+   so there is only a single version.  Possibly for loops can also re-use
+   the code.
+*/
+
+/* Count the number of 'for' loop in a list comprehension.
+
+   Helper for ast_for_listcomp().
+*/
+
+static int
+count_list_fors(struct compiling *c, const node *n)
+{
+    int n_fors = 0;
+    node *ch = CHILD(n, 1);
+
+ count_list_for:
+    n_fors++;
+    REQ(ch, list_for);
+    if (NCH(ch) == 5)
+        ch = CHILD(ch, 4);
+    else
+        return n_fors;
+ count_list_iter:
+    REQ(ch, list_iter);
+    ch = CHILD(ch, 0);
+    if (TYPE(ch) == list_for)
+        goto count_list_for;
+    else if (TYPE(ch) == list_if) {
+        if (NCH(ch) == 3) {
+            ch = CHILD(ch, 2);
+            goto count_list_iter;
+        }
+        else
+            return n_fors;
+    }
+
+    /* Should never be reached */
+    PyErr_SetString(PyExc_SystemError, "logic error in count_list_fors");
+    return -1;
+}
+
+/* Count the number of 'if' statements in a list comprehension.
+
+   Helper for ast_for_listcomp().
+*/
+
+static int
+count_list_ifs(struct compiling *c, const node *n)
+{
+    int n_ifs = 0;
+
+ count_list_iter:
+    REQ(n, list_iter);
+    if (TYPE(CHILD(n, 0)) == list_for)
+        return n_ifs;
+    n = CHILD(n, 0);
+    REQ(n, list_if);
+    n_ifs++;
+    if (NCH(n) == 2)
+        return n_ifs;
+    n = CHILD(n, 2);
+    goto count_list_iter;
+}
+
+static expr_ty
+ast_for_listcomp(struct compiling *c, const node *n)
+{
+    /* listmaker: test ( list_for | (',' test)* [','] )
+       list_for: 'for' exprlist 'in' testlist_safe [list_iter]
+       list_iter: list_for | list_if
+       list_if: 'if' test [list_iter]
+       testlist_safe: test [(',' test)+ [',']]
+    */
+    expr_ty elt, first;
+    asdl_seq *listcomps;
+    int i, n_fors;
+    node *ch;
+
+    REQ(n, listmaker);
+    assert(NCH(n) > 1);
+
+    elt = ast_for_expr(c, CHILD(n, 0));
+    if (!elt)
+        return NULL;
+
+    n_fors = count_list_fors(c, n);
+    if (n_fors == -1)
+        return NULL;
+
+    listcomps = asdl_seq_new(n_fors, c->c_arena);
+    if (!listcomps)
+        return NULL;
+
+    ch = CHILD(n, 1);
+    for (i = 0; i < n_fors; i++) {
+        comprehension_ty lc;
+        asdl_seq *t;
+        expr_ty expression;
+        node *for_ch;
+
+        REQ(ch, list_for);
+
+        for_ch = CHILD(ch, 1);
+        t = ast_for_exprlist(c, for_ch, Store);
+        if (!t)
+            return NULL;
+        expression = ast_for_testlist(c, CHILD(ch, 3));
+        if (!expression)
+            return NULL;
+
+        /* Check the # of children rather than the length of t, since
+           [x for x, in ... ] has 1 element in t, but still requires a Tuple.
+        */
+        first = (expr_ty)asdl_seq_GET(t, 0);
+        if (NCH(for_ch) == 1)
+            lc = comprehension(first, expression, NULL, c->c_arena);
+        else
+            lc = comprehension(Tuple(t, Store, first->lineno, first->col_offset,
+                                     c->c_arena),
+                               expression, NULL, c->c_arena);
+        if (!lc)
+            return NULL;
+
+        if (NCH(ch) == 5) {
+            int j, n_ifs;
+            asdl_seq *ifs;
+            expr_ty list_for_expr;
+
+            ch = CHILD(ch, 4);
+            n_ifs = count_list_ifs(c, ch);
+            if (n_ifs == -1)
+                return NULL;
+
+            ifs = asdl_seq_new(n_ifs, c->c_arena);
+            if (!ifs)
+                return NULL;
+
+            for (j = 0; j < n_ifs; j++) {
+                REQ(ch, list_iter);
+                ch = CHILD(ch, 0);
+                REQ(ch, list_if);
+
+                list_for_expr = ast_for_expr(c, CHILD(ch, 1));
+                if (!list_for_expr)
+                    return NULL;
+
+                asdl_seq_SET(ifs, j, list_for_expr);
+                if (NCH(ch) == 3)
+                    ch = CHILD(ch, 2);
+            }
+            /* on exit, must guarantee that ch is a list_for */
+            if (TYPE(ch) == list_iter)
+                ch = CHILD(ch, 0);
+            lc->ifs = ifs;
+        }
+        asdl_seq_SET(listcomps, i, lc);
+    }
+
+    return ListComp(elt, listcomps, LINENO(n), n->n_col_offset, c->c_arena);
+}
+
+/*
+   Count the number of 'for' loops in a comprehension.
+
+   Helper for ast_for_comprehension().
+*/
+
+static int
+count_comp_fors(struct compiling *c, const node *n)
+{
+    int n_fors = 0;
+
+  count_comp_for:
+    n_fors++;
+    REQ(n, comp_for);
+    if (NCH(n) == 5)
+        n = CHILD(n, 4);
+    else
+        return n_fors;
+  count_comp_iter:
+    REQ(n, comp_iter);
+    n = CHILD(n, 0);
+    if (TYPE(n) == comp_for)
+        goto count_comp_for;
+    else if (TYPE(n) == comp_if) {
+        if (NCH(n) == 3) {
+            n = CHILD(n, 2);
+            goto count_comp_iter;
+        }
+        else
+            return n_fors;
+    }
+
+    /* Should never be reached */
+    PyErr_SetString(PyExc_SystemError,
+                    "logic error in count_comp_fors");
+    return -1;
+}
+
+/* Count the number of 'if' statements in a comprehension.
+
+   Helper for ast_for_comprehension().
+*/
+
+static int
+count_comp_ifs(struct compiling *c, const node *n)
+{
+    int n_ifs = 0;
+
+    while (1) {
+        REQ(n, comp_iter);
+        if (TYPE(CHILD(n, 0)) == comp_for)
+            return n_ifs;
+        n = CHILD(n, 0);
+        REQ(n, comp_if);
+        n_ifs++;
+        if (NCH(n) == 2)
+            return n_ifs;
+        n = CHILD(n, 2);
+    }
+}
+
+static asdl_seq *
+ast_for_comprehension(struct compiling *c, const node *n)
+{
+    int i, n_fors;
+    asdl_seq *comps;
+
+    n_fors = count_comp_fors(c, n);
+    if (n_fors == -1)
+        return NULL;
+
+    comps = asdl_seq_new(n_fors, c->c_arena);
+    if (!comps)
+        return NULL;
+
+    for (i = 0; i < n_fors; i++) {
+        comprehension_ty comp;
+        asdl_seq *t;
+        expr_ty expression, first;
+        node *for_ch;
+
+        REQ(n, comp_for);
+
+        for_ch = CHILD(n, 1);
+        t = ast_for_exprlist(c, for_ch, Store);
+        if (!t)
+            return NULL;
+        expression = ast_for_expr(c, CHILD(n, 3));
+        if (!expression)
+            return NULL;
+
+        /* Check the # of children rather than the length of t, since
+           (x for x, in ...) has 1 element in t, but still requires a Tuple. */
+        first = (expr_ty)asdl_seq_GET(t, 0);
+        if (NCH(for_ch) == 1)
+            comp = comprehension(first, expression, NULL, c->c_arena);
+        else
+            comp = comprehension(Tuple(t, Store, first->lineno, first->col_offset,
+                                     c->c_arena),
+                               expression, NULL, c->c_arena);
+        if (!comp)
+            return NULL;
+
+        if (NCH(n) == 5) {
+            int j, n_ifs;
+            asdl_seq *ifs;
+
+            n = CHILD(n, 4);
+            n_ifs = count_comp_ifs(c, n);
+            if (n_ifs == -1)
+                return NULL;
+
+            ifs = asdl_seq_new(n_ifs, c->c_arena);
+            if (!ifs)
+                return NULL;
+
+            for (j = 0; j < n_ifs; j++) {
+                REQ(n, comp_iter);
+                n = CHILD(n, 0);
+                REQ(n, comp_if);
+
+                expression = ast_for_expr(c, CHILD(n, 1));
+                if (!expression)
+                    return NULL;
+                asdl_seq_SET(ifs, j, expression);
+                if (NCH(n) == 3)
+                    n = CHILD(n, 2);
+            }
+            /* on exit, must guarantee that n is a comp_for */
+            if (TYPE(n) == comp_iter)
+                n = CHILD(n, 0);
+            comp->ifs = ifs;
+        }
+        asdl_seq_SET(comps, i, comp);
+    }
+    return comps;
+}
+
+static expr_ty
+ast_for_itercomp(struct compiling *c, const node *n, int type)
+{
+    expr_ty elt;
+    asdl_seq *comps;
+
+    assert(NCH(n) > 1);
+
+    elt = ast_for_expr(c, CHILD(n, 0));
+    if (!elt)
+        return NULL;
+
+    comps = ast_for_comprehension(c, CHILD(n, 1));
+    if (!comps)
+        return NULL;
+
+    if (type == COMP_GENEXP)
+        return GeneratorExp(elt, comps, LINENO(n), n->n_col_offset, c->c_arena);
+    else if (type == COMP_SETCOMP)
+        return SetComp(elt, comps, LINENO(n), n->n_col_offset, c->c_arena);
+    else
+        /* Should never happen */
+        return NULL;
+}
+
+static expr_ty
+ast_for_dictcomp(struct compiling *c, const node *n)
+{
+    expr_ty key, value;
+    asdl_seq *comps;
+
+    assert(NCH(n) > 3);
+    REQ(CHILD(n, 1), COLON);
+
+    key = ast_for_expr(c, CHILD(n, 0));
+    if (!key)
+        return NULL;
+
+    value = ast_for_expr(c, CHILD(n, 2));
+    if (!value)
+        return NULL;
+
+    comps = ast_for_comprehension(c, CHILD(n, 3));
+    if (!comps)
+        return NULL;
+
+    return DictComp(key, value, comps, LINENO(n), n->n_col_offset, c->c_arena);
+}
+
+static expr_ty
+ast_for_genexp(struct compiling *c, const node *n)
+{
+    assert(TYPE(n) == (testlist_comp) || TYPE(n) == (argument));
+    return ast_for_itercomp(c, n, COMP_GENEXP);
+}
+
+static expr_ty
+ast_for_setcomp(struct compiling *c, const node *n)
+{
+    assert(TYPE(n) == (dictorsetmaker));
+    return ast_for_itercomp(c, n, COMP_SETCOMP);
+}
+
+static expr_ty
+ast_for_atom(struct compiling *c, const node *n)
+{
+    /* atom: '(' [yield_expr|testlist_comp] ')' | '[' [listmaker] ']'
+       | '{' [dictmaker] '}' | '`' testlist '`' | NAME | NUMBER | STRING+
+    */
+    node *ch = CHILD(n, 0);
+
+    switch (TYPE(ch)) {
+    case NAME: {
+        /* All names start in Load context, but may later be
+           changed. */
+        PyObject *name = NEW_IDENTIFIER(ch);
+        if (!name)
+            return NULL;
+        return Name(name, Load, LINENO(n), n->n_col_offset, c->c_arena);
+    }
+    case STRING: {
+        PyObject *str = parsestrplus(c, n);
+        if (!str) {
+#ifdef Py_USING_UNICODE
+            if (PyErr_ExceptionMatches(PyExc_UnicodeError)){
+                PyObject *type, *value, *tback, *errstr;
+                PyErr_Fetch(&type, &value, &tback);
+                errstr = PyObject_Str(value);
+                if (errstr) {
+                    char *s = "";
+                    char buf[128];
+                    s = _PyUnicode_AsString(errstr);
+                    PyOS_snprintf(buf, sizeof(buf), "(unicode error) %s", s);
+                    ast_error(n, buf);
+                    Py_DECREF(errstr);
+                } else {
+                    ast_error(n, "(unicode error) unknown error");
+                }
+                Py_DECREF(type);
+                Py_DECREF(value);
+                Py_XDECREF(tback);
+            }
+#endif
+            return NULL;
+        }
+        PyArena_AddPyObject(c->c_arena, str);
+        return Str(str, LINENO(n), n->n_col_offset, c->c_arena);
+    }
+    case NUMBER: {
+        PyObject *pynum = parsenumber(c, STR(ch));
+        if (!pynum)
+            return NULL;
+
+        PyArena_AddPyObject(c->c_arena, pynum);
+        return Num(pynum, LINENO(n), n->n_col_offset, c->c_arena);
+    }
+    case LPAR: /* some parenthesized expressions */
+        ch = CHILD(n, 1);
+
+        if (TYPE(ch) == RPAR)
+            return Tuple(NULL, Load, LINENO(n), n->n_col_offset, c->c_arena);
+
+        if (TYPE(ch) == yield_expr)
+            return ast_for_expr(c, ch);
+
+        return ast_for_testlist_comp(c, ch);
+    case LSQB: /* list (or list comprehension) */
+        ch = CHILD(n, 1);
+
+        if (TYPE(ch) == RSQB)
+            return List(NULL, Load, LINENO(n), n->n_col_offset, c->c_arena);
+
+        REQ(ch, listmaker);
+        if (NCH(ch) == 1 || TYPE(CHILD(ch, 1)) == COMMA) {
+            asdl_seq *elts = seq_for_testlist(c, ch);
+            if (!elts)
+                return NULL;
+
+            return List(elts, Load, LINENO(n), n->n_col_offset, c->c_arena);
+        }
+        else
+            return ast_for_listcomp(c, ch);
+    case LBRACE: {
+        /* dictorsetmaker:
+         *    (test ':' test (comp_for | (',' test ':' test)* [','])) |
+         *    (test (comp_for | (',' test)* [',']))
+         */
+        int i, size;
+        asdl_seq *keys, *values;
+
+        ch = CHILD(n, 1);
+        if (TYPE(ch) == RBRACE) {
+            /* it's an empty dict */
+            return Dict(NULL, NULL, LINENO(n), n->n_col_offset, c->c_arena);
+        } else if (NCH(ch) == 1 || TYPE(CHILD(ch, 1)) == COMMA) {
+            /* it's a simple set */
+            asdl_seq *elts;
+            size = (NCH(ch) + 1) / 2; /* +1 in case no trailing comma */
+            elts = asdl_seq_new(size, c->c_arena);
+            if (!elts)
+                return NULL;
+            for (i = 0; i < NCH(ch); i += 2) {
+                expr_ty expression;
+                expression = ast_for_expr(c, CHILD(ch, i));
+                if (!expression)
+                    return NULL;
+                asdl_seq_SET(elts, i / 2, expression);
+            }
+            return Set(elts, LINENO(n), n->n_col_offset, c->c_arena);
+        } else if (TYPE(CHILD(ch, 1)) == comp_for) {
+            /* it's a set comprehension */
+            return ast_for_setcomp(c, ch);
+        } else if (NCH(ch) > 3 && TYPE(CHILD(ch, 3)) == comp_for) {
+            return ast_for_dictcomp(c, ch);
+        } else {
+            /* it's a dict */
+            size = (NCH(ch) + 1) / 4; /* +1 in case no trailing comma */
+            keys = asdl_seq_new(size, c->c_arena);
+            if (!keys)
+                return NULL;
+
+            values = asdl_seq_new(size, c->c_arena);
+            if (!values)
+                return NULL;
+
+            for (i = 0; i < NCH(ch); i += 4) {
+                expr_ty expression;
+
+                expression = ast_for_expr(c, CHILD(ch, i));
+                if (!expression)
+                    return NULL;
+
+                asdl_seq_SET(keys, i / 4, expression);
+
+                expression = ast_for_expr(c, CHILD(ch, i + 2));
+                if (!expression)
+                    return NULL;
+
+                asdl_seq_SET(values, i / 4, expression);
+            }
+            return Dict(keys, values, LINENO(n), n->n_col_offset, c->c_arena);
+        }
+    }
+    case BACKQUOTE: { /* repr */
+        expr_ty expression;
+        if (Py_Py3kWarningFlag &&
+            !ast_warn(c, n, "backquote not supported in 3.x; use repr()"))
+            return NULL;
+        expression = ast_for_testlist(c, CHILD(n, 1));
+        if (!expression)
+            return NULL;
+
+        return Repr(expression, LINENO(n), n->n_col_offset, c->c_arena);
+    }
+    default:
+        PyErr_Format(PyExc_SystemError, "unhandled atom %d", TYPE(ch));
+        return NULL;
+    }
+}
+
+static slice_ty
+ast_for_slice(struct compiling *c, const node *n)
+{
+    node *ch;
+    expr_ty lower = NULL, upper = NULL, step = NULL;
+
+    REQ(n, subscript);
+
+    /*
+       subscript: '.' '.' '.' | test | [test] ':' [test] [sliceop]
+       sliceop: ':' [test]
+    */
+    ch = CHILD(n, 0);
+    if (TYPE(ch) == DOT)
+        return Ellipsis(c->c_arena);
+
+    if (NCH(n) == 1 && TYPE(ch) == test) {
+        /* 'step' variable hold no significance in terms of being used over
+           other vars */
+        step = ast_for_expr(c, ch);
+        if (!step)
+            return NULL;
+
+        return Index(step, c->c_arena);
+    }
+
+    if (TYPE(ch) == test) {
+        lower = ast_for_expr(c, ch);
+        if (!lower)
+            return NULL;
+    }
+
+    /* If there's an upper bound it's in the second or third position. */
+    if (TYPE(ch) == COLON) {
+        if (NCH(n) > 1) {
+            node *n2 = CHILD(n, 1);
+
+            if (TYPE(n2) == test) {
+                upper = ast_for_expr(c, n2);
+                if (!upper)
+                    return NULL;
+            }
+        }
+    } else if (NCH(n) > 2) {
+        node *n2 = CHILD(n, 2);
+
+        if (TYPE(n2) == test) {
+            upper = ast_for_expr(c, n2);
+            if (!upper)
+                return NULL;
+        }
+    }
+
+    ch = CHILD(n, NCH(n) - 1);
+    if (TYPE(ch) == sliceop) {
+        if (NCH(ch) == 1) {
+            /*
+              This is an extended slice (ie "x[::]") with no expression in the
+              step field. We set this literally to "None" in order to
+              disambiguate it from x[:]. (The interpreter might have to call
+              __getslice__ for x[:], but it must call __getitem__ for x[::].)
+            */
+            identifier none = new_identifier("None", c->c_arena);
+            if (!none)
+                return NULL;
+            ch = CHILD(ch, 0);
+            step = Name(none, Load, LINENO(ch), ch->n_col_offset, c->c_arena);
+            if (!step)
+                return NULL;
+        } else {
+            ch = CHILD(ch, 1);
+            if (TYPE(ch) == test) {
+                step = ast_for_expr(c, ch);
+                if (!step)
+                    return NULL;
+            }
+        }
+    }
+
+    return Slice(lower, upper, step, c->c_arena);
+}
+
+static expr_ty
+ast_for_binop(struct compiling *c, const node *n)
+{
+        /* Must account for a sequence of expressions.
+           How should A op B op C by represented?
+           BinOp(BinOp(A, op, B), op, C).
+        */
+
+        int i, nops;
+        expr_ty expr1, expr2, result;
+        operator_ty newoperator;
+
+        expr1 = ast_for_expr(c, CHILD(n, 0));
+        if (!expr1)
+            return NULL;
+
+        expr2 = ast_for_expr(c, CHILD(n, 2));
+        if (!expr2)
+            return NULL;
+
+        newoperator = get_operator(CHILD(n, 1));
+        if (!newoperator)
+            return NULL;
+
+        result = BinOp(expr1, newoperator, expr2, LINENO(n), n->n_col_offset,
+                       c->c_arena);
+        if (!result)
+            return NULL;
+
+        nops = (NCH(n) - 1) / 2;
+        for (i = 1; i < nops; i++) {
+                expr_ty tmp_result, tmp;
+                const node* next_oper = CHILD(n, i * 2 + 1);
+
+                newoperator = get_operator(next_oper);
+                if (!newoperator)
+                    return NULL;
+
+                tmp = ast_for_expr(c, CHILD(n, i * 2 + 2));
+                if (!tmp)
+                    return NULL;
+
+                tmp_result = BinOp(result, newoperator, tmp,
+                                   LINENO(next_oper), next_oper->n_col_offset,
+                                   c->c_arena);
+                if (!tmp_result)
+                        return NULL;
+                result = tmp_result;
+        }
+        return result;
+}
+
+static expr_ty
+ast_for_trailer(struct compiling *c, const node *n, expr_ty left_expr)
+{
+    /* trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME
+       subscriptlist: subscript (',' subscript)* [',']
+       subscript: '.' '.' '.' | test | [test] ':' [test] [sliceop]
+     */
+    REQ(n, trailer);
+    if (TYPE(CHILD(n, 0)) == LPAR) {
+        if (NCH(n) == 2)
+            return Call(left_expr, NULL, NULL, NULL, NULL, LINENO(n),
+                        n->n_col_offset, c->c_arena);
+        else
+            return ast_for_call(c, CHILD(n, 1), left_expr);
+    }
+    else if (TYPE(CHILD(n, 0)) == DOT ) {
+        PyObject *attr_id = NEW_IDENTIFIER(CHILD(n, 1));
+        if (!attr_id)
+            return NULL;
+        return Attribute(left_expr, attr_id, Load,
+                         LINENO(n), n->n_col_offset, c->c_arena);
+    }
+    else {
+        REQ(CHILD(n, 0), LSQB);
+        REQ(CHILD(n, 2), RSQB);
+        n = CHILD(n, 1);
+        if (NCH(n) == 1) {
+            slice_ty slc = ast_for_slice(c, CHILD(n, 0));
+            if (!slc)
+                return NULL;
+            return Subscript(left_expr, slc, Load, LINENO(n), n->n_col_offset,
+                             c->c_arena);
+        }
+        else {
+            /* The grammar is ambiguous here. The ambiguity is resolved
+               by treating the sequence as a tuple literal if there are
+               no slice features.
+            */
+            int j;
+            slice_ty slc;
+            expr_ty e;
+            bool simple = true;
+            asdl_seq *slices, *elts;
+            slices = asdl_seq_new((NCH(n) + 1) / 2, c->c_arena);
+            if (!slices)
+                return NULL;
+            for (j = 0; j < NCH(n); j += 2) {
+                slc = ast_for_slice(c, CHILD(n, j));
+                if (!slc)
+                    return NULL;
+                if (slc->kind != Index_kind)
+                    simple = false;
+                asdl_seq_SET(slices, j / 2, slc);
+            }
+            if (!simple) {
+                return Subscript(left_expr, ExtSlice(slices, c->c_arena),
+                                 Load, LINENO(n), n->n_col_offset, c->c_arena);
+            }
+            /* extract Index values and put them in a Tuple */
+            elts = asdl_seq_new(asdl_seq_LEN(slices), c->c_arena);
+            if (!elts)
+                return NULL;
+            for (j = 0; j < asdl_seq_LEN(slices); ++j) {
+                slc = (slice_ty)asdl_seq_GET(slices, j);
+                assert(slc->kind == Index_kind  && slc->v.Index.value);
+                asdl_seq_SET(elts, j, slc->v.Index.value);
+            }
+            e = Tuple(elts, Load, LINENO(n), n->n_col_offset, c->c_arena);
+            if (!e)
+                return NULL;
+            return Subscript(left_expr, Index(e, c->c_arena),
+                             Load, LINENO(n), n->n_col_offset, c->c_arena);
+        }
+    }
+}
+
+static expr_ty
+ast_for_factor(struct compiling *c, const node *n)
+{
+    node *pfactor, *ppower, *patom, *pnum;
+    expr_ty expression;
+
+    /* If the unary - operator is applied to a constant, don't generate
+       a UNARY_NEGATIVE opcode.  Just store the approriate value as a
+       constant.  The peephole optimizer already does something like
+       this but it doesn't handle the case where the constant is
+       (sys.maxint - 1).  In that case, we want a PyIntObject, not a
+       PyLongObject.
+    */
+    if (TYPE(CHILD(n, 0)) == MINUS &&
+        NCH(n) == 2 &&
+        TYPE((pfactor = CHILD(n, 1))) == factor &&
+        NCH(pfactor) == 1 &&
+        TYPE((ppower = CHILD(pfactor, 0))) == power &&
+        NCH(ppower) == 1 &&
+        TYPE((patom = CHILD(ppower, 0))) == atom &&
+        TYPE((pnum = CHILD(patom, 0))) == NUMBER) {
+        PyObject *pynum;
+        char *s = PyObject_MALLOC(strlen(STR(pnum)) + 2);
+        if (s == NULL)
+            return NULL;
+        s[0] = '-';
+        strcpy(s + 1, STR(pnum));
+        pynum = parsenumber(c, s);
+        PyObject_FREE(s);
+        if (!pynum)
+            return NULL;
+
+        PyArena_AddPyObject(c->c_arena, pynum);
+        return Num(pynum, LINENO(n), n->n_col_offset, c->c_arena);
+    }
+
+    expression = ast_for_expr(c, CHILD(n, 1));
+    if (!expression)
+        return NULL;
+
+    switch (TYPE(CHILD(n, 0))) {
+        case PLUS:
+            return UnaryOp(UAdd, expression, LINENO(n), n->n_col_offset,
+                           c->c_arena);
+        case MINUS:
+            return UnaryOp(USub, expression, LINENO(n), n->n_col_offset,
+                           c->c_arena);
+        case TILDE:
+            return UnaryOp(Invert, expression, LINENO(n),
+                           n->n_col_offset, c->c_arena);
+    }
+    PyErr_Format(PyExc_SystemError, "unhandled factor: %d",
+                 TYPE(CHILD(n, 0)));
+    return NULL;
+}
+
+static expr_ty
+ast_for_power(struct compiling *c, const node *n)
+{
+    /* power: atom trailer* ('**' factor)*
+     */
+    int i;
+    expr_ty e, tmp;
+    REQ(n, power);
+    e = ast_for_atom(c, CHILD(n, 0));
+    if (!e)
+        return NULL;
+    if (NCH(n) == 1)
+        return e;
+    for (i = 1; i < NCH(n); i++) {
+        node *ch = CHILD(n, i);
+        if (TYPE(ch) != trailer)
+            break;
+        tmp = ast_for_trailer(c, ch, e);
+        if (!tmp)
+            return NULL;
+        tmp->lineno = e->lineno;
+        tmp->col_offset = e->col_offset;
+        e = tmp;
+    }
+    if (TYPE(CHILD(n, NCH(n) - 1)) == factor) {
+        expr_ty f = ast_for_expr(c, CHILD(n, NCH(n) - 1));
+        if (!f)
+            return NULL;
+        tmp = BinOp(e, Pow, f, LINENO(n), n->n_col_offset, c->c_arena);
+        if (!tmp)
+            return NULL;
+        e = tmp;
+    }
+    return e;
+}
+
+/* Do not name a variable 'expr'!  Will cause a compile error.
+*/
+
+static expr_ty
+ast_for_expr(struct compiling *c, const node *n)
+{
+    /* handle the full range of simple expressions
+       test: or_test ['if' or_test 'else' test] | lambdef
+       or_test: and_test ('or' and_test)*
+       and_test: not_test ('and' not_test)*
+       not_test: 'not' not_test | comparison
+       comparison: expr (comp_op expr)*
+       expr: xor_expr ('|' xor_expr)*
+       xor_expr: and_expr ('^' and_expr)*
+       and_expr: shift_expr ('&' shift_expr)*
+       shift_expr: arith_expr (('<<'|'>>') arith_expr)*
+       arith_expr: term (('+'|'-') term)*
+       term: factor (('*'|'/'|'%'|'//') factor)*
+       factor: ('+'|'-'|'~') factor | power
+       power: atom trailer* ('**' factor)*
+
+       As well as modified versions that exist for backward compatibility,
+       to explicitly allow:
+       [ x for x in lambda: 0, lambda: 1 ]
+       (which would be ambiguous without these extra rules)
+
+       old_test: or_test | old_lambdef
+       old_lambdef: 'lambda' [vararglist] ':' old_test
+
+    */
+
+    asdl_seq *seq;
+    int i;
+
+ loop:
+    switch (TYPE(n)) {
+        case test:
+        case old_test:
+            if (TYPE(CHILD(n, 0)) == lambdef ||
+                TYPE(CHILD(n, 0)) == old_lambdef)
+                return ast_for_lambdef(c, CHILD(n, 0));
+            else if (NCH(n) > 1)
+                return ast_for_ifexpr(c, n);
+            /* Fallthrough */
+        case or_test:
+        case and_test:
+            if (NCH(n) == 1) {
+                n = CHILD(n, 0);
+                goto loop;
+            }
+            seq = asdl_seq_new((NCH(n) + 1) / 2, c->c_arena);
+            if (!seq)
+                return NULL;
+            for (i = 0; i < NCH(n); i += 2) {
+                expr_ty e = ast_for_expr(c, CHILD(n, i));
+                if (!e)
+                    return NULL;
+                asdl_seq_SET(seq, i / 2, e);
+            }
+            if (!strcmp(STR(CHILD(n, 1)), "and"))
+                return BoolOp(And, seq, LINENO(n), n->n_col_offset,
+                              c->c_arena);
+            assert(!strcmp(STR(CHILD(n, 1)), "or"));
+            return BoolOp(Or, seq, LINENO(n), n->n_col_offset, c->c_arena);
+        case not_test:
+            if (NCH(n) == 1) {
+                n = CHILD(n, 0);
+                goto loop;
+            }
+            else {
+                expr_ty expression = ast_for_expr(c, CHILD(n, 1));
+                if (!expression)
+                    return NULL;
+
+                return UnaryOp(Not, expression, LINENO(n), n->n_col_offset,
+                               c->c_arena);
+            }
+        case comparison:
+            if (NCH(n) == 1) {
+                n = CHILD(n, 0);
+                goto loop;
+            }
+            else {
+                expr_ty expression;
+                asdl_int_seq *ops;
+                asdl_seq *cmps;
+                ops = asdl_int_seq_new(NCH(n) / 2, c->c_arena);
+                if (!ops)
+                    return NULL;
+                cmps = asdl_seq_new(NCH(n) / 2, c->c_arena);
+                if (!cmps) {
+                    return NULL;
+                }
+                for (i = 1; i < NCH(n); i += 2) {
+                    cmpop_ty newoperator;
+
+                    newoperator = ast_for_comp_op(c, CHILD(n, i));
+                    if (!newoperator) {
+                        return NULL;
+                    }
+
+                    expression = ast_for_expr(c, CHILD(n, i + 1));
+                    if (!expression) {
+                        return NULL;
+                    }
+
+                    asdl_seq_SET(ops, i / 2, newoperator);
+                    asdl_seq_SET(cmps, i / 2, expression);
+                }
+                expression = ast_for_expr(c, CHILD(n, 0));
+                if (!expression) {
+                    return NULL;
+                }
+
+                return Compare(expression, ops, cmps, LINENO(n),
+                               n->n_col_offset, c->c_arena);
+            }
+            break;
+
+        /* The next five cases all handle BinOps.  The main body of code
+           is the same in each case, but the switch turned inside out to
+           reuse the code for each type of operator.
+         */
+        case expr:
+        case xor_expr:
+        case and_expr:
+        case shift_expr:
+        case arith_expr:
+        case term:
+            if (NCH(n) == 1) {
+                n = CHILD(n, 0);
+                goto loop;
+            }
+            return ast_for_binop(c, n);
+        case yield_expr: {
+            expr_ty exp = NULL;
+            if (NCH(n) == 2) {
+                exp = ast_for_testlist(c, CHILD(n, 1));
+                if (!exp)
+                    return NULL;
+            }
+            return Yield(exp, LINENO(n), n->n_col_offset, c->c_arena);
+        }
+        case factor:
+            if (NCH(n) == 1) {
+                n = CHILD(n, 0);
+                goto loop;
+            }
+            return ast_for_factor(c, n);
+        case power:
+            return ast_for_power(c, n);
+        default:
+            PyErr_Format(PyExc_SystemError, "unhandled expr: %d", TYPE(n));
+            return NULL;
+    }
+    /* should never get here unless if error is set */
+    return NULL;
+}
+
+static expr_ty
+ast_for_call(struct compiling *c, const node *n, expr_ty func)
+{
+    /*
+      arglist: (argument ',')* (argument [',']| '*' test [',' '**' test]
+               | '**' test)
+      argument: [test '='] test [comp_for]        # Really [keyword '='] test
+    */
+
+    int i, nargs, nkeywords, ngens;
+    asdl_seq *args;
+    asdl_seq *keywords;
+    expr_ty vararg = NULL, kwarg = NULL;
+
+    REQ(n, arglist);
+
+    nargs = 0;
+    nkeywords = 0;
+    ngens = 0;
+    for (i = 0; i < NCH(n); i++) {
+        node *ch = CHILD(n, i);
+        if (TYPE(ch) == argument) {
+            if (NCH(ch) == 1)
+                nargs++;
+            else if (TYPE(CHILD(ch, 1)) == comp_for)
+                ngens++;
+            else
+                nkeywords++;
+        }
+    }
+    if (ngens > 1 || (ngens && (nargs || nkeywords))) {
+        ast_error(n, "Generator expression must be parenthesized "
+                  "if not sole argument");
+        return NULL;
+    }
+
+    if (nargs + nkeywords + ngens > 255) {
+      ast_error(n, "more than 255 arguments");
+      return NULL;
+    }
+
+    args = asdl_seq_new(nargs + ngens, c->c_arena);
+    if (!args)
+        return NULL;
+    keywords = asdl_seq_new(nkeywords, c->c_arena);
+    if (!keywords)
+        return NULL;
+    nargs = 0;
+    nkeywords = 0;
+    for (i = 0; i < NCH(n); i++) {
+        node *ch = CHILD(n, i);
+        if (TYPE(ch) == argument) {
+            expr_ty e;
+            if (NCH(ch) == 1) {
+                if (nkeywords) {
+                    ast_error(CHILD(ch, 0),
+                              "non-keyword arg after keyword arg");
+                    return NULL;
+                }
+                if (vararg) {
+                    ast_error(CHILD(ch, 0),
+                              "only named arguments may follow *expression");
+                    return NULL;
+                }
+                e = ast_for_expr(c, CHILD(ch, 0));
+                if (!e)
+                    return NULL;
+                asdl_seq_SET(args, nargs++, e);
+            }
+            else if (TYPE(CHILD(ch, 1)) == comp_for) {
+                e = ast_for_genexp(c, ch);
+                if (!e)
+                    return NULL;
+                asdl_seq_SET(args, nargs++, e);
+            }
+            else {
+                keyword_ty kw;
+                identifier key;
+                int k;
+                char *tmp;
+
+                /* CHILD(ch, 0) is test, but must be an identifier? */
+                e = ast_for_expr(c, CHILD(ch, 0));
+                if (!e)
+                    return NULL;
+                /* f(lambda x: x[0] = 3) ends up getting parsed with
+                 * LHS test = lambda x: x[0], and RHS test = 3.
+                 * SF bug 132313 points out that complaining about a keyword
+                 * then is very confusing.
+                 */
+                if (e->kind == Lambda_kind) {
+                    ast_error(CHILD(ch, 0),
+                              "lambda cannot contain assignment");
+                    return NULL;
+                } else if (e->kind != Name_kind) {
+                    ast_error(CHILD(ch, 0), "keyword can't be an expression");
+                    return NULL;
+                }
+                key = e->v.Name.id;
+                if (!forbidden_check(c, CHILD(ch, 0), PyBytes_AS_STRING(key)))
+                    return NULL;
+                for (k = 0; k < nkeywords; k++) {
+                    tmp = _PyUnicode_AsString(
+                        ((keyword_ty)asdl_seq_GET(keywords, k))->arg);
+                    if (!strcmp(tmp, _PyUnicode_AsString(key))) {
+                        ast_error(CHILD(ch, 0), "keyword argument repeated");
+                        return NULL;
+                    }
+                }
+                e = ast_for_expr(c, CHILD(ch, 2));
+                if (!e)
+                    return NULL;
+                kw = keyword(key, e, c->c_arena);
+                if (!kw)
+                    return NULL;
+                asdl_seq_SET(keywords, nkeywords++, kw);
+            }
+        }
+        else if (TYPE(ch) == STAR) {
+            vararg = ast_for_expr(c, CHILD(n, i+1));
+            if (!vararg)
+                return NULL;
+            i++;
+        }
+        else if (TYPE(ch) == DOUBLESTAR) {
+            kwarg = ast_for_expr(c, CHILD(n, i+1));
+            if (!kwarg)
+                return NULL;
+            i++;
+        }
+    }
+
+    return Call(func, args, keywords, vararg, kwarg, func->lineno,
+                func->col_offset, c->c_arena);
+}
+
+static expr_ty
+ast_for_testlist(struct compiling *c, const node* n)
+{
+    /* testlist_comp: test (',' test)* [','] */
+    /* testlist: test (',' test)* [','] */
+    /* testlist_safe: test (',' test)+ [','] */
+    /* testlist1: test (',' test)* */
+    assert(NCH(n) > 0);
+    if (TYPE(n) == testlist_comp) {
+        if (NCH(n) > 1)
+            assert(TYPE(CHILD(n, 1)) != comp_for);
+    }
+    else {
+        assert(TYPE(n) == testlist ||
+               TYPE(n) == testlist_safe ||
+               TYPE(n) == testlist1);
+    }
+    if (NCH(n) == 1)
+        return ast_for_expr(c, CHILD(n, 0));
+    else {
+        asdl_seq *tmp = seq_for_testlist(c, n);
+        if (!tmp)
+            return NULL;
+        return Tuple(tmp, Load, LINENO(n), n->n_col_offset, c->c_arena);
+    }
+}
+
+static expr_ty
+ast_for_testlist_comp(struct compiling *c, const node* n)
+{
+    /* testlist_comp: test ( comp_for | (',' test)* [','] ) */
+    /* argument: test [ comp_for ] */
+    assert(TYPE(n) == testlist_comp || TYPE(n) == argument);
+    if (NCH(n) > 1 && TYPE(CHILD(n, 1)) == comp_for)
+        return ast_for_genexp(c, n);
+    return ast_for_testlist(c, n);
+}
+
+/* like ast_for_testlist() but returns a sequence */
+static asdl_seq*
+ast_for_class_bases(struct compiling *c, const node* n)
+{
+    /* testlist: test (',' test)* [','] */
+    assert(NCH(n) > 0);
+    REQ(n, testlist);
+    if (NCH(n) == 1) {
+        expr_ty base;
+        asdl_seq *bases = asdl_seq_new(1, c->c_arena);
+        if (!bases)
+            return NULL;
+        base = ast_for_expr(c, CHILD(n, 0));
+        if (!base)
+            return NULL;
+        asdl_seq_SET(bases, 0, base);
+        return bases;
+    }
+
+    return seq_for_testlist(c, n);
+}
+
+static stmt_ty
+ast_for_expr_stmt(struct compiling *c, const node *n)
+{
+    REQ(n, expr_stmt);
+    /* expr_stmt: testlist (augassign (yield_expr|testlist)
+                | ('=' (yield_expr|testlist))* [TYPE_COMMENT])
+       testlist: test (',' test)* [',']
+       augassign: '+=' | '-=' | '*=' | '/=' | '%=' | '&=' | '|=' | '^='
+                | '<<=' | '>>=' | '**=' | '//='
+       test: ... here starts the operator precendence dance
+     */
+    int num = NCH(n);
+
+    if (num == 1 || (num == 2 && TYPE(CHILD(n, 1)) == TYPE_COMMENT)) {
+        expr_ty e = ast_for_testlist(c, CHILD(n, 0));
+        if (!e)
+            return NULL;
+
+        return Expr(e, LINENO(n), n->n_col_offset, c->c_arena);
+    }
+    else if (TYPE(CHILD(n, 1)) == augassign) {
+        expr_ty expr1, expr2;
+        operator_ty newoperator;
+        node *ch = CHILD(n, 0);
+
+        expr1 = ast_for_testlist(c, ch);
+        if (!expr1)
+            return NULL;
+        if(!set_context(c, expr1, Store, ch))
+            return NULL;
+        /* set_context checks that most expressions are not the left side.
+          Augmented assignments can only have a name, a subscript, or an
+          attribute on the left, though, so we have to explicitly check for
+          those. */
+        switch (expr1->kind) {
+            case Name_kind:
+            case Attribute_kind:
+            case Subscript_kind:
+                break;
+            default:
+                ast_error(ch, "illegal expression for augmented assignment");
+                return NULL;
+        }
+
+        ch = CHILD(n, 2);
+        if (TYPE(ch) == testlist)
+            expr2 = ast_for_testlist(c, ch);
+        else
+            expr2 = ast_for_expr(c, ch);
+        if (!expr2)
+            return NULL;
+
+        newoperator = ast_for_augassign(c, CHILD(n, 1));
+        if (!newoperator)
+            return NULL;
+
+        return AugAssign(expr1, newoperator, expr2, LINENO(n), n->n_col_offset,
+                         c->c_arena);
+    }
+    else {
+        int i, nch_minus_type, has_type_comment;
+        asdl_seq *targets;
+        node *value;
+        expr_ty expression;
+        string type_comment;
+
+        /* a normal assignment */
+        REQ(CHILD(n, 1), EQUAL);
+
+        has_type_comment = TYPE(CHILD(n, num - 1)) == TYPE_COMMENT;
+        nch_minus_type = num - has_type_comment;
+
+        targets = asdl_seq_new(nch_minus_type / 2, c->c_arena);
+        if (!targets)
+            return NULL;
+        for (i = 0; i < nch_minus_type - 2; i += 2) {
+            expr_ty e;
+            node *ch = CHILD(n, i);
+            if (TYPE(ch) == yield_expr) {
+                ast_error(ch, "assignment to yield expression not possible");
+                return NULL;
+            }
+            e = ast_for_testlist(c, ch);
+            if (!e)
+                return NULL;
+
+            /* set context to assign */
+            if (!set_context(c, e, Store, CHILD(n, i)))
+                return NULL;
+
+            asdl_seq_SET(targets, i / 2, e);
+        }
+        value = CHILD(n, nch_minus_type - 1);
+        if (TYPE(value) == testlist)
+            expression = ast_for_testlist(c, value);
+        else
+            expression = ast_for_expr(c, value);
+        if (!expression)
+            return NULL;
+        if (has_type_comment)
+            type_comment = NEW_TYPE_COMMENT(CHILD(n, nch_minus_type));
+        else
+            type_comment = NULL;
+        return Assign(targets, expression, type_comment, LINENO(n), n->n_col_offset,
+                      c->c_arena);
+    }
+}
+
+static stmt_ty
+ast_for_print_stmt(struct compiling *c, const node *n)
+{
+    /* print_stmt: 'print' ( [ test (',' test)* [','] ]
+                             | '>>' test [ (',' test)+ [','] ] )
+     */
+    expr_ty dest = NULL, expression;
+    asdl_seq *seq = NULL;
+    bool nl;
+    int i, j, values_count, start = 1;
+
+    REQ(n, print_stmt);
+    if (NCH(n) >= 2 && TYPE(CHILD(n, 1)) == RIGHTSHIFT) {
+        dest = ast_for_expr(c, CHILD(n, 2));
+        if (!dest)
+            return NULL;
+            start = 4;
+    }
+    values_count = (NCH(n) + 1 - start) / 2;
+    if (values_count) {
+        seq = asdl_seq_new(values_count, c->c_arena);
+        if (!seq)
+            return NULL;
+        for (i = start, j = 0; i < NCH(n); i += 2, ++j) {
+            expression = ast_for_expr(c, CHILD(n, i));
+            if (!expression)
+                return NULL;
+            asdl_seq_SET(seq, j, expression);
+        }
+    }
+    nl = (TYPE(CHILD(n, NCH(n) - 1)) == COMMA) ? false : true;
+    return Print(dest, seq, nl, LINENO(n), n->n_col_offset, c->c_arena);
+}
+
+static asdl_seq *
+ast_for_exprlist(struct compiling *c, const node *n, expr_context_ty context)
+{
+    asdl_seq *seq;
+    int i;
+    expr_ty e;
+
+    REQ(n, exprlist);
+
+    seq = asdl_seq_new((NCH(n) + 1) / 2, c->c_arena);
+    if (!seq)
+        return NULL;
+    for (i = 0; i < NCH(n); i += 2) {
+        e = ast_for_expr(c, CHILD(n, i));
+        if (!e)
+            return NULL;
+        asdl_seq_SET(seq, i / 2, e);
+        if (context && !set_context(c, e, context, CHILD(n, i)))
+            return NULL;
+    }
+    return seq;
+}
+
+static stmt_ty
+ast_for_del_stmt(struct compiling *c, const node *n)
+{
+    asdl_seq *expr_list;
+
+    /* del_stmt: 'del' exprlist */
+    REQ(n, del_stmt);
+
+    expr_list = ast_for_exprlist(c, CHILD(n, 1), Del);
+    if (!expr_list)
+        return NULL;
+    return Delete(expr_list, LINENO(n), n->n_col_offset, c->c_arena);
+}
+
+static stmt_ty
+ast_for_flow_stmt(struct compiling *c, const node *n)
+{
+    /*
+      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_expr
+      yield_expr: 'yield' testlist
+      raise_stmt: 'raise' [test [',' test [',' test]]]
+    */
+    node *ch;
+
+    REQ(n, flow_stmt);
+    ch = CHILD(n, 0);
+    switch (TYPE(ch)) {
+        case break_stmt:
+            return Break(LINENO(n), n->n_col_offset, c->c_arena);
+        case continue_stmt:
+            return Continue(LINENO(n), n->n_col_offset, c->c_arena);
+        case yield_stmt: { /* will reduce to yield_expr */
+            expr_ty exp = ast_for_expr(c, CHILD(ch, 0));
+            if (!exp)
+                return NULL;
+            return Expr(exp, LINENO(n), n->n_col_offset, c->c_arena);
+        }
+        case return_stmt:
+            if (NCH(ch) == 1)
+                return Return(NULL, LINENO(n), n->n_col_offset, c->c_arena);
+            else {
+                expr_ty expression = ast_for_testlist(c, CHILD(ch, 1));
+                if (!expression)
+                    return NULL;
+                return Return(expression, LINENO(n), n->n_col_offset,
+                              c->c_arena);
+            }
+        case raise_stmt:
+            if (NCH(ch) == 1)
+                return Raise(NULL, NULL, NULL, LINENO(n), n->n_col_offset,
+                             c->c_arena);
+            else if (NCH(ch) == 2) {
+                expr_ty expression = ast_for_expr(c, CHILD(ch, 1));
+                if (!expression)
+                    return NULL;
+                return Raise(expression, NULL, NULL, LINENO(n),
+                             n->n_col_offset, c->c_arena);
+            }
+            else if (NCH(ch) == 4) {
+                expr_ty expr1, expr2;
+
+                expr1 = ast_for_expr(c, CHILD(ch, 1));
+                if (!expr1)
+                    return NULL;
+                expr2 = ast_for_expr(c, CHILD(ch, 3));
+                if (!expr2)
+                    return NULL;
+
+                return Raise(expr1, expr2, NULL, LINENO(n), n->n_col_offset,
+                             c->c_arena);
+            }
+            else if (NCH(ch) == 6) {
+                expr_ty expr1, expr2, expr3;
+
+                expr1 = ast_for_expr(c, CHILD(ch, 1));
+                if (!expr1)
+                    return NULL;
+                expr2 = ast_for_expr(c, CHILD(ch, 3));
+                if (!expr2)
+                    return NULL;
+                expr3 = ast_for_expr(c, CHILD(ch, 5));
+                if (!expr3)
+                    return NULL;
+
+                return Raise(expr1, expr2, expr3, LINENO(n), n->n_col_offset,
+                             c->c_arena);
+            }
+        default:
+            PyErr_Format(PyExc_SystemError,
+                         "unexpected flow_stmt: %d", TYPE(ch));
+            return NULL;
+    }
+}
+
+static alias_ty
+alias_for_import_name(struct compiling *c, const node *n, int store)
+{
+    /*
+      import_as_name: NAME ['as' NAME]
+      dotted_as_name: dotted_name ['as' NAME]
+      dotted_name: NAME ('.' NAME)*
+    */
+    PyObject *str, *name;
+
+ loop:
+    switch (TYPE(n)) {
+         case import_as_name: {
+            node *name_node = CHILD(n, 0);
+            str = NULL;
+            if (NCH(n) == 3) {
+                node *str_node = CHILD(n, 2);
+                if (store && !forbidden_check(c, str_node, STR(str_node)))
+                    return NULL;
+                str = NEW_IDENTIFIER(str_node);
+                if (!str)
+                    return NULL;
+            }
+            else {
+                if (!forbidden_check(c, name_node, STR(name_node)))
+                    return NULL;
+            }
+            name = NEW_IDENTIFIER(name_node);
+            if (!name)
+                return NULL;
+            return alias(name, str, c->c_arena);
+        }
+        case dotted_as_name:
+            if (NCH(n) == 1) {
+                n = CHILD(n, 0);
+                goto loop;
+            }
+            else {
+                node *asname_node = CHILD(n, 2);
+                alias_ty a = alias_for_import_name(c, CHILD(n, 0), 0);
+                if (!a)
+                    return NULL;
+                assert(!a->asname);
+                if (!forbidden_check(c, asname_node, STR(asname_node)))
+                    return NULL;
+                a->asname = NEW_IDENTIFIER(asname_node);
+                if (!a->asname)
+                    return NULL;
+                return a;
+            }
+            break;
+        case dotted_name:
+            if (NCH(n) == 1) {
+                node *name_node = CHILD(n, 0);
+                if (store && !forbidden_check(c, name_node, STR(name_node)))
+                    return NULL;
+                name = NEW_IDENTIFIER(name_node);
+                if (!name)
+                    return NULL;
+                return alias(name, NULL, c->c_arena);
+            }
+            else {
+                /* Create a string of the form "a.b.c" */
+                int i;
+                size_t len;
+                char *s;
+                PyObject *uni;
+
+                len = 0;
+                for (i = 0; i < NCH(n); i += 2)
+                    /* length of string plus one for the dot */
+                    len += strlen(STR(CHILD(n, i))) + 1;
+                len--; /* the last name doesn't have a dot */
+                str = PyBytes_FromStringAndSize(NULL, len);
+                if (!str)
+                    return NULL;
+                s = PyBytes_AS_STRING(str);
+                if (!s)
+                    return NULL;
+                for (i = 0; i < NCH(n); i += 2) {
+                    char *sch = STR(CHILD(n, i));
+                    strcpy(s, STR(CHILD(n, i)));
+                    s += strlen(sch);
+                    *s++ = '.';
+                }
+                --s;
+                *s = '\0';
+                uni = PyUnicode_DecodeUTF8(PyBytes_AS_STRING(str),
+                                           PyBytes_GET_SIZE(str),
+                                           NULL);
+                Py_DECREF(str);
+                if (!uni)
+                    return NULL;
+                str = uni;
+                PyUnicode_InternInPlace(&str);
+                if (PyArena_AddPyObject(c->c_arena, str) < 0) {
+                    Py_DECREF(str);
+                    return NULL;
+                }
+                return alias(str, NULL, c->c_arena);
+            }
+            break;
+        case STAR:
+            str = PyUnicode_InternFromString("*");
+            if (PyArena_AddPyObject(c->c_arena, str) < 0) {
+                Py_DECREF(str);
+                return NULL;
+            }
+            return alias(str, NULL, c->c_arena);
+        default:
+            PyErr_Format(PyExc_SystemError,
+                         "unexpected import name: %d", TYPE(n));
+            return NULL;
+    }
+
+    PyErr_SetString(PyExc_SystemError, "unhandled import name condition");
+    return NULL;
+}
+
+static stmt_ty
+ast_for_import_stmt(struct compiling *c, const node *n)
+{
+    /*
+      import_stmt: import_name | import_from
+      import_name: 'import' dotted_as_names
+      import_from: 'from' ('.'* dotted_name | '.') 'import'
+                          ('*' | '(' import_as_names ')' | import_as_names)
+    */
+    int lineno;
+    int col_offset;
+    int i;
+    asdl_seq *aliases;
+
+    REQ(n, import_stmt);
+    lineno = LINENO(n);
+    col_offset = n->n_col_offset;
+    n = CHILD(n, 0);
+    if (TYPE(n) == import_name) {
+        n = CHILD(n, 1);
+        REQ(n, dotted_as_names);
+        aliases = asdl_seq_new((NCH(n) + 1) / 2, c->c_arena);
+        if (!aliases)
+            return NULL;
+        for (i = 0; i < NCH(n); i += 2) {
+            alias_ty import_alias = alias_for_import_name(c, CHILD(n, i), 1);
+            if (!import_alias)
+                return NULL;
+            asdl_seq_SET(aliases, i / 2, import_alias);
+        }
+        return Import(aliases, lineno, col_offset, c->c_arena);
+    }
+    else if (TYPE(n) == import_from) {
+        int n_children;
+        int idx, ndots = 0;
+        alias_ty mod = NULL;
+        identifier modname = NULL;
+
+       /* Count the number of dots (for relative imports) and check for the
+          optional module name */
+        for (idx = 1; idx < NCH(n); idx++) {
+            if (TYPE(CHILD(n, idx)) == dotted_name) {
+                mod = alias_for_import_name(c, CHILD(n, idx), 0);
+                if (!mod)
+                    return NULL;
+                idx++;
+                break;
+            } else if (TYPE(CHILD(n, idx)) != DOT) {
+                break;
+            }
+            ndots++;
+        }
+        idx++; /* skip over the 'import' keyword */
+        switch (TYPE(CHILD(n, idx))) {
+        case STAR:
+            /* from ... import * */
+            n = CHILD(n, idx);
+            n_children = 1;
+            break;
+        case LPAR:
+            /* from ... import (x, y, z) */
+            n = CHILD(n, idx + 1);
+            n_children = NCH(n);
+            break;
+        case import_as_names:
+            /* from ... import x, y, z */
+            n = CHILD(n, idx);
+            n_children = NCH(n);
+            if (n_children % 2 == 0) {
+                ast_error(n, "trailing comma not allowed without"
+                             " surrounding parentheses");
+                return NULL;
+            }
+            break;
+        default:
+            ast_error(n, "Unexpected node-type in from-import");
+            return NULL;
+        }
+
+        aliases = asdl_seq_new((n_children + 1) / 2, c->c_arena);
+        if (!aliases)
+            return NULL;
+
+        /* handle "from ... import *" special b/c there's no children */
+        if (TYPE(n) == STAR) {
+            alias_ty import_alias = alias_for_import_name(c, n, 1);
+            if (!import_alias)
+                return NULL;
+                asdl_seq_SET(aliases, 0, import_alias);
+        }
+        else {
+            for (i = 0; i < NCH(n); i += 2) {
+                alias_ty import_alias = alias_for_import_name(c, CHILD(n, i), 1);
+                if (!import_alias)
+                    return NULL;
+                    asdl_seq_SET(aliases, i / 2, import_alias);
+            }
+        }
+        if (mod != NULL)
+            modname = mod->name;
+        return ImportFrom(modname, aliases, ndots, lineno, col_offset,
+                          c->c_arena);
+    }
+    PyErr_Format(PyExc_SystemError,
+                 "unknown import statement: starts with command '%s'",
+                 STR(CHILD(n, 0)));
+    return NULL;
+}
+
+static stmt_ty
+ast_for_global_stmt(struct compiling *c, const node *n)
+{
+    /* global_stmt: 'global' NAME (',' NAME)* */
+    identifier name;
+    asdl_seq *s;
+    int i;
+
+    REQ(n, global_stmt);
+    s = asdl_seq_new(NCH(n) / 2, c->c_arena);
+    if (!s)
+        return NULL;
+    for (i = 1; i < NCH(n); i += 2) {
+        name = NEW_IDENTIFIER(CHILD(n, i));
+        if (!name)
+            return NULL;
+        asdl_seq_SET(s, i / 2, name);
+    }
+    return Global(s, LINENO(n), n->n_col_offset, c->c_arena);
+}
+
+static stmt_ty
+ast_for_exec_stmt(struct compiling *c, const node *n)
+{
+    expr_ty expr1, globals = NULL, locals = NULL;
+    int n_children = NCH(n);
+    if (n_children != 2 && n_children != 4 && n_children != 6) {
+        PyErr_Format(PyExc_SystemError,
+                     "poorly formed 'exec' statement: %d parts to statement",
+                     n_children);
+        return NULL;
+    }
+
+    /* exec_stmt: 'exec' expr ['in' test [',' test]] */
+    REQ(n, exec_stmt);
+    expr1 = ast_for_expr(c, CHILD(n, 1));
+    if (!expr1)
+        return NULL;
+
+    if (expr1->kind == Tuple_kind && n_children < 4 &&
+        (asdl_seq_LEN(expr1->v.Tuple.elts) == 2 ||
+         asdl_seq_LEN(expr1->v.Tuple.elts) == 3)) {
+        /* Backwards compatibility: passing exec args as a tuple */
+        globals = asdl_seq_GET(expr1->v.Tuple.elts, 1);
+        if (asdl_seq_LEN(expr1->v.Tuple.elts) == 3) {
+            locals = asdl_seq_GET(expr1->v.Tuple.elts, 2);
+        }
+        expr1 = asdl_seq_GET(expr1->v.Tuple.elts, 0);
+    }
+
+    if (n_children >= 4) {
+        globals = ast_for_expr(c, CHILD(n, 3));
+        if (!globals)
+            return NULL;
+    }
+    if (n_children == 6) {
+        locals = ast_for_expr(c, CHILD(n, 5));
+        if (!locals)
+            return NULL;
+    }
+
+    return Exec(expr1, globals, locals, LINENO(n), n->n_col_offset,
+                c->c_arena);
+}
+
+static stmt_ty
+ast_for_assert_stmt(struct compiling *c, const node *n)
+{
+    /* assert_stmt: 'assert' test [',' test] */
+    REQ(n, assert_stmt);
+    if (NCH(n) == 2) {
+        expr_ty expression = ast_for_expr(c, CHILD(n, 1));
+        if (!expression)
+            return NULL;
+        return Assert(expression, NULL, LINENO(n), n->n_col_offset,
+                      c->c_arena);
+    }
+    else if (NCH(n) == 4) {
+        expr_ty expr1, expr2;
+
+        expr1 = ast_for_expr(c, CHILD(n, 1));
+        if (!expr1)
+            return NULL;
+        expr2 = ast_for_expr(c, CHILD(n, 3));
+        if (!expr2)
+            return NULL;
+
+        return Assert(expr1, expr2, LINENO(n), n->n_col_offset, c->c_arena);
+    }
+    PyErr_Format(PyExc_SystemError,
+                 "improper number of parts to 'assert' statement: %d",
+                 NCH(n));
+    return NULL;
+}
+
+static asdl_seq *
+ast_for_suite(struct compiling *c, const node *n)
+{
+    /* suite: simple_stmt | NEWLINE [TYPE_COMMENT NEWLINE] INDENT stmt+ DEDENT */
+    asdl_seq *seq;
+    stmt_ty s;
+    int i, total, num, end, pos = 0;
+    node *ch;
+
+    REQ(n, suite);
+
+    total = num_stmts(n);
+    seq = asdl_seq_new(total, c->c_arena);
+    if (!seq)
+        return NULL;
+    if (TYPE(CHILD(n, 0)) == simple_stmt) {
+        n = CHILD(n, 0);
+        /* simple_stmt always ends with a NEWLINE,
+           and may have a trailing SEMI
+        */
+        end = NCH(n) - 1;
+        if (TYPE(CHILD(n, end - 1)) == SEMI)
+            end--;
+        /* loop by 2 to skip semi-colons */
+        for (i = 0; i < end; i += 2) {
+            ch = CHILD(n, i);
+            s = ast_for_stmt(c, ch);
+            if (!s)
+                return NULL;
+            asdl_seq_SET(seq, pos++, s);
+        }
+    }
+    else {
+        i = 2;
+        if (TYPE(CHILD(n, 1)) == TYPE_COMMENT)
+            i += 2;
+
+        for (; i < (NCH(n) - 1); i++) {
+            ch = CHILD(n, i);
+            REQ(ch, stmt);
+            num = num_stmts(ch);
+            if (num == 1) {
+                /* small_stmt or compound_stmt with only one child */
+                s = ast_for_stmt(c, ch);
+                if (!s)
+                    return NULL;
+                asdl_seq_SET(seq, pos++, s);
+            }
+            else {
+                int j;
+                ch = CHILD(ch, 0);
+                REQ(ch, simple_stmt);
+                for (j = 0; j < NCH(ch); j += 2) {
+                    /* statement terminates with a semi-colon ';' */
+                    if (NCH(CHILD(ch, j)) == 0) {
+                        assert((j + 1) == NCH(ch));
+                        break;
+                    }
+                    s = ast_for_stmt(c, CHILD(ch, j));
+                    if (!s)
+                        return NULL;
+                    asdl_seq_SET(seq, pos++, s);
+                }
+            }
+        }
+    }
+    assert(pos == seq->size);
+    return seq;
+}
+
+static stmt_ty
+ast_for_if_stmt(struct compiling *c, const node *n)
+{
+    /* if_stmt: 'if' test ':' suite ('elif' test ':' suite)*
+       ['else' ':' suite]
+    */
+    char *s;
+
+    REQ(n, if_stmt);
+
+    if (NCH(n) == 4) {
+        expr_ty expression;
+        asdl_seq *suite_seq;
+
+        expression = ast_for_expr(c, CHILD(n, 1));
+        if (!expression)
+            return NULL;
+        suite_seq = ast_for_suite(c, CHILD(n, 3));
+        if (!suite_seq)
+            return NULL;
+
+        return If(expression, suite_seq, NULL, LINENO(n), n->n_col_offset,
+                  c->c_arena);
+    }
+
+    s = STR(CHILD(n, 4));
+    /* s[2], the third character in the string, will be
+       's' for el_s_e, or
+       'i' for el_i_f
+    */
+    if (s[2] == 's') {
+        expr_ty expression;
+        asdl_seq *seq1, *seq2;
+
+        expression = ast_for_expr(c, CHILD(n, 1));
+        if (!expression)
+            return NULL;
+        seq1 = ast_for_suite(c, CHILD(n, 3));
+        if (!seq1)
+            return NULL;
+        seq2 = ast_for_suite(c, CHILD(n, 6));
+        if (!seq2)
+            return NULL;
+
+        return If(expression, seq1, seq2, LINENO(n), n->n_col_offset,
+                  c->c_arena);
+    }
+    else if (s[2] == 'i') {
+        int i, n_elif, has_else = 0;
+        expr_ty expression;
+        asdl_seq *suite_seq;
+        asdl_seq *orelse = NULL;
+        n_elif = NCH(n) - 4;
+        /* must reference the child n_elif+1 since 'else' token is third,
+           not fourth, child from the end. */
+        if (TYPE(CHILD(n, (n_elif + 1))) == NAME
+            && STR(CHILD(n, (n_elif + 1)))[2] == 's') {
+            has_else = 1;
+            n_elif -= 3;
+        }
+        n_elif /= 4;
+
+        if (has_else) {
+            asdl_seq *suite_seq2;
+
+            orelse = asdl_seq_new(1, c->c_arena);
+            if (!orelse)
+                return NULL;
+            expression = ast_for_expr(c, CHILD(n, NCH(n) - 6));
+            if (!expression)
+                return NULL;
+            suite_seq = ast_for_suite(c, CHILD(n, NCH(n) - 4));
+            if (!suite_seq)
+                return NULL;
+            suite_seq2 = ast_for_suite(c, CHILD(n, NCH(n) - 1));
+            if (!suite_seq2)
+                return NULL;
+
+            asdl_seq_SET(orelse, 0,
+                         If(expression, suite_seq, suite_seq2,
+                            LINENO(CHILD(n, NCH(n) - 6)),
+                            CHILD(n, NCH(n) - 6)->n_col_offset,
+                            c->c_arena));
+            /* the just-created orelse handled the last elif */
+            n_elif--;
+        }
+
+        for (i = 0; i < n_elif; i++) {
+            int off = 5 + (n_elif - i - 1) * 4;
+            asdl_seq *newobj = asdl_seq_new(1, c->c_arena);
+            if (!newobj)
+                return NULL;
+            expression = ast_for_expr(c, CHILD(n, off));
+            if (!expression)
+                return NULL;
+            suite_seq = ast_for_suite(c, CHILD(n, off + 2));
+            if (!suite_seq)
+                return NULL;
+
+            asdl_seq_SET(newobj, 0,
+                         If(expression, suite_seq, orelse,
+                            LINENO(CHILD(n, off)),
+                            CHILD(n, off)->n_col_offset, c->c_arena));
+            orelse = newobj;
+        }
+        expression = ast_for_expr(c, CHILD(n, 1));
+        if (!expression)
+            return NULL;
+        suite_seq = ast_for_suite(c, CHILD(n, 3));
+        if (!suite_seq)
+            return NULL;
+        return If(expression, suite_seq, orelse,
+                  LINENO(n), n->n_col_offset, c->c_arena);
+    }
+
+    PyErr_Format(PyExc_SystemError,
+                 "unexpected token in 'if' statement: %s", s);
+    return NULL;
+}
+
+static stmt_ty
+ast_for_while_stmt(struct compiling *c, const node *n)
+{
+    /* while_stmt: 'while' test ':' suite ['else' ':' suite] */
+    REQ(n, while_stmt);
+
+    if (NCH(n) == 4) {
+        expr_ty expression;
+        asdl_seq *suite_seq;
+
+        expression = ast_for_expr(c, CHILD(n, 1));
+        if (!expression)
+            return NULL;
+        suite_seq = ast_for_suite(c, CHILD(n, 3));
+        if (!suite_seq)
+            return NULL;
+        return While(expression, suite_seq, NULL, LINENO(n), n->n_col_offset,
+                     c->c_arena);
+    }
+    else if (NCH(n) == 7) {
+        expr_ty expression;
+        asdl_seq *seq1, *seq2;
+
+        expression = ast_for_expr(c, CHILD(n, 1));
+        if (!expression)
+            return NULL;
+        seq1 = ast_for_suite(c, CHILD(n, 3));
+        if (!seq1)
+            return NULL;
+        seq2 = ast_for_suite(c, CHILD(n, 6));
+        if (!seq2)
+            return NULL;
+
+        return While(expression, seq1, seq2, LINENO(n), n->n_col_offset,
+                     c->c_arena);
+    }
+
+    PyErr_Format(PyExc_SystemError,
+                 "wrong number of tokens for 'while' statement: %d",
+                 NCH(n));
+    return NULL;
+}
+
+static stmt_ty
+ast_for_for_stmt(struct compiling *c, const node *n)
+{
+    asdl_seq *_target, *seq = NULL, *suite_seq;
+    expr_ty expression;
+    expr_ty target, first;
+    const node *node_target;
+    int has_type_comment;
+    string type_comment;
+    /* for_stmt: 'for' exprlist 'in' testlist ':' [TYPE_COMMENT] suite ['else' ':' suite] */
+    REQ(n, for_stmt);
+
+    has_type_comment = TYPE(CHILD(n, 5)) == TYPE_COMMENT;
+
+    if (NCH(n) == 9 + has_type_comment) {
+        seq = ast_for_suite(c, CHILD(n, 8 + has_type_comment));
+        if (!seq)
+            return NULL;
+    }
+
+    node_target = CHILD(n, 1);
+    _target = ast_for_exprlist(c, node_target, Store);
+    if (!_target)
+        return NULL;
+    /* Check the # of children rather than the length of _target, since
+       for x, in ... has 1 element in _target, but still requires a Tuple. */
+    first = (expr_ty)asdl_seq_GET(_target, 0);
+    if (NCH(node_target) == 1)
+        target = first;
+    else
+        target = Tuple(_target, Store, first->lineno, first->col_offset, c->c_arena);
+
+    expression = ast_for_testlist(c, CHILD(n, 3));
+    if (!expression)
+        return NULL;
+    suite_seq = ast_for_suite(c, CHILD(n, 5 + has_type_comment));
+    if (!suite_seq)
+        return NULL;
+
+    if (has_type_comment)
+        type_comment = NEW_TYPE_COMMENT(CHILD(n, 5));
+    else
+        type_comment = NULL;
+
+    return For(target, expression, suite_seq, seq, type_comment, LINENO(n), n->n_col_offset,
+               c->c_arena);
+}
+
+static excepthandler_ty
+ast_for_except_clause(struct compiling *c, const node *exc, node *body)
+{
+    /* except_clause: 'except' [test [(',' | 'as') test]] */
+    REQ(exc, except_clause);
+    REQ(body, suite);
+
+    if (NCH(exc) == 1) {
+        asdl_seq *suite_seq = ast_for_suite(c, body);
+        if (!suite_seq)
+            return NULL;
+
+        return ExceptHandler(NULL, NULL, suite_seq, LINENO(exc),
+                             exc->n_col_offset, c->c_arena);
+    }
+    else if (NCH(exc) == 2) {
+        expr_ty expression;
+        asdl_seq *suite_seq;
+
+        expression = ast_for_expr(c, CHILD(exc, 1));
+        if (!expression)
+            return NULL;
+        suite_seq = ast_for_suite(c, body);
+        if (!suite_seq)
+            return NULL;
+
+        return ExceptHandler(expression, NULL, suite_seq, LINENO(exc),
+                             exc->n_col_offset, c->c_arena);
+    }
+    else if (NCH(exc) == 4) {
+        asdl_seq *suite_seq;
+        expr_ty expression;
+        expr_ty e = ast_for_expr(c, CHILD(exc, 3));
+        if (!e)
+            return NULL;
+        if (!set_context(c, e, Store, CHILD(exc, 3)))
+            return NULL;
+        expression = ast_for_expr(c, CHILD(exc, 1));
+        if (!expression)
+            return NULL;
+        suite_seq = ast_for_suite(c, body);
+        if (!suite_seq)
+            return NULL;
+
+        return ExceptHandler(expression, e, suite_seq, LINENO(exc),
+                             exc->n_col_offset, c->c_arena);
+    }
+
+    PyErr_Format(PyExc_SystemError,
+                 "wrong number of children for 'except' clause: %d",
+                 NCH(exc));
+    return NULL;
+}
+
+static stmt_ty
+ast_for_try_stmt(struct compiling *c, const node *n)
+{
+    const int nch = NCH(n);
+    int n_except = (nch - 3)/3;
+    asdl_seq *body, *orelse = NULL, *finally = NULL;
+
+    REQ(n, try_stmt);
+
+    body = ast_for_suite(c, CHILD(n, 2));
+    if (body == NULL)
+        return NULL;
+
+    if (TYPE(CHILD(n, nch - 3)) == NAME) {
+        if (strcmp(STR(CHILD(n, nch - 3)), "finally") == 0) {
+            if (nch >= 9 && TYPE(CHILD(n, nch - 6)) == NAME) {
+                /* we can assume it's an "else",
+                   because nch >= 9 for try-else-finally and
+                   it would otherwise have a type of except_clause */
+                orelse = ast_for_suite(c, CHILD(n, nch - 4));
+                if (orelse == NULL)
+                    return NULL;
+                n_except--;
+            }
+
+            finally = ast_for_suite(c, CHILD(n, nch - 1));
+            if (finally == NULL)
+                return NULL;
+            n_except--;
+        }
+        else {
+            /* we can assume it's an "else",
+               otherwise it would have a type of except_clause */
+            orelse = ast_for_suite(c, CHILD(n, nch - 1));
+            if (orelse == NULL)
+                return NULL;
+            n_except--;
+        }
+    }
+    else if (TYPE(CHILD(n, nch - 3)) != except_clause) {
+        ast_error(n, "malformed 'try' statement");
+        return NULL;
+    }
+
+    if (n_except > 0) {
+        int i;
+        stmt_ty except_st;
+        /* process except statements to create a try ... except */
+        asdl_seq *handlers = asdl_seq_new(n_except, c->c_arena);
+        if (handlers == NULL)
+            return NULL;
+
+        for (i = 0; i < n_except; i++) {
+            excepthandler_ty e = ast_for_except_clause(c, CHILD(n, 3 + i * 3),
+                                                       CHILD(n, 5 + i * 3));
+            if (!e)
+                return NULL;
+            asdl_seq_SET(handlers, i, e);
+        }
+
+        except_st = TryExcept(body, handlers, orelse, LINENO(n),
+                              n->n_col_offset, c->c_arena);
+        if (!finally)
+            return except_st;
+
+        /* if a 'finally' is present too, we nest the TryExcept within a
+           TryFinally to emulate try ... except ... finally */
+        body = asdl_seq_new(1, c->c_arena);
+        if (body == NULL)
+            return NULL;
+        asdl_seq_SET(body, 0, except_st);
+    }
+
+    /* must be a try ... finally (except clauses are in body, if any exist) */
+    assert(finally != NULL);
+    return TryFinally(body, finally, LINENO(n), n->n_col_offset, c->c_arena);
+}
+
+/* with_item: test ['as' expr] */
+static stmt_ty
+ast_for_with_item(struct compiling *c, const node *n, asdl_seq *content, string type_comment)
+{
+    expr_ty context_expr, optional_vars = NULL;
+
+    REQ(n, with_item);
+    context_expr = ast_for_expr(c, CHILD(n, 0));
+    if (!context_expr)
+        return NULL;
+    if (NCH(n) == 3) {
+        optional_vars = ast_for_expr(c, CHILD(n, 2));
+
+        if (!optional_vars) {
+            return NULL;
+        }
+        if (!set_context(c, optional_vars, Store, n)) {
+            return NULL;
+        }
+    }
+
+    return With(context_expr, optional_vars, content, type_comment, LINENO(n),
+                n->n_col_offset, c->c_arena);
+}
+
+/* with_stmt: 'with' with_item (',' with_item)*  ':' [TYPE_COMMENT] suite */
+static stmt_ty
+ast_for_with_stmt(struct compiling *c, const node *n)
+{
+    int i, has_type_comment;
+    stmt_ty ret;
+    asdl_seq *inner;
+    string type_comment;
+
+    REQ(n, with_stmt);
+
+    has_type_comment = TYPE(CHILD(n, NCH(n) - 2)) == TYPE_COMMENT;
+
+    /* process the with items inside-out */
+    i = NCH(n) - 1;
+    /* the suite of the innermost with item is the suite of the with stmt */
+    inner = ast_for_suite(c, CHILD(n, i));
+    if (!inner)
+        return NULL;
+
+    if (has_type_comment) {
+        type_comment = NEW_TYPE_COMMENT(CHILD(n, NCH(n) - 2));
+        i--;
+    } else
+        type_comment = NULL;
+
+
+    for (;;) {
+        i -= 2;
+        ret = ast_for_with_item(c, CHILD(n, i), inner, type_comment);
+        if (!ret)
+            return NULL;
+        /* was this the last item? */
+        if (i == 1)
+            break;
+        /* if not, wrap the result so far in a new sequence */
+        inner = asdl_seq_new(1, c->c_arena);
+        if (!inner)
+            return NULL;
+        asdl_seq_SET(inner, 0, ret);
+    }
+
+    return ret;
+}
+
+static stmt_ty
+ast_for_classdef(struct compiling *c, const node *n, asdl_seq *decorator_seq)
+{
+    /* classdef: 'class' NAME ['(' testlist ')'] ':' suite */
+    PyObject *classname;
+    asdl_seq *bases, *s;
+
+    REQ(n, classdef);
+
+    if (!forbidden_check(c, n, STR(CHILD(n, 1))))
+            return NULL;
+
+    if (NCH(n) == 4) {
+        s = ast_for_suite(c, CHILD(n, 3));
+        if (!s)
+            return NULL;
+        classname = NEW_IDENTIFIER(CHILD(n, 1));
+        if (!classname)
+            return NULL;
+        return ClassDef(classname, NULL, s, decorator_seq, LINENO(n),
+                        n->n_col_offset, c->c_arena);
+    }
+    /* check for empty base list */
+    if (TYPE(CHILD(n,3)) == RPAR) {
+        s = ast_for_suite(c, CHILD(n,5));
+        if (!s)
+            return NULL;
+        classname = NEW_IDENTIFIER(CHILD(n, 1));
+        if (!classname)
+            return NULL;
+        return ClassDef(classname, NULL, s, decorator_seq, LINENO(n),
+                        n->n_col_offset, c->c_arena);
+    }
+
+    /* else handle the base class list */
+    bases = ast_for_class_bases(c, CHILD(n, 3));
+    if (!bases)
+        return NULL;
+
+    s = ast_for_suite(c, CHILD(n, 6));
+    if (!s)
+        return NULL;
+    classname = NEW_IDENTIFIER(CHILD(n, 1));
+    if (!classname)
+        return NULL;
+    return ClassDef(classname, bases, s, decorator_seq,
+                    LINENO(n), n->n_col_offset, c->c_arena);
+}
+
+static stmt_ty
+ast_for_stmt(struct compiling *c, const node *n)
+{
+    if (TYPE(n) == stmt) {
+        assert(NCH(n) == 1);
+        n = CHILD(n, 0);
+    }
+    if (TYPE(n) == simple_stmt) {
+        assert(num_stmts(n) == 1);
+        n = CHILD(n, 0);
+    }
+    if (TYPE(n) == small_stmt) {
+        n = CHILD(n, 0);
+        /* small_stmt: expr_stmt | print_stmt  | del_stmt | pass_stmt
+                     | flow_stmt | import_stmt | global_stmt | exec_stmt
+                     | assert_stmt
+        */
+        switch (TYPE(n)) {
+            case expr_stmt:
+                return ast_for_expr_stmt(c, n);
+            case print_stmt:
+                return ast_for_print_stmt(c, n);
+            case del_stmt:
+                return ast_for_del_stmt(c, n);
+            case pass_stmt:
+                return Pass(LINENO(n), n->n_col_offset, c->c_arena);
+            case flow_stmt:
+                return ast_for_flow_stmt(c, n);
+            case import_stmt:
+                return ast_for_import_stmt(c, n);
+            case global_stmt:
+                return ast_for_global_stmt(c, n);
+            case exec_stmt:
+                return ast_for_exec_stmt(c, n);
+            case assert_stmt:
+                return ast_for_assert_stmt(c, n);
+            default:
+                PyErr_Format(PyExc_SystemError,
+                             "unhandled small_stmt: TYPE=%d NCH=%d\n",
+                             TYPE(n), NCH(n));
+                return NULL;
+        }
+    }
+    else {
+        /* compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt
+                        | funcdef | classdef | decorated
+        */
+        node *ch = CHILD(n, 0);
+        REQ(n, compound_stmt);
+        switch (TYPE(ch)) {
+            case if_stmt:
+                return ast_for_if_stmt(c, ch);
+            case while_stmt:
+                return ast_for_while_stmt(c, ch);
+            case for_stmt:
+                return ast_for_for_stmt(c, ch);
+            case try_stmt:
+                return ast_for_try_stmt(c, ch);
+            case with_stmt:
+                return ast_for_with_stmt(c, ch);
+            case funcdef:
+                return ast_for_funcdef(c, ch, NULL);
+            case classdef:
+                return ast_for_classdef(c, ch, NULL);
+            case decorated:
+                return ast_for_decorated(c, ch);
+            default:
+                PyErr_Format(PyExc_SystemError,
+                             "unhandled small_stmt: TYPE=%d NCH=%d\n",
+                             TYPE(n), NCH(n));
+                return NULL;
+        }
+    }
+}
+
+static PyObject *
+parsenumber(struct compiling *c, const char *s)
+{
+        const char *end;
+        long x;
+        double dx;
+#ifndef WITHOUT_COMPLEX
+        Py_complex complex;
+        int imflag;
+#endif
+
+        assert(s != NULL);
+        errno = 0;
+        end = s + strlen(s) - 1;
+#ifndef WITHOUT_COMPLEX
+        imflag = *end == 'j' || *end == 'J';
+#endif
+        if (*end == 'l' || *end == 'L') {
+                /* Make a copy without the trailing 'L' */
+                size_t len = end - s  + 1;
+                char *copy = malloc(len);
+                if (copy == NULL)
+                        return PyErr_NoMemory();
+                memcpy(copy, s, len);
+                copy[len - 1] = '\0';
+                PyObject *result = PyLong_FromString(copy, (char **)0, 0);
+                free(copy);
+                return result;
+        }
+        x = Ta27OS_strtol((char *)s, (char **)&end, 0);
+        if (*end == '\0') {
+                if (errno != 0)
+                        return PyLong_FromString((char *)s, (char **)0, 0);
+                return PyLong_FromLong(x);
+        }
+        /* XXX Huge floats may silently fail */
+#ifndef WITHOUT_COMPLEX
+        if (imflag) {
+                complex.real = 0.;
+                complex.imag = PyOS_string_to_double(s, (char **)&end, NULL);
+                if (complex.imag == -1.0 && PyErr_Occurred())
+                        return NULL;
+                return PyComplex_FromCComplex(complex);
+        }
+        else
+#endif
+        {
+                dx = PyOS_string_to_double(s, NULL, NULL);
+                if (dx == -1.0 && PyErr_Occurred())
+                        return NULL;
+                return PyFloat_FromDouble(dx);
+        }
+}
+
+/* adapted from Python 3.5.1 */
+static PyObject *
+decode_utf8(struct compiling *c, const char **sPtr, const char *end)
+{
+#ifndef Py_USING_UNICODE
+        Py_FatalError("decode_utf8 should not be called in this build.");
+        return NULL;
+#else
+    const char *s, *t;
+    t = s = *sPtr;
+    /* while (s < end && *s != '\\') s++; */ /* inefficient for u".." */
+    while (s < end && (*s & 0x80)) s++;
+    *sPtr = s;
+    return PyUnicode_DecodeUTF8(t, s - t, NULL);
+#endif
+}
+
+#ifdef Py_USING_UNICODE
+/* taken from Python 3.5.1 */
+static PyObject *
+decode_unicode(struct compiling *c, const char *s, size_t len, int rawmode, const char *encoding)
+{
+    PyObject *v, *u;
+    char *buf;
+    char *p;
+    const char *end;
+
+    if (encoding == NULL) {
+        u = NULL;
+    } else {
+        /* check for integer overflow */
+        if (len > PY_SIZE_MAX / 6)
+            return NULL;
+        /* "ä" (2 bytes) may become "\U000000E4" (10 bytes), or 1:5
+           "\ä" (3 bytes) may become "\u005c\U000000E4" (16 bytes), or ~1:6 */
+        u = PyBytes_FromStringAndSize((char *)NULL, len * 6);
+        if (u == NULL)
+            return NULL;
+        p = buf = PyBytes_AsString(u);
+        end = s + len;
+        while (s < end) {
+            if (*s == '\\') {
+                *p++ = *s++;
+                if (*s & 0x80) {
+                    strcpy(p, "u005c");
+                    p += 5;
+                }
+            }
+            if (*s & 0x80) { /* XXX inefficient */
+                PyObject *w;
+                int kind;
+                void *data;
+                Py_ssize_t len, i;
+                w = decode_utf8(c, &s, end);
+                if (w == NULL) {
+                    Py_DECREF(u);
+                    return NULL;
+                }
+                kind = PyUnicode_KIND(w);
+                data = PyUnicode_DATA(w);
+                len = PyUnicode_GET_LENGTH(w);
+                for (i = 0; i < len; i++) {
+                    Py_UCS4 chr = PyUnicode_READ(kind, data, i);
+                    sprintf(p, "\\U%08x", chr);
+                    p += 10;
+                }
+                /* Should be impossible to overflow */
+                assert(p - buf <= Py_SIZE(u));
+                Py_DECREF(w);
+            } else {
+                *p++ = *s++;
+            }
+        }
+        len = p - buf;
+        s = buf;
+    }
+    if (rawmode)
+        v = PyUnicode_DecodeRawUnicodeEscape(s, len, NULL);
+    else
+        v = PyUnicode_DecodeUnicodeEscape(s, len, NULL);
+    Py_XDECREF(u);
+    return v;
+}
+#endif
+
+/* s is a Python string literal, including the bracketing quote characters,
+ * and r &/or u prefixes (if any), and embedded escape sequences (if any).
+ * parsestr parses it, and returns the decoded Python string object.
+ */
+static PyObject *
+parsestr(struct compiling *c, const node *n, const char *s)
+{
+        size_t len, i;
+        int quote = Py_CHARMASK(*s);
+        int rawmode = 0;
+        int need_encoding;
+        int unicode = c->c_future_unicode;
+        int bytes = 0;
+
+        if (isalpha(quote) || quote == '_') {
+                if (quote == 'u' || quote == 'U') {
+                        quote = *++s;
+                        unicode = 1;
+                }
+                if (quote == 'b' || quote == 'B') {
+                        quote = *++s;
+                        unicode = 0;
+                        bytes = 1;
+                }
+                if (quote == 'r' || quote == 'R') {
+                        quote = *++s;
+                        rawmode = 1;
+                }
+        }
+        if (quote != '\'' && quote != '\"') {
+                PyErr_BadInternalCall();
+                return NULL;
+        }
+        s++;
+        len = strlen(s);
+        if (len > INT_MAX) {
+                PyErr_SetString(PyExc_OverflowError,
+                                "string to parse is too long");
+                return NULL;
+        }
+        if (s[--len] != quote) {
+                PyErr_BadInternalCall();
+                return NULL;
+        }
+        if (len >= 4 && s[0] == quote && s[1] == quote) {
+                s += 2;
+                len -= 2;
+                if (s[--len] != quote || s[--len] != quote) {
+                        PyErr_BadInternalCall();
+                        return NULL;
+                }
+        }
+        if (Py_Py3kWarningFlag && bytes) {
+            for (i = 0; i < len; i++) {
+                if ((unsigned char)s[i] > 127) {
+                    if (!ast_warn(c, n,
+                        "non-ascii bytes literals not supported in 3.x"))
+                        return NULL;
+                    break;
+                }
+            }
+        }
+#ifdef Py_USING_UNICODE
+        if (unicode || Py_UnicodeFlag) {
+                return decode_unicode(c, s, len, rawmode, c->c_encoding);
+        }
+#endif
+        need_encoding = (c->c_encoding != NULL &&
+                         strcmp(c->c_encoding, "utf-8") != 0 &&
+                         strcmp(c->c_encoding, "iso-8859-1") != 0);
+        if (rawmode || strchr(s, '\\') == NULL) {
+                if (need_encoding) {
+#ifndef Py_USING_UNICODE
+                        /* This should not happen - we never see any other
+                           encoding. */
+                        Py_FatalError(
+                            "cannot deal with encodings in this build.");
+#else
+                        PyObject *v, *u = PyUnicode_DecodeUTF8(s, len, NULL);
+                        if (u == NULL)
+                                return NULL;
+                        v = PyUnicode_AsEncodedString(u, c->c_encoding, NULL);
+                        Py_DECREF(u);
+                        return v;
+#endif
+                } else {
+                  return PyBytes_FromStringAndSize(s, len);
+                }
+        }
+
+        return PyBytes_DecodeEscape(s, len, NULL, 1,
+                                    need_encoding ? c->c_encoding : NULL);
+}
+
+/* Build a Python string object out of a STRING atom.  This takes care of
+ * compile-time literal catenation, calling parsestr() on each piece, and
+ * pasting the intermediate results together.
+ */
+static PyObject *
+parsestrplus(struct compiling *c, const node *n)
+{
+        PyObject *v;
+        int i;
+        REQ(CHILD(n, 0), STRING);
+        if ((v = parsestr(c, n, STR(CHILD(n, 0)))) != NULL) {
+                /* String literal concatenation */
+                for (i = 1; i < NCH(n); i++) {
+                        PyObject *s;
+                        s = parsestr(c, n, STR(CHILD(n, i)));
+                        if (s == NULL)
+                                goto onError;
+                        if (PyBytes_Check(v) && PyBytes_Check(s)) {
+                                PyBytes_ConcatAndDel(&v, s);
+                                if (v == NULL)
+                                    goto onError;
+                        }
+#ifdef Py_USING_UNICODE
+                        else {
+                                PyObject *temp;
+                                /* Python 2's PyUnicode_FromObject (which is
+                                 * called on the arguments to PyUnicode_Concat)
+                                 * automatically converts Bytes objects into
+                                 * Str objects, but in Python 3 it throws a
+                                 * syntax error.  To allow mixed literal
+                                 * concatenation e.g. "foo" u"bar" (which is
+                                 * valid in Python 2), we have to explicitly
+                                 * check for Bytes and convert manually. */
+                                if (PyBytes_Check(s)) {
+                                    temp = PyUnicode_FromEncodedObject(s, NULL, "strict");
+                                    Py_DECREF(s);
+                                    s = temp;
+                                }
+
+                                if (PyBytes_Check(v)) {
+                                    temp = PyUnicode_FromEncodedObject(v, NULL, "strict");
+                                    Py_DECREF(v);
+                                    v = temp;
+                                }
+
+                                temp = PyUnicode_Concat(v, s);
+                                Py_DECREF(s);
+                                Py_DECREF(v);
+                                v = temp;
+                                if (v == NULL)
+                                    goto onError;
+                        }
+#endif
+                }
+        }
+        return v;
+
+ onError:
+        Py_XDECREF(v);
+        return NULL;
+}
diff --git a/ast27/Python/graminit.c b/ast27/Python/graminit.c
new file mode 100644
index 0000000..c61ce80
--- /dev/null
+++ b/ast27/Python/graminit.c
@@ -0,0 +1,2337 @@
+/* Generated by Parser/pgen */
+
+#include "pgenheaders.h"
+#include "grammar.h"
+PyAPI_DATA(grammar) _Ta27Parser_Grammar;
+static arc arcs_0_0[3] = {
+    {2, 1},
+    {3, 1},
+    {4, 2},
+};
+static arc arcs_0_1[1] = {
+    {0, 1},
+};
+static arc arcs_0_2[1] = {
+    {2, 1},
+};
+static state states_0[3] = {
+    {3, arcs_0_0},
+    {1, arcs_0_1},
+    {1, arcs_0_2},
+};
+static arc arcs_1_0[3] = {
+    {2, 0},
+    {6, 0},
+    {7, 1},
+};
+static arc arcs_1_1[1] = {
+    {0, 1},
+};
+static state states_1[2] = {
+    {3, arcs_1_0},
+    {1, arcs_1_1},
+};
+static arc arcs_2_0[1] = {
+    {9, 1},
+};
+static arc arcs_2_1[2] = {
+    {2, 1},
+    {7, 2},
+};
+static arc arcs_2_2[1] = {
+    {0, 2},
+};
+static state states_2[3] = {
+    {1, arcs_2_0},
+    {2, arcs_2_1},
+    {1, arcs_2_2},
+};
+static arc arcs_3_0[1] = {
+    {11, 1},
+};
+static arc arcs_3_1[1] = {
+    {12, 2},
+};
+static arc arcs_3_2[2] = {
+    {13, 3},
+    {2, 4},
+};
+static arc arcs_3_3[2] = {
+    {14, 5},
+    {15, 6},
+};
+static arc arcs_3_4[1] = {
+    {0, 4},
+};
+static arc arcs_3_5[1] = {
+    {15, 6},
+};
+static arc arcs_3_6[1] = {
+    {2, 4},
+};
+static state states_3[7] = {
+    {1, arcs_3_0},
+    {1, arcs_3_1},
+    {2, arcs_3_2},
+    {2, arcs_3_3},
+    {1, arcs_3_4},
+    {1, arcs_3_5},
+    {1, arcs_3_6},
+};
+static arc arcs_4_0[1] = {
+    {10, 1},
+};
+static arc arcs_4_1[2] = {
+    {10, 1},
+    {0, 1},
+};
+static state states_4[2] = {
+    {1, arcs_4_0},
+    {2, arcs_4_1},
+};
+static arc arcs_5_0[1] = {
+    {16, 1},
+};
+static arc arcs_5_1[2] = {
+    {18, 2},
+    {19, 2},
+};
+static arc arcs_5_2[1] = {
+    {0, 2},
+};
+static state states_5[3] = {
+    {1, arcs_5_0},
+    {2, arcs_5_1},
+    {1, arcs_5_2},
+};
+static arc arcs_6_0[1] = {
+    {20, 1},
+};
+static arc arcs_6_1[1] = {
+    {21, 2},
+};
+static arc arcs_6_2[1] = {
+    {22, 3},
+};
+static arc arcs_6_3[1] = {
+    {23, 4},
+};
+static arc arcs_6_4[2] = {
+    {24, 5},
+    {25, 6},
+};
+static arc arcs_6_5[1] = {
+    {25, 6},
+};
+static arc arcs_6_6[1] = {
+    {0, 6},
+};
+static state states_6[7] = {
+    {1, arcs_6_0},
+    {1, arcs_6_1},
+    {1, arcs_6_2},
+    {1, arcs_6_3},
+    {2, arcs_6_4},
+    {1, arcs_6_5},
+    {1, arcs_6_6},
+};
+static arc arcs_7_0[1] = {
+    {13, 1},
+};
+static arc arcs_7_1[2] = {
+    {26, 2},
+    {15, 3},
+};
+static arc arcs_7_2[1] = {
+    {15, 3},
+};
+static arc arcs_7_3[1] = {
+    {0, 3},
+};
+static state states_7[4] = {
+    {1, arcs_7_0},
+    {2, arcs_7_1},
+    {1, arcs_7_2},
+    {1, arcs_7_3},
+};
+static arc arcs_8_0[3] = {
+    {27, 1},
+    {31, 2},
+    {32, 3},
+};
+static arc arcs_8_1[4] = {
+    {28, 4},
+    {30, 5},
+    {24, 6},
+    {0, 1},
+};
+static arc arcs_8_2[1] = {
+    {21, 7},
+};
+static arc arcs_8_3[1] = {
+    {21, 8},
+};
+static arc arcs_8_4[1] = {
+    {29, 9},
+};
+static arc arcs_8_5[5] = {
+    {27, 1},
+    {24, 10},
+    {31, 2},
+    {32, 3},
+    {0, 5},
+};
+static arc arcs_8_6[1] = {
+    {0, 6},
+};
+static arc arcs_8_7[3] = {
+    {30, 11},
+    {24, 6},
+    {0, 7},
+};
+static arc arcs_8_8[2] = {
+    {24, 6},
+    {0, 8},
+};
+static arc arcs_8_9[3] = {
+    {30, 5},
+    {24, 6},
+    {0, 9},
+};
+static arc arcs_8_10[4] = {
+    {27, 1},
+    {31, 2},
+    {32, 3},
+    {0, 10},
+};
+static arc arcs_8_11[2] = {
+    {24, 12},
+    {32, 3},
+};
+static arc arcs_8_12[1] = {
+    {32, 3},
+};
+static state states_8[13] = {
+    {3, arcs_8_0},
+    {4, arcs_8_1},
+    {1, arcs_8_2},
+    {1, arcs_8_3},
+    {1, arcs_8_4},
+    {5, arcs_8_5},
+    {1, arcs_8_6},
+    {3, arcs_8_7},
+    {2, arcs_8_8},
+    {3, arcs_8_9},
+    {4, arcs_8_10},
+    {2, arcs_8_11},
+    {1, arcs_8_12},
+};
+static arc arcs_9_0[2] = {
+    {21, 1},
+    {13, 2},
+};
+static arc arcs_9_1[1] = {
+    {0, 1},
+};
+static arc arcs_9_2[1] = {
+    {33, 3},
+};
+static arc arcs_9_3[1] = {
+    {15, 1},
+};
+static state states_9[4] = {
+    {2, arcs_9_0},
+    {1, arcs_9_1},
+    {1, arcs_9_2},
+    {1, arcs_9_3},
+};
+static arc arcs_10_0[1] = {
+    {27, 1},
+};
+static arc arcs_10_1[2] = {
+    {30, 2},
+    {0, 1},
+};
+static arc arcs_10_2[2] = {
+    {27, 1},
+    {0, 2},
+};
+static state states_10[3] = {
+    {1, arcs_10_0},
+    {2, arcs_10_1},
+    {2, arcs_10_2},
+};
+static arc arcs_11_0[2] = {
+    {3, 1},
+    {4, 1},
+};
+static arc arcs_11_1[1] = {
+    {0, 1},
+};
+static state states_11[2] = {
+    {2, arcs_11_0},
+    {1, arcs_11_1},
+};
+static arc arcs_12_0[1] = {
+    {34, 1},
+};
+static arc arcs_12_1[2] = {
+    {35, 2},
+    {2, 3},
+};
+static arc arcs_12_2[2] = {
+    {34, 1},
+    {2, 3},
+};
+static arc arcs_12_3[1] = {
+    {0, 3},
+};
+static state states_12[4] = {
+    {1, arcs_12_0},
+    {2, arcs_12_1},
+    {2, arcs_12_2},
+    {1, arcs_12_3},
+};
+static arc arcs_13_0[9] = {
+    {36, 1},
+    {37, 1},
+    {38, 1},
+    {39, 1},
+    {40, 1},
+    {41, 1},
+    {42, 1},
+    {43, 1},
+    {44, 1},
+};
+static arc arcs_13_1[1] = {
+    {0, 1},
+};
+static state states_13[2] = {
+    {9, arcs_13_0},
+    {1, arcs_13_1},
+};
+static arc arcs_14_0[1] = {
+    {9, 1},
+};
+static arc arcs_14_1[4] = {
+    {45, 2},
+    {28, 3},
+    {24, 4},
+    {0, 1},
+};
+static arc arcs_14_2[2] = {
+    {46, 4},
+    {9, 4},
+};
+static arc arcs_14_3[2] = {
+    {46, 5},
+    {9, 5},
+};
+static arc arcs_14_4[1] = {
+    {0, 4},
+};
+static arc arcs_14_5[3] = {
+    {28, 3},
+    {24, 4},
+    {0, 5},
+};
+static state states_14[6] = {
+    {1, arcs_14_0},
+    {4, arcs_14_1},
+    {2, arcs_14_2},
+    {2, arcs_14_3},
+    {1, arcs_14_4},
+    {3, arcs_14_5},
+};
+static arc arcs_15_0[12] = {
+    {47, 1},
+    {48, 1},
+    {49, 1},
+    {50, 1},
+    {51, 1},
+    {52, 1},
+    {53, 1},
+    {54, 1},
+    {55, 1},
+    {56, 1},
+    {57, 1},
+    {58, 1},
+};
+static arc arcs_15_1[1] = {
+    {0, 1},
+};
+static state states_15[2] = {
+    {12, arcs_15_0},
+    {1, arcs_15_1},
+};
+static arc arcs_16_0[1] = {
+    {59, 1},
+};
+static arc arcs_16_1[3] = {
+    {29, 2},
+    {60, 3},
+    {0, 1},
+};
+static arc arcs_16_2[2] = {
+    {30, 4},
+    {0, 2},
+};
+static arc arcs_16_3[1] = {
+    {29, 5},
+};
+static arc arcs_16_4[2] = {
+    {29, 2},
+    {0, 4},
+};
+static arc arcs_16_5[2] = {
+    {30, 6},
+    {0, 5},
+};
+static arc arcs_16_6[1] = {
+    {29, 7},
+};
+static arc arcs_16_7[2] = {
+    {30, 8},
+    {0, 7},
+};
+static arc arcs_16_8[2] = {
+    {29, 7},
+    {0, 8},
+};
+static state states_16[9] = {
+    {1, arcs_16_0},
+    {3, arcs_16_1},
+    {2, arcs_16_2},
+    {1, arcs_16_3},
+    {2, arcs_16_4},
+    {2, arcs_16_5},
+    {1, arcs_16_6},
+    {2, arcs_16_7},
+    {2, arcs_16_8},
+};
+static arc arcs_17_0[1] = {
+    {61, 1},
+};
+static arc arcs_17_1[1] = {
+    {62, 2},
+};
+static arc arcs_17_2[1] = {
+    {0, 2},
+};
+static state states_17[3] = {
+    {1, arcs_17_0},
+    {1, arcs_17_1},
+    {1, arcs_17_2},
+};
+static arc arcs_18_0[1] = {
+    {63, 1},
+};
+static arc arcs_18_1[1] = {
+    {0, 1},
+};
+static state states_18[2] = {
+    {1, arcs_18_0},
+    {1, arcs_18_1},
+};
+static arc arcs_19_0[5] = {
+    {64, 1},
+    {65, 1},
+    {66, 1},
+    {67, 1},
+    {68, 1},
+};
+static arc arcs_19_1[1] = {
+    {0, 1},
+};
+static state states_19[2] = {
+    {5, arcs_19_0},
+    {1, arcs_19_1},
+};
+static arc arcs_20_0[1] = {
+    {69, 1},
+};
+static arc arcs_20_1[1] = {
+    {0, 1},
+};
+static state states_20[2] = {
+    {1, arcs_20_0},
+    {1, arcs_20_1},
+};
+static arc arcs_21_0[1] = {
+    {70, 1},
+};
+static arc arcs_21_1[1] = {
+    {0, 1},
+};
+static state states_21[2] = {
+    {1, arcs_21_0},
+    {1, arcs_21_1},
+};
+static arc arcs_22_0[1] = {
+    {71, 1},
+};
+static arc arcs_22_1[2] = {
+    {9, 2},
+    {0, 1},
+};
+static arc arcs_22_2[1] = {
+    {0, 2},
+};
+static state states_22[3] = {
+    {1, arcs_22_0},
+    {2, arcs_22_1},
+    {1, arcs_22_2},
+};
+static arc arcs_23_0[1] = {
+    {46, 1},
+};
+static arc arcs_23_1[1] = {
+    {0, 1},
+};
+static state states_23[2] = {
+    {1, arcs_23_0},
+    {1, arcs_23_1},
+};
+static arc arcs_24_0[1] = {
+    {72, 1},
+};
+static arc arcs_24_1[2] = {
+    {29, 2},
+    {0, 1},
+};
+static arc arcs_24_2[2] = {
+    {30, 3},
+    {0, 2},
+};
+static arc arcs_24_3[1] = {
+    {29, 4},
+};
+static arc arcs_24_4[2] = {
+    {30, 5},
+    {0, 4},
+};
+static arc arcs_24_5[1] = {
+    {29, 6},
+};
+static arc arcs_24_6[1] = {
+    {0, 6},
+};
+static state states_24[7] = {
+    {1, arcs_24_0},
+    {2, arcs_24_1},
+    {2, arcs_24_2},
+    {1, arcs_24_3},
+    {2, arcs_24_4},
+    {1, arcs_24_5},
+    {1, arcs_24_6},
+};
+static arc arcs_25_0[2] = {
+    {73, 1},
+    {74, 1},
+};
+static arc arcs_25_1[1] = {
+    {0, 1},
+};
+static state states_25[2] = {
+    {2, arcs_25_0},
+    {1, arcs_25_1},
+};
+static arc arcs_26_0[1] = {
+    {75, 1},
+};
+static arc arcs_26_1[1] = {
+    {76, 2},
+};
+static arc arcs_26_2[1] = {
+    {0, 2},
+};
+static state states_26[3] = {
+    {1, arcs_26_0},
+    {1, arcs_26_1},
+    {1, arcs_26_2},
+};
+static arc arcs_27_0[1] = {
+    {77, 1},
+};
+static arc arcs_27_1[2] = {
+    {78, 2},
+    {12, 3},
+};
+static arc arcs_27_2[3] = {
+    {78, 2},
+    {12, 3},
+    {75, 4},
+};
+static arc arcs_27_3[1] = {
+    {75, 4},
+};
+static arc arcs_27_4[3] = {
+    {31, 5},
+    {13, 6},
+    {79, 5},
+};
+static arc arcs_27_5[1] = {
+    {0, 5},
+};
+static arc arcs_27_6[1] = {
+    {79, 7},
+};
+static arc arcs_27_7[1] = {
+    {15, 5},
+};
+static state states_27[8] = {
+    {1, arcs_27_0},
+    {2, arcs_27_1},
+    {3, arcs_27_2},
+    {1, arcs_27_3},
+    {3, arcs_27_4},
+    {1, arcs_27_5},
+    {1, arcs_27_6},
+    {1, arcs_27_7},
+};
+static arc arcs_28_0[1] = {
+    {21, 1},
+};
+static arc arcs_28_1[2] = {
+    {81, 2},
+    {0, 1},
+};
+static arc arcs_28_2[1] = {
+    {21, 3},
+};
+static arc arcs_28_3[1] = {
+    {0, 3},
+};
+static state states_28[4] = {
+    {1, arcs_28_0},
+    {2, arcs_28_1},
+    {1, arcs_28_2},
+    {1, arcs_28_3},
+};
+static arc arcs_29_0[1] = {
+    {12, 1},
+};
+static arc arcs_29_1[2] = {
+    {81, 2},
+    {0, 1},
+};
+static arc arcs_29_2[1] = {
+    {21, 3},
+};
+static arc arcs_29_3[1] = {
+    {0, 3},
+};
+static state states_29[4] = {
+    {1, arcs_29_0},
+    {2, arcs_29_1},
+    {1, arcs_29_2},
+    {1, arcs_29_3},
+};
+static arc arcs_30_0[1] = {
+    {80, 1},
+};
+static arc arcs_30_1[2] = {
+    {30, 2},
+    {0, 1},
+};
+static arc arcs_30_2[2] = {
+    {80, 1},
+    {0, 2},
+};
+static state states_30[3] = {
+    {1, arcs_30_0},
+    {2, arcs_30_1},
+    {2, arcs_30_2},
+};
+static arc arcs_31_0[1] = {
+    {82, 1},
+};
+static arc arcs_31_1[2] = {
+    {30, 0},
+    {0, 1},
+};
+static state states_31[2] = {
+    {1, arcs_31_0},
+    {2, arcs_31_1},
+};
+static arc arcs_32_0[1] = {
+    {21, 1},
+};
+static arc arcs_32_1[2] = {
+    {78, 0},
+    {0, 1},
+};
+static state states_32[2] = {
+    {1, arcs_32_0},
+    {2, arcs_32_1},
+};
+static arc arcs_33_0[1] = {
+    {83, 1},
+};
+static arc arcs_33_1[1] = {
+    {21, 2},
+};
+static arc arcs_33_2[2] = {
+    {30, 1},
+    {0, 2},
+};
+static state states_33[3] = {
+    {1, arcs_33_0},
+    {1, arcs_33_1},
+    {2, arcs_33_2},
+};
+static arc arcs_34_0[1] = {
+    {84, 1},
+};
+static arc arcs_34_1[1] = {
+    {85, 2},
+};
+static arc arcs_34_2[2] = {
+    {86, 3},
+    {0, 2},
+};
+static arc arcs_34_3[1] = {
+    {29, 4},
+};
+static arc arcs_34_4[2] = {
+    {30, 5},
+    {0, 4},
+};
+static arc arcs_34_5[1] = {
+    {29, 6},
+};
+static arc arcs_34_6[1] = {
+    {0, 6},
+};
+static state states_34[7] = {
+    {1, arcs_34_0},
+    {1, arcs_34_1},
+    {2, arcs_34_2},
+    {1, arcs_34_3},
+    {2, arcs_34_4},
+    {1, arcs_34_5},
+    {1, arcs_34_6},
+};
+static arc arcs_35_0[1] = {
+    {87, 1},
+};
+static arc arcs_35_1[1] = {
+    {29, 2},
+};
+static arc arcs_35_2[2] = {
+    {30, 3},
+    {0, 2},
+};
+static arc arcs_35_3[1] = {
+    {29, 4},
+};
+static arc arcs_35_4[1] = {
+    {0, 4},
+};
+static state states_35[5] = {
+    {1, arcs_35_0},
+    {1, arcs_35_1},
+    {2, arcs_35_2},
+    {1, arcs_35_3},
+    {1, arcs_35_4},
+};
+static arc arcs_36_0[8] = {
+    {88, 1},
+    {89, 1},
+    {90, 1},
+    {91, 1},
+    {92, 1},
+    {19, 1},
+    {18, 1},
+    {17, 1},
+};
+static arc arcs_36_1[1] = {
+    {0, 1},
+};
+static state states_36[2] = {
+    {8, arcs_36_0},
+    {1, arcs_36_1},
+};
+static arc arcs_37_0[1] = {
+    {93, 1},
+};
+static arc arcs_37_1[1] = {
+    {29, 2},
+};
+static arc arcs_37_2[1] = {
+    {23, 3},
+};
+static arc arcs_37_3[1] = {
+    {25, 4},
+};
+static arc arcs_37_4[3] = {
+    {94, 1},
+    {95, 5},
+    {0, 4},
+};
+static arc arcs_37_5[1] = {
+    {23, 6},
+};
+static arc arcs_37_6[1] = {
+    {25, 7},
+};
+static arc arcs_37_7[1] = {
+    {0, 7},
+};
+static state states_37[8] = {
+    {1, arcs_37_0},
+    {1, arcs_37_1},
+    {1, arcs_37_2},
+    {1, arcs_37_3},
+    {3, arcs_37_4},
+    {1, arcs_37_5},
+    {1, arcs_37_6},
+    {1, arcs_37_7},
+};
+static arc arcs_38_0[1] = {
+    {96, 1},
+};
+static arc arcs_38_1[1] = {
+    {29, 2},
+};
+static arc arcs_38_2[1] = {
+    {23, 3},
+};
+static arc arcs_38_3[1] = {
+    {25, 4},
+};
+static arc arcs_38_4[2] = {
+    {95, 5},
+    {0, 4},
+};
+static arc arcs_38_5[1] = {
+    {23, 6},
+};
+static arc arcs_38_6[1] = {
+    {25, 7},
+};
+static arc arcs_38_7[1] = {
+    {0, 7},
+};
+static state states_38[8] = {
+    {1, arcs_38_0},
+    {1, arcs_38_1},
+    {1, arcs_38_2},
+    {1, arcs_38_3},
+    {2, arcs_38_4},
+    {1, arcs_38_5},
+    {1, arcs_38_6},
+    {1, arcs_38_7},
+};
+static arc arcs_39_0[1] = {
+    {97, 1},
+};
+static arc arcs_39_1[1] = {
+    {62, 2},
+};
+static arc arcs_39_2[1] = {
+    {86, 3},
+};
+static arc arcs_39_3[1] = {
+    {9, 4},
+};
+static arc arcs_39_4[1] = {
+    {23, 5},
+};
+static arc arcs_39_5[2] = {
+    {24, 6},
+    {25, 7},
+};
+static arc arcs_39_6[1] = {
+    {25, 7},
+};
+static arc arcs_39_7[2] = {
+    {95, 8},
+    {0, 7},
+};
+static arc arcs_39_8[1] = {
+    {23, 9},
+};
+static arc arcs_39_9[1] = {
+    {25, 10},
+};
+static arc arcs_39_10[1] = {
+    {0, 10},
+};
+static state states_39[11] = {
+    {1, arcs_39_0},
+    {1, arcs_39_1},
+    {1, arcs_39_2},
+    {1, arcs_39_3},
+    {1, arcs_39_4},
+    {2, arcs_39_5},
+    {1, arcs_39_6},
+    {2, arcs_39_7},
+    {1, arcs_39_8},
+    {1, arcs_39_9},
+    {1, arcs_39_10},
+};
+static arc arcs_40_0[1] = {
+    {98, 1},
+};
+static arc arcs_40_1[1] = {
+    {23, 2},
+};
+static arc arcs_40_2[1] = {
+    {25, 3},
+};
+static arc arcs_40_3[2] = {
+    {99, 4},
+    {100, 5},
+};
+static arc arcs_40_4[1] = {
+    {23, 6},
+};
+static arc arcs_40_5[1] = {
+    {23, 7},
+};
+static arc arcs_40_6[1] = {
+    {25, 8},
+};
+static arc arcs_40_7[1] = {
+    {25, 9},
+};
+static arc arcs_40_8[4] = {
+    {99, 4},
+    {95, 10},
+    {100, 5},
+    {0, 8},
+};
+static arc arcs_40_9[1] = {
+    {0, 9},
+};
+static arc arcs_40_10[1] = {
+    {23, 11},
+};
+static arc arcs_40_11[1] = {
+    {25, 12},
+};
+static arc arcs_40_12[2] = {
+    {100, 5},
+    {0, 12},
+};
+static state states_40[13] = {
+    {1, arcs_40_0},
+    {1, arcs_40_1},
+    {1, arcs_40_2},
+    {2, arcs_40_3},
+    {1, arcs_40_4},
+    {1, arcs_40_5},
+    {1, arcs_40_6},
+    {1, arcs_40_7},
+    {4, arcs_40_8},
+    {1, arcs_40_9},
+    {1, arcs_40_10},
+    {1, arcs_40_11},
+    {2, arcs_40_12},
+};
+static arc arcs_41_0[1] = {
+    {101, 1},
+};
+static arc arcs_41_1[1] = {
+    {102, 2},
+};
+static arc arcs_41_2[2] = {
+    {30, 1},
+    {23, 3},
+};
+static arc arcs_41_3[2] = {
+    {24, 4},
+    {25, 5},
+};
+static arc arcs_41_4[1] = {
+    {25, 5},
+};
+static arc arcs_41_5[1] = {
+    {0, 5},
+};
+static state states_41[6] = {
+    {1, arcs_41_0},
+    {1, arcs_41_1},
+    {2, arcs_41_2},
+    {2, arcs_41_3},
+    {1, arcs_41_4},
+    {1, arcs_41_5},
+};
+static arc arcs_42_0[1] = {
+    {29, 1},
+};
+static arc arcs_42_1[2] = {
+    {81, 2},
+    {0, 1},
+};
+static arc arcs_42_2[1] = {
+    {85, 3},
+};
+static arc arcs_42_3[1] = {
+    {0, 3},
+};
+static state states_42[4] = {
+    {1, arcs_42_0},
+    {2, arcs_42_1},
+    {1, arcs_42_2},
+    {1, arcs_42_3},
+};
+static arc arcs_43_0[1] = {
+    {103, 1},
+};
+static arc arcs_43_1[2] = {
+    {29, 2},
+    {0, 1},
+};
+static arc arcs_43_2[3] = {
+    {81, 3},
+    {30, 3},
+    {0, 2},
+};
+static arc arcs_43_3[1] = {
+    {29, 4},
+};
+static arc arcs_43_4[1] = {
+    {0, 4},
+};
+static state states_43[5] = {
+    {1, arcs_43_0},
+    {2, arcs_43_1},
+    {3, arcs_43_2},
+    {1, arcs_43_3},
+    {1, arcs_43_4},
+};
+static arc arcs_44_0[2] = {
+    {3, 1},
+    {2, 2},
+};
+static arc arcs_44_1[1] = {
+    {0, 1},
+};
+static arc arcs_44_2[2] = {
+    {24, 3},
+    {104, 4},
+};
+static arc arcs_44_3[1] = {
+    {2, 5},
+};
+static arc arcs_44_4[1] = {
+    {6, 6},
+};
+static arc arcs_44_5[1] = {
+    {104, 4},
+};
+static arc arcs_44_6[2] = {
+    {6, 6},
+    {105, 1},
+};
+static state states_44[7] = {
+    {2, arcs_44_0},
+    {1, arcs_44_1},
+    {2, arcs_44_2},
+    {1, arcs_44_3},
+    {1, arcs_44_4},
+    {1, arcs_44_5},
+    {2, arcs_44_6},
+};
+static arc arcs_45_0[1] = {
+    {107, 1},
+};
+static arc arcs_45_1[2] = {
+    {30, 2},
+    {0, 1},
+};
+static arc arcs_45_2[1] = {
+    {107, 3},
+};
+static arc arcs_45_3[2] = {
+    {30, 4},
+    {0, 3},
+};
+static arc arcs_45_4[2] = {
+    {107, 3},
+    {0, 4},
+};
+static state states_45[5] = {
+    {1, arcs_45_0},
+    {2, arcs_45_1},
+    {1, arcs_45_2},
+    {2, arcs_45_3},
+    {2, arcs_45_4},
+};
+static arc arcs_46_0[2] = {
+    {108, 1},
+    {109, 1},
+};
+static arc arcs_46_1[1] = {
+    {0, 1},
+};
+static state states_46[2] = {
+    {2, arcs_46_0},
+    {1, arcs_46_1},
+};
+static arc arcs_47_0[1] = {
+    {110, 1},
+};
+static arc arcs_47_1[2] = {
+    {26, 2},
+    {23, 3},
+};
+static arc arcs_47_2[1] = {
+    {23, 3},
+};
+static arc arcs_47_3[1] = {
+    {107, 4},
+};
+static arc arcs_47_4[1] = {
+    {0, 4},
+};
+static state states_47[5] = {
+    {1, arcs_47_0},
+    {2, arcs_47_1},
+    {1, arcs_47_2},
+    {1, arcs_47_3},
+    {1, arcs_47_4},
+};
+static arc arcs_48_0[2] = {
+    {108, 1},
+    {111, 2},
+};
+static arc arcs_48_1[2] = {
+    {93, 3},
+    {0, 1},
+};
+static arc arcs_48_2[1] = {
+    {0, 2},
+};
+static arc arcs_48_3[1] = {
+    {108, 4},
+};
+static arc arcs_48_4[1] = {
+    {95, 5},
+};
+static arc arcs_48_5[1] = {
+    {29, 2},
+};
+static state states_48[6] = {
+    {2, arcs_48_0},
+    {2, arcs_48_1},
+    {1, arcs_48_2},
+    {1, arcs_48_3},
+    {1, arcs_48_4},
+    {1, arcs_48_5},
+};
+static arc arcs_49_0[1] = {
+    {112, 1},
+};
+static arc arcs_49_1[2] = {
+    {113, 0},
+    {0, 1},
+};
+static state states_49[2] = {
+    {1, arcs_49_0},
+    {2, arcs_49_1},
+};
+static arc arcs_50_0[1] = {
+    {114, 1},
+};
+static arc arcs_50_1[2] = {
+    {115, 0},
+    {0, 1},
+};
+static state states_50[2] = {
+    {1, arcs_50_0},
+    {2, arcs_50_1},
+};
+static arc arcs_51_0[2] = {
+    {116, 1},
+    {117, 2},
+};
+static arc arcs_51_1[1] = {
+    {114, 2},
+};
+static arc arcs_51_2[1] = {
+    {0, 2},
+};
+static state states_51[3] = {
+    {2, arcs_51_0},
+    {1, arcs_51_1},
+    {1, arcs_51_2},
+};
+static arc arcs_52_0[1] = {
+    {85, 1},
+};
+static arc arcs_52_1[2] = {
+    {118, 0},
+    {0, 1},
+};
+static state states_52[2] = {
+    {1, arcs_52_0},
+    {2, arcs_52_1},
+};
+static arc arcs_53_0[10] = {
+    {119, 1},
+    {120, 1},
+    {121, 1},
+    {122, 1},
+    {123, 1},
+    {124, 1},
+    {125, 1},
+    {86, 1},
+    {116, 2},
+    {126, 3},
+};
+static arc arcs_53_1[1] = {
+    {0, 1},
+};
+static arc arcs_53_2[1] = {
+    {86, 1},
+};
+static arc arcs_53_3[2] = {
+    {116, 1},
+    {0, 3},
+};
+static state states_53[4] = {
+    {10, arcs_53_0},
+    {1, arcs_53_1},
+    {1, arcs_53_2},
+    {2, arcs_53_3},
+};
+static arc arcs_54_0[1] = {
+    {127, 1},
+};
+static arc arcs_54_1[2] = {
+    {128, 0},
+    {0, 1},
+};
+static state states_54[2] = {
+    {1, arcs_54_0},
+    {2, arcs_54_1},
+};
+static arc arcs_55_0[1] = {
+    {129, 1},
+};
+static arc arcs_55_1[2] = {
+    {130, 0},
+    {0, 1},
+};
+static state states_55[2] = {
+    {1, arcs_55_0},
+    {2, arcs_55_1},
+};
+static arc arcs_56_0[1] = {
+    {131, 1},
+};
+static arc arcs_56_1[2] = {
+    {132, 0},
+    {0, 1},
+};
+static state states_56[2] = {
+    {1, arcs_56_0},
+    {2, arcs_56_1},
+};
+static arc arcs_57_0[1] = {
+    {133, 1},
+};
+static arc arcs_57_1[3] = {
+    {134, 0},
+    {60, 0},
+    {0, 1},
+};
+static state states_57[2] = {
+    {1, arcs_57_0},
+    {3, arcs_57_1},
+};
+static arc arcs_58_0[1] = {
+    {135, 1},
+};
+static arc arcs_58_1[3] = {
+    {136, 0},
+    {137, 0},
+    {0, 1},
+};
+static state states_58[2] = {
+    {1, arcs_58_0},
+    {3, arcs_58_1},
+};
+static arc arcs_59_0[1] = {
+    {138, 1},
+};
+static arc arcs_59_1[5] = {
+    {31, 0},
+    {139, 0},
+    {140, 0},
+    {141, 0},
+    {0, 1},
+};
+static state states_59[2] = {
+    {1, arcs_59_0},
+    {5, arcs_59_1},
+};
+static arc arcs_60_0[4] = {
+    {136, 1},
+    {137, 1},
+    {142, 1},
+    {143, 2},
+};
+static arc arcs_60_1[1] = {
+    {138, 2},
+};
+static arc arcs_60_2[1] = {
+    {0, 2},
+};
+static state states_60[3] = {
+    {4, arcs_60_0},
+    {1, arcs_60_1},
+    {1, arcs_60_2},
+};
+static arc arcs_61_0[1] = {
+    {144, 1},
+};
+static arc arcs_61_1[3] = {
+    {145, 1},
+    {32, 2},
+    {0, 1},
+};
+static arc arcs_61_2[1] = {
+    {138, 3},
+};
+static arc arcs_61_3[1] = {
+    {0, 3},
+};
+static state states_61[4] = {
+    {1, arcs_61_0},
+    {3, arcs_61_1},
+    {1, arcs_61_2},
+    {1, arcs_61_3},
+};
+static arc arcs_62_0[7] = {
+    {13, 1},
+    {147, 2},
+    {150, 3},
+    {153, 4},
+    {21, 5},
+    {155, 5},
+    {156, 6},
+};
+static arc arcs_62_1[3] = {
+    {46, 7},
+    {146, 7},
+    {15, 5},
+};
+static arc arcs_62_2[2] = {
+    {148, 8},
+    {149, 5},
+};
+static arc arcs_62_3[2] = {
+    {151, 9},
+    {152, 5},
+};
+static arc arcs_62_4[1] = {
+    {154, 10},
+};
+static arc arcs_62_5[1] = {
+    {0, 5},
+};
+static arc arcs_62_6[2] = {
+    {156, 6},
+    {0, 6},
+};
+static arc arcs_62_7[1] = {
+    {15, 5},
+};
+static arc arcs_62_8[1] = {
+    {149, 5},
+};
+static arc arcs_62_9[1] = {
+    {152, 5},
+};
+static arc arcs_62_10[1] = {
+    {153, 5},
+};
+static state states_62[11] = {
+    {7, arcs_62_0},
+    {3, arcs_62_1},
+    {2, arcs_62_2},
+    {2, arcs_62_3},
+    {1, arcs_62_4},
+    {1, arcs_62_5},
+    {2, arcs_62_6},
+    {1, arcs_62_7},
+    {1, arcs_62_8},
+    {1, arcs_62_9},
+    {1, arcs_62_10},
+};
+static arc arcs_63_0[1] = {
+    {29, 1},
+};
+static arc arcs_63_1[3] = {
+    {157, 2},
+    {30, 3},
+    {0, 1},
+};
+static arc arcs_63_2[1] = {
+    {0, 2},
+};
+static arc arcs_63_3[2] = {
+    {29, 4},
+    {0, 3},
+};
+static arc arcs_63_4[2] = {
+    {30, 3},
+    {0, 4},
+};
+static state states_63[5] = {
+    {1, arcs_63_0},
+    {3, arcs_63_1},
+    {1, arcs_63_2},
+    {2, arcs_63_3},
+    {2, arcs_63_4},
+};
+static arc arcs_64_0[1] = {
+    {29, 1},
+};
+static arc arcs_64_1[3] = {
+    {158, 2},
+    {30, 3},
+    {0, 1},
+};
+static arc arcs_64_2[1] = {
+    {0, 2},
+};
+static arc arcs_64_3[2] = {
+    {29, 4},
+    {0, 3},
+};
+static arc arcs_64_4[2] = {
+    {30, 3},
+    {0, 4},
+};
+static state states_64[5] = {
+    {1, arcs_64_0},
+    {3, arcs_64_1},
+    {1, arcs_64_2},
+    {2, arcs_64_3},
+    {2, arcs_64_4},
+};
+static arc arcs_65_0[1] = {
+    {110, 1},
+};
+static arc arcs_65_1[2] = {
+    {26, 2},
+    {23, 3},
+};
+static arc arcs_65_2[1] = {
+    {23, 3},
+};
+static arc arcs_65_3[1] = {
+    {29, 4},
+};
+static arc arcs_65_4[1] = {
+    {0, 4},
+};
+static state states_65[5] = {
+    {1, arcs_65_0},
+    {2, arcs_65_1},
+    {1, arcs_65_2},
+    {1, arcs_65_3},
+    {1, arcs_65_4},
+};
+static arc arcs_66_0[3] = {
+    {13, 1},
+    {147, 2},
+    {78, 3},
+};
+static arc arcs_66_1[2] = {
+    {14, 4},
+    {15, 5},
+};
+static arc arcs_66_2[1] = {
+    {159, 6},
+};
+static arc arcs_66_3[1] = {
+    {21, 5},
+};
+static arc arcs_66_4[1] = {
+    {15, 5},
+};
+static arc arcs_66_5[1] = {
+    {0, 5},
+};
+static arc arcs_66_6[1] = {
+    {149, 5},
+};
+static state states_66[7] = {
+    {3, arcs_66_0},
+    {2, arcs_66_1},
+    {1, arcs_66_2},
+    {1, arcs_66_3},
+    {1, arcs_66_4},
+    {1, arcs_66_5},
+    {1, arcs_66_6},
+};
+static arc arcs_67_0[1] = {
+    {160, 1},
+};
+static arc arcs_67_1[2] = {
+    {30, 2},
+    {0, 1},
+};
+static arc arcs_67_2[2] = {
+    {160, 1},
+    {0, 2},
+};
+static state states_67[3] = {
+    {1, arcs_67_0},
+    {2, arcs_67_1},
+    {2, arcs_67_2},
+};
+static arc arcs_68_0[3] = {
+    {78, 1},
+    {29, 2},
+    {23, 3},
+};
+static arc arcs_68_1[1] = {
+    {78, 4},
+};
+static arc arcs_68_2[2] = {
+    {23, 3},
+    {0, 2},
+};
+static arc arcs_68_3[3] = {
+    {29, 5},
+    {161, 6},
+    {0, 3},
+};
+static arc arcs_68_4[1] = {
+    {78, 6},
+};
+static arc arcs_68_5[2] = {
+    {161, 6},
+    {0, 5},
+};
+static arc arcs_68_6[1] = {
+    {0, 6},
+};
+static state states_68[7] = {
+    {3, arcs_68_0},
+    {1, arcs_68_1},
+    {2, arcs_68_2},
+    {3, arcs_68_3},
+    {1, arcs_68_4},
+    {2, arcs_68_5},
+    {1, arcs_68_6},
+};
+static arc arcs_69_0[1] = {
+    {23, 1},
+};
+static arc arcs_69_1[2] = {
+    {29, 2},
+    {0, 1},
+};
+static arc arcs_69_2[1] = {
+    {0, 2},
+};
+static state states_69[3] = {
+    {1, arcs_69_0},
+    {2, arcs_69_1},
+    {1, arcs_69_2},
+};
+static arc arcs_70_0[1] = {
+    {85, 1},
+};
+static arc arcs_70_1[2] = {
+    {30, 2},
+    {0, 1},
+};
+static arc arcs_70_2[2] = {
+    {85, 1},
+    {0, 2},
+};
+static state states_70[3] = {
+    {1, arcs_70_0},
+    {2, arcs_70_1},
+    {2, arcs_70_2},
+};
+static arc arcs_71_0[1] = {
+    {29, 1},
+};
+static arc arcs_71_1[2] = {
+    {30, 2},
+    {0, 1},
+};
+static arc arcs_71_2[2] = {
+    {29, 1},
+    {0, 2},
+};
+static state states_71[3] = {
+    {1, arcs_71_0},
+    {2, arcs_71_1},
+    {2, arcs_71_2},
+};
+static arc arcs_72_0[1] = {
+    {29, 1},
+};
+static arc arcs_72_1[4] = {
+    {23, 2},
+    {158, 3},
+    {30, 4},
+    {0, 1},
+};
+static arc arcs_72_2[1] = {
+    {29, 5},
+};
+static arc arcs_72_3[1] = {
+    {0, 3},
+};
+static arc arcs_72_4[2] = {
+    {29, 6},
+    {0, 4},
+};
+static arc arcs_72_5[3] = {
+    {158, 3},
+    {30, 7},
+    {0, 5},
+};
+static arc arcs_72_6[2] = {
+    {30, 4},
+    {0, 6},
+};
+static arc arcs_72_7[2] = {
+    {29, 8},
+    {0, 7},
+};
+static arc arcs_72_8[1] = {
+    {23, 9},
+};
+static arc arcs_72_9[1] = {
+    {29, 10},
+};
+static arc arcs_72_10[2] = {
+    {30, 7},
+    {0, 10},
+};
+static state states_72[11] = {
+    {1, arcs_72_0},
+    {4, arcs_72_1},
+    {1, arcs_72_2},
+    {1, arcs_72_3},
+    {2, arcs_72_4},
+    {3, arcs_72_5},
+    {2, arcs_72_6},
+    {2, arcs_72_7},
+    {1, arcs_72_8},
+    {1, arcs_72_9},
+    {2, arcs_72_10},
+};
+static arc arcs_73_0[1] = {
+    {162, 1},
+};
+static arc arcs_73_1[1] = {
+    {21, 2},
+};
+static arc arcs_73_2[2] = {
+    {13, 3},
+    {23, 4},
+};
+static arc arcs_73_3[2] = {
+    {9, 5},
+    {15, 6},
+};
+static arc arcs_73_4[1] = {
+    {25, 7},
+};
+static arc arcs_73_5[1] = {
+    {15, 6},
+};
+static arc arcs_73_6[1] = {
+    {23, 4},
+};
+static arc arcs_73_7[1] = {
+    {0, 7},
+};
+static state states_73[8] = {
+    {1, arcs_73_0},
+    {1, arcs_73_1},
+    {2, arcs_73_2},
+    {2, arcs_73_3},
+    {1, arcs_73_4},
+    {1, arcs_73_5},
+    {1, arcs_73_6},
+    {1, arcs_73_7},
+};
+static arc arcs_74_0[3] = {
+    {163, 1},
+    {31, 2},
+    {32, 3},
+};
+static arc arcs_74_1[2] = {
+    {30, 4},
+    {0, 1},
+};
+static arc arcs_74_2[1] = {
+    {29, 5},
+};
+static arc arcs_74_3[1] = {
+    {29, 6},
+};
+static arc arcs_74_4[4] = {
+    {163, 1},
+    {31, 2},
+    {32, 3},
+    {0, 4},
+};
+static arc arcs_74_5[2] = {
+    {30, 7},
+    {0, 5},
+};
+static arc arcs_74_6[1] = {
+    {0, 6},
+};
+static arc arcs_74_7[2] = {
+    {163, 5},
+    {32, 3},
+};
+static state states_74[8] = {
+    {3, arcs_74_0},
+    {2, arcs_74_1},
+    {1, arcs_74_2},
+    {1, arcs_74_3},
+    {4, arcs_74_4},
+    {2, arcs_74_5},
+    {1, arcs_74_6},
+    {2, arcs_74_7},
+};
+static arc arcs_75_0[1] = {
+    {29, 1},
+};
+static arc arcs_75_1[3] = {
+    {158, 2},
+    {28, 3},
+    {0, 1},
+};
+static arc arcs_75_2[1] = {
+    {0, 2},
+};
+static arc arcs_75_3[1] = {
+    {29, 2},
+};
+static state states_75[4] = {
+    {1, arcs_75_0},
+    {3, arcs_75_1},
+    {1, arcs_75_2},
+    {1, arcs_75_3},
+};
+static arc arcs_76_0[2] = {
+    {157, 1},
+    {165, 1},
+};
+static arc arcs_76_1[1] = {
+    {0, 1},
+};
+static state states_76[2] = {
+    {2, arcs_76_0},
+    {1, arcs_76_1},
+};
+static arc arcs_77_0[1] = {
+    {97, 1},
+};
+static arc arcs_77_1[1] = {
+    {62, 2},
+};
+static arc arcs_77_2[1] = {
+    {86, 3},
+};
+static arc arcs_77_3[1] = {
+    {106, 4},
+};
+static arc arcs_77_4[2] = {
+    {164, 5},
+    {0, 4},
+};
+static arc arcs_77_5[1] = {
+    {0, 5},
+};
+static state states_77[6] = {
+    {1, arcs_77_0},
+    {1, arcs_77_1},
+    {1, arcs_77_2},
+    {1, arcs_77_3},
+    {2, arcs_77_4},
+    {1, arcs_77_5},
+};
+static arc arcs_78_0[1] = {
+    {93, 1},
+};
+static arc arcs_78_1[1] = {
+    {107, 2},
+};
+static arc arcs_78_2[2] = {
+    {164, 3},
+    {0, 2},
+};
+static arc arcs_78_3[1] = {
+    {0, 3},
+};
+static state states_78[4] = {
+    {1, arcs_78_0},
+    {1, arcs_78_1},
+    {2, arcs_78_2},
+    {1, arcs_78_3},
+};
+static arc arcs_79_0[2] = {
+    {158, 1},
+    {167, 1},
+};
+static arc arcs_79_1[1] = {
+    {0, 1},
+};
+static state states_79[2] = {
+    {2, arcs_79_0},
+    {1, arcs_79_1},
+};
+static arc arcs_80_0[1] = {
+    {97, 1},
+};
+static arc arcs_80_1[1] = {
+    {62, 2},
+};
+static arc arcs_80_2[1] = {
+    {86, 3},
+};
+static arc arcs_80_3[1] = {
+    {108, 4},
+};
+static arc arcs_80_4[2] = {
+    {166, 5},
+    {0, 4},
+};
+static arc arcs_80_5[1] = {
+    {0, 5},
+};
+static state states_80[6] = {
+    {1, arcs_80_0},
+    {1, arcs_80_1},
+    {1, arcs_80_2},
+    {1, arcs_80_3},
+    {2, arcs_80_4},
+    {1, arcs_80_5},
+};
+static arc arcs_81_0[1] = {
+    {93, 1},
+};
+static arc arcs_81_1[1] = {
+    {107, 2},
+};
+static arc arcs_81_2[2] = {
+    {166, 3},
+    {0, 2},
+};
+static arc arcs_81_3[1] = {
+    {0, 3},
+};
+static state states_81[4] = {
+    {1, arcs_81_0},
+    {1, arcs_81_1},
+    {2, arcs_81_2},
+    {1, arcs_81_3},
+};
+static arc arcs_82_0[1] = {
+    {29, 1},
+};
+static arc arcs_82_1[2] = {
+    {30, 0},
+    {0, 1},
+};
+static state states_82[2] = {
+    {1, arcs_82_0},
+    {2, arcs_82_1},
+};
+static arc arcs_83_0[1] = {
+    {21, 1},
+};
+static arc arcs_83_1[1] = {
+    {0, 1},
+};
+static state states_83[2] = {
+    {1, arcs_83_0},
+    {1, arcs_83_1},
+};
+static arc arcs_84_0[1] = {
+    {169, 1},
+};
+static arc arcs_84_1[2] = {
+    {9, 2},
+    {0, 1},
+};
+static arc arcs_84_2[1] = {
+    {0, 2},
+};
+static state states_84[3] = {
+    {1, arcs_84_0},
+    {2, arcs_84_1},
+    {1, arcs_84_2},
+};
+static arc arcs_85_0[1] = {
+    {171, 1},
+};
+static arc arcs_85_1[2] = {
+    {2, 1},
+    {7, 2},
+};
+static arc arcs_85_2[1] = {
+    {0, 2},
+};
+static state states_85[3] = {
+    {1, arcs_85_0},
+    {2, arcs_85_1},
+    {1, arcs_85_2},
+};
+static arc arcs_86_0[1] = {
+    {13, 1},
+};
+static arc arcs_86_1[2] = {
+    {172, 2},
+    {15, 3},
+};
+static arc arcs_86_2[1] = {
+    {15, 3},
+};
+static arc arcs_86_3[1] = {
+    {173, 4},
+};
+static arc arcs_86_4[1] = {
+    {29, 5},
+};
+static arc arcs_86_5[1] = {
+    {0, 5},
+};
+static state states_86[6] = {
+    {1, arcs_86_0},
+    {2, arcs_86_1},
+    {1, arcs_86_2},
+    {1, arcs_86_3},
+    {1, arcs_86_4},
+    {1, arcs_86_5},
+};
+static arc arcs_87_0[3] = {
+    {29, 1},
+    {31, 2},
+    {32, 3},
+};
+static arc arcs_87_1[2] = {
+    {30, 4},
+    {0, 1},
+};
+static arc arcs_87_2[3] = {
+    {29, 5},
+    {30, 6},
+    {0, 2},
+};
+static arc arcs_87_3[1] = {
+    {29, 7},
+};
+static arc arcs_87_4[4] = {
+    {29, 1},
+    {31, 8},
+    {32, 3},
+    {0, 4},
+};
+static arc arcs_87_5[2] = {
+    {30, 6},
+    {0, 5},
+};
+static arc arcs_87_6[2] = {
+    {29, 5},
+    {32, 3},
+};
+static arc arcs_87_7[1] = {
+    {0, 7},
+};
+static arc arcs_87_8[3] = {
+    {29, 9},
+    {30, 10},
+    {0, 8},
+};
+static arc arcs_87_9[2] = {
+    {30, 10},
+    {0, 9},
+};
+static arc arcs_87_10[2] = {
+    {29, 9},
+    {32, 3},
+};
+static state states_87[11] = {
+    {3, arcs_87_0},
+    {2, arcs_87_1},
+    {3, arcs_87_2},
+    {1, arcs_87_3},
+    {4, arcs_87_4},
+    {2, arcs_87_5},
+    {2, arcs_87_6},
+    {1, arcs_87_7},
+    {3, arcs_87_8},
+    {2, arcs_87_9},
+    {2, arcs_87_10},
+};
+static dfa dfas[88] = {
+    {256, "single_input", 0, 3, states_0,
+     "\004\050\060\000\000\000\000\250\340\051\230\040\047\100\020\000\000\103\110\032\004\002"},
+    {257, "file_input", 0, 2, states_1,
+     "\204\050\060\000\000\000\000\250\340\051\230\040\047\100\020\000\000\103\110\032\004\002"},
+    {258, "eval_input", 0, 3, states_2,
+     "\000\040\040\000\000\000\000\000\000\000\000\000\000\100\020\000\000\103\110\032\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\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\000"},
+    {261, "decorated", 0, 3, states_5,
+     "\000\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
+    {262, "funcdef", 0, 7, states_6,
+     "\000\000\020\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
+    {263, "parameters", 0, 4, states_7,
+     "\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
+    {264, "varargslist", 0, 13, states_8,
+     "\000\040\040\200\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
+    {265, "fpdef", 0, 4, states_9,
+     "\000\040\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
+    {266, "fplist", 0, 3, states_10,
+     "\000\040\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
+    {267, "stmt", 0, 2, states_11,
+     "\000\050\060\000\000\000\000\250\340\051\230\040\047\100\020\000\000\103\110\032\004\002"},
+    {268, "simple_stmt", 0, 4, states_12,
+     "\000\040\040\000\000\000\000\250\340\051\230\000\000\100\020\000\000\103\110\032\000\002"},
+    {269, "small_stmt", 0, 2, states_13,
+     "\000\040\040\000\000\000\000\250\340\051\230\000\000\100\020\000\000\103\110\032\000\002"},
+    {270, "expr_stmt", 0, 6, states_14,
+     "\000\040\040\000\000\000\000\000\000\000\000\000\000\100\020\000\000\103\110\032\000\000"},
+    {271, "augassign", 0, 2, states_15,
+     "\000\000\000\000\000\200\377\007\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
+    {272, "print_stmt", 0, 9, states_16,
+     "\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
+    {273, "del_stmt", 0, 3, states_17,
+     "\000\000\000\000\000\000\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
+    {274, "pass_stmt", 0, 2, states_18,
+     "\000\000\000\000\000\000\000\200\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
+    {275, "flow_stmt", 0, 2, states_19,
+     "\000\000\000\000\000\000\000\000\340\001\000\000\000\000\000\000\000\000\000\000\000\002"},
+    {276, "break_stmt", 0, 2, states_20,
+     "\000\000\000\000\000\000\000\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000"},
+    {277, "continue_stmt", 0, 2, states_21,
+     "\000\000\000\000\000\000\000\000\100\000\000\000\000\000\000\000\000\000\000\000\000\000"},
+    {278, "return_stmt", 0, 3, states_22,
+     "\000\000\000\000\000\000\000\000\200\000\000\000\000\000\000\000\000\000\000\000\000\000"},
+    {279, "yield_stmt", 0, 2, states_23,
+     "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002"},
+    {280, "raise_stmt", 0, 7, states_24,
+     "\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000"},
+    {281, "import_stmt", 0, 2, states_25,
+     "\000\000\000\000\000\000\000\000\000\050\000\000\000\000\000\000\000\000\000\000\000\000"},
+    {282, "import_name", 0, 3, states_26,
+     "\000\000\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\000\000\000\000\000"},
+    {283, "import_from", 0, 8, states_27,
+     "\000\000\000\000\000\000\000\000\000\040\000\000\000\000\000\000\000\000\000\000\000\000"},
+    {284, "import_as_name", 0, 4, states_28,
+     "\000\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
+    {285, "dotted_as_name", 0, 4, states_29,
+     "\000\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
+    {286, "import_as_names", 0, 3, states_30,
+     "\000\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
+    {287, "dotted_as_names", 0, 2, states_31,
+     "\000\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
+    {288, "dotted_name", 0, 2, states_32,
+     "\000\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
+    {289, "global_stmt", 0, 3, states_33,
+     "\000\000\000\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\000\000\000\000"},
+    {290, "exec_stmt", 0, 7, states_34,
+     "\000\000\000\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\000\000\000\000"},
+    {291, "assert_stmt", 0, 5, states_35,
+     "\000\000\000\000\000\000\000\000\000\000\200\000\000\000\000\000\000\000\000\000\000\000"},
+    {292, "compound_stmt", 0, 2, states_36,
+     "\000\010\020\000\000\000\000\000\000\000\000\040\047\000\000\000\000\000\000\000\004\000"},
+    {293, "if_stmt", 0, 8, states_37,
+     "\000\000\000\000\000\000\000\000\000\000\000\040\000\000\000\000\000\000\000\000\000\000"},
+    {294, "while_stmt", 0, 8, states_38,
+     "\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000"},
+    {295, "for_stmt", 0, 11, states_39,
+     "\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000"},
+    {296, "try_stmt", 0, 13, states_40,
+     "\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000"},
+    {297, "with_stmt", 0, 6, states_41,
+     "\000\000\000\000\000\000\000\000\000\000\000\000\040\000\000\000\000\000\000\000\000\000"},
+    {298, "with_item", 0, 4, states_42,
+     "\000\040\040\000\000\000\000\000\000\000\000\000\000\100\020\000\000\103\110\032\000\000"},
+    {299, "except_clause", 0, 5, states_43,
+     "\000\000\000\000\000\000\000\000\000\000\000\000\200\000\000\000\000\000\000\000\000\000"},
+    {300, "suite", 0, 7, states_44,
+     "\004\040\040\000\000\000\000\250\340\051\230\000\000\100\020\000\000\103\110\032\000\002"},
+    {301, "testlist_safe", 0, 5, states_45,
+     "\000\040\040\000\000\000\000\000\000\000\000\000\000\100\020\000\000\103\110\032\000\000"},
+    {302, "old_test", 0, 2, states_46,
+     "\000\040\040\000\000\000\000\000\000\000\000\000\000\100\020\000\000\103\110\032\000\000"},
+    {303, "old_lambdef", 0, 5, states_47,
+     "\000\000\000\000\000\000\000\000\000\000\000\000\000\100\000\000\000\000\000\000\000\000"},
+    {304, "test", 0, 6, states_48,
+     "\000\040\040\000\000\000\000\000\000\000\000\000\000\100\020\000\000\103\110\032\000\000"},
+    {305, "or_test", 0, 2, states_49,
+     "\000\040\040\000\000\000\000\000\000\000\000\000\000\000\020\000\000\103\110\032\000\000"},
+    {306, "and_test", 0, 2, states_50,
+     "\000\040\040\000\000\000\000\000\000\000\000\000\000\000\020\000\000\103\110\032\000\000"},
+    {307, "not_test", 0, 3, states_51,
+     "\000\040\040\000\000\000\000\000\000\000\000\000\000\000\020\000\000\103\110\032\000\000"},
+    {308, "comparison", 0, 2, states_52,
+     "\000\040\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\103\110\032\000\000"},
+    {309, "comp_op", 0, 4, states_53,
+     "\000\000\000\000\000\000\000\000\000\000\100\000\000\000\220\177\000\000\000\000\000\000"},
+    {310, "expr", 0, 2, states_54,
+     "\000\040\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\103\110\032\000\000"},
+    {311, "xor_expr", 0, 2, states_55,
+     "\000\040\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\103\110\032\000\000"},
+    {312, "and_expr", 0, 2, states_56,
+     "\000\040\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\103\110\032\000\000"},
+    {313, "shift_expr", 0, 2, states_57,
+     "\000\040\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\103\110\032\000\000"},
+    {314, "arith_expr", 0, 2, states_58,
+     "\000\040\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\103\110\032\000\000"},
+    {315, "term", 0, 2, states_59,
+     "\000\040\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\103\110\032\000\000"},
+    {316, "factor", 0, 3, states_60,
+     "\000\040\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\103\110\032\000\000"},
+    {317, "power", 0, 4, states_61,
+     "\000\040\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\110\032\000\000"},
+    {318, "atom", 0, 11, states_62,
+     "\000\040\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\110\032\000\000"},
+    {319, "listmaker", 0, 5, states_63,
+     "\000\040\040\000\000\000\000\000\000\000\000\000\000\100\020\000\000\103\110\032\000\000"},
+    {320, "testlist_comp", 0, 5, states_64,
+     "\000\040\040\000\000\000\000\000\000\000\000\000\000\100\020\000\000\103\110\032\000\000"},
+    {321, "lambdef", 0, 5, states_65,
+     "\000\000\000\000\000\000\000\000\000\000\000\000\000\100\000\000\000\000\000\000\000\000"},
+    {322, "trailer", 0, 7, states_66,
+     "\000\040\000\000\000\000\000\000\000\100\000\000\000\000\000\000\000\000\010\000\000\000"},
+    {323, "subscriptlist", 0, 3, states_67,
+     "\000\040\240\000\000\000\000\000\000\100\000\000\000\100\020\000\000\103\110\032\000\000"},
+    {324, "subscript", 0, 7, states_68,
+     "\000\040\240\000\000\000\000\000\000\100\000\000\000\100\020\000\000\103\110\032\000\000"},
+    {325, "sliceop", 0, 3, states_69,
+     "\000\000\200\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
+    {326, "exprlist", 0, 3, states_70,
+     "\000\040\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\103\110\032\000\000"},
+    {327, "testlist", 0, 3, states_71,
+     "\000\040\040\000\000\000\000\000\000\000\000\000\000\100\020\000\000\103\110\032\000\000"},
+    {328, "dictorsetmaker", 0, 11, states_72,
+     "\000\040\040\000\000\000\000\000\000\000\000\000\000\100\020\000\000\103\110\032\000\000"},
+    {329, "classdef", 0, 8, states_73,
+     "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000"},
+    {330, "arglist", 0, 8, states_74,
+     "\000\040\040\200\001\000\000\000\000\000\000\000\000\100\020\000\000\103\110\032\000\000"},
+    {331, "argument", 0, 4, states_75,
+     "\000\040\040\000\000\000\000\000\000\000\000\000\000\100\020\000\000\103\110\032\000\000"},
+    {332, "list_iter", 0, 2, states_76,
+     "\000\000\000\000\000\000\000\000\000\000\000\040\002\000\000\000\000\000\000\000\000\000"},
+    {333, "list_for", 0, 6, states_77,
+     "\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000"},
+    {334, "list_if", 0, 4, states_78,
+     "\000\000\000\000\000\000\000\000\000\000\000\040\000\000\000\000\000\000\000\000\000\000"},
+    {335, "comp_iter", 0, 2, states_79,
+     "\000\000\000\000\000\000\000\000\000\000\000\040\002\000\000\000\000\000\000\000\000\000"},
+    {336, "comp_for", 0, 6, states_80,
+     "\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000"},
+    {337, "comp_if", 0, 4, states_81,
+     "\000\000\000\000\000\000\000\000\000\000\000\040\000\000\000\000\000\000\000\000\000\000"},
+    {338, "testlist1", 0, 2, states_82,
+     "\000\040\040\000\000\000\000\000\000\000\000\000\000\100\020\000\000\103\110\032\000\000"},
+    {339, "encoding_decl", 0, 2, states_83,
+     "\000\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
+    {340, "yield_expr", 0, 3, states_84,
+     "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002"},
+    {341, "func_type_input", 0, 3, states_85,
+     "\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
+    {342, "func_type", 0, 6, states_86,
+     "\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
+    {343, "typelist", 0, 11, states_87,
+     "\000\040\040\200\001\000\000\000\000\000\000\000\000\100\020\000\000\103\110\032\000\000"},
+};
+static label labels[174] = {
+    {0, "EMPTY"},
+    {256, 0},
+    {4, 0},
+    {268, 0},
+    {292, 0},
+    {257, 0},
+    {267, 0},
+    {0, 0},
+    {258, 0},
+    {327, 0},
+    {259, 0},
+    {50, 0},
+    {288, 0},
+    {7, 0},
+    {330, 0},
+    {8, 0},
+    {260, 0},
+    {261, 0},
+    {329, 0},
+    {262, 0},
+    {1, "def"},
+    {1, 0},
+    {263, 0},
+    {11, 0},
+    {54, 0},
+    {300, 0},
+    {264, 0},
+    {265, 0},
+    {22, 0},
+    {304, 0},
+    {12, 0},
+    {16, 0},
+    {36, 0},
+    {266, 0},
+    {269, 0},
+    {13, 0},
+    {270, 0},
+    {272, 0},
+    {273, 0},
+    {274, 0},
+    {275, 0},
+    {281, 0},
+    {289, 0},
+    {290, 0},
+    {291, 0},
+    {271, 0},
+    {340, 0},
+    {37, 0},
+    {38, 0},
+    {39, 0},
+    {40, 0},
+    {41, 0},
+    {42, 0},
+    {43, 0},
+    {44, 0},
+    {45, 0},
+    {46, 0},
+    {47, 0},
+    {49, 0},
+    {1, "print"},
+    {35, 0},
+    {1, "del"},
+    {326, 0},
+    {1, "pass"},
+    {276, 0},
+    {277, 0},
+    {278, 0},
+    {280, 0},
+    {279, 0},
+    {1, "break"},
+    {1, "continue"},
+    {1, "return"},
+    {1, "raise"},
+    {282, 0},
+    {283, 0},
+    {1, "import"},
+    {287, 0},
+    {1, "from"},
+    {23, 0},
+    {286, 0},
+    {284, 0},
+    {1, "as"},
+    {285, 0},
+    {1, "global"},
+    {1, "exec"},
+    {310, 0},
+    {1, "in"},
+    {1, "assert"},
+    {293, 0},
+    {294, 0},
+    {295, 0},
+    {296, 0},
+    {297, 0},
+    {1, "if"},
+    {1, "elif"},
+    {1, "else"},
+    {1, "while"},
+    {1, "for"},
+    {1, "try"},
+    {299, 0},
+    {1, "finally"},
+    {1, "with"},
+    {298, 0},
+    {1, "except"},
+    {5, 0},
+    {6, 0},
+    {301, 0},
+    {302, 0},
+    {305, 0},
+    {303, 0},
+    {1, "lambda"},
+    {321, 0},
+    {306, 0},
+    {1, "or"},
+    {307, 0},
+    {1, "and"},
+    {1, "not"},
+    {308, 0},
+    {309, 0},
+    {20, 0},
+    {21, 0},
+    {28, 0},
+    {31, 0},
+    {30, 0},
+    {29, 0},
+    {29, 0},
+    {1, "is"},
+    {311, 0},
+    {18, 0},
+    {312, 0},
+    {33, 0},
+    {313, 0},
+    {19, 0},
+    {314, 0},
+    {34, 0},
+    {315, 0},
+    {14, 0},
+    {15, 0},
+    {316, 0},
+    {17, 0},
+    {24, 0},
+    {48, 0},
+    {32, 0},
+    {317, 0},
+    {318, 0},
+    {322, 0},
+    {320, 0},
+    {9, 0},
+    {319, 0},
+    {10, 0},
+    {26, 0},
+    {328, 0},
+    {27, 0},
+    {25, 0},
+    {338, 0},
+    {2, 0},
+    {3, 0},
+    {333, 0},
+    {336, 0},
+    {323, 0},
+    {324, 0},
+    {325, 0},
+    {1, "class"},
+    {331, 0},
+    {332, 0},
+    {334, 0},
+    {335, 0},
+    {337, 0},
+    {339, 0},
+    {1, "yield"},
+    {341, 0},
+    {342, 0},
+    {343, 0},
+    {52, 0},
+};
+grammar _Ta27Parser_Grammar = {
+    88,
+    dfas,
+    {174, labels},
+    256
+};
diff --git a/ast27/Python/mystrtoul.c b/ast27/Python/mystrtoul.c
new file mode 100644
index 0000000..45ef03f
--- /dev/null
+++ b/ast27/Python/mystrtoul.c
@@ -0,0 +1,285 @@
+
+#include "Python.h"
+
+#if defined(__sgi) && defined(WITH_THREAD) && !defined(_SGI_MP_SOURCE)
+#define _SGI_MP_SOURCE
+#endif
+
+/* strtol and strtoul, renamed to avoid conflicts */
+
+
+#include <ctype.h>
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+
+/* Static overflow check values for bases 2 through 36.
+ * smallmax[base] is the largest unsigned long i such that
+ * i * base doesn't overflow unsigned long.
+ */
+static unsigned long smallmax[] = {
+    0, /* bases 0 and 1 are invalid */
+    0,
+    ULONG_MAX / 2,
+    ULONG_MAX / 3,
+    ULONG_MAX / 4,
+    ULONG_MAX / 5,
+    ULONG_MAX / 6,
+    ULONG_MAX / 7,
+    ULONG_MAX / 8,
+    ULONG_MAX / 9,
+    ULONG_MAX / 10,
+    ULONG_MAX / 11,
+    ULONG_MAX / 12,
+    ULONG_MAX / 13,
+    ULONG_MAX / 14,
+    ULONG_MAX / 15,
+    ULONG_MAX / 16,
+    ULONG_MAX / 17,
+    ULONG_MAX / 18,
+    ULONG_MAX / 19,
+    ULONG_MAX / 20,
+    ULONG_MAX / 21,
+    ULONG_MAX / 22,
+    ULONG_MAX / 23,
+    ULONG_MAX / 24,
+    ULONG_MAX / 25,
+    ULONG_MAX / 26,
+    ULONG_MAX / 27,
+    ULONG_MAX / 28,
+    ULONG_MAX / 29,
+    ULONG_MAX / 30,
+    ULONG_MAX / 31,
+    ULONG_MAX / 32,
+    ULONG_MAX / 33,
+    ULONG_MAX / 34,
+    ULONG_MAX / 35,
+    ULONG_MAX / 36,
+};
+
+/* maximum digits that can't ever overflow for bases 2 through 36,
+ * calculated by [int(math.floor(math.log(2**32, i))) for i in range(2, 37)].
+ * Note that this is pessimistic if sizeof(long) > 4.
+ */
+#if SIZEOF_LONG == 4
+static int digitlimit[] = {
+    0,  0, 32, 20, 16, 13, 12, 11, 10, 10,  /*  0 -  9 */
+    9,  9,  8,  8,  8,  8,  8,  7,  7,  7,  /* 10 - 19 */
+    7,  7,  7,  7,  6,  6,  6,  6,  6,  6,  /* 20 - 29 */
+    6,  6,  6,  6,  6,  6,  6};             /* 30 - 36 */
+#elif SIZEOF_LONG == 8
+/* [int(math.floor(math.log(2**64, i))) for i in range(2, 37)] */
+static int digitlimit[] = {
+         0,   0, 64, 40, 32, 27, 24, 22, 21, 20,  /*  0 -  9 */
+    19,  18, 17, 17, 16, 16, 16, 15, 15, 15,  /* 10 - 19 */
+    14,  14, 14, 14, 13, 13, 13, 13, 13, 13,  /* 20 - 29 */
+    13,  12, 12, 12, 12, 12, 12};             /* 30 - 36 */
+#else
+#error "Need table for SIZEOF_LONG"
+#endif
+
+/*
+**      strtoul
+**              This is a general purpose routine for converting
+**              an ascii string to an integer in an arbitrary base.
+**              Leading white space is ignored.  If 'base' is zero
+**              it looks for a leading 0, 0b, 0B, 0o, 0O, 0x or 0X
+**              to tell which base.  If these are absent it defaults
+**              to 10. Base must be 0 or between 2 and 36 (inclusive).
+**              If 'ptr' is non-NULL it will contain a pointer to
+**              the end of the scan.
+**              Errors due to bad pointers will probably result in
+**              exceptions - we don't check for them.
+*/
+unsigned long
+Ta27OS_strtoul(register char *str, char **ptr, int base)
+{
+    register unsigned long result = 0; /* return value of the function */
+    register int c;             /* current input character */
+    register int ovlimit;       /* required digits to overflow */
+
+    /* skip leading white space */
+    while (*str && isspace(Py_CHARMASK(*str)))
+        ++str;
+
+    /* check for leading 0 or 0x for auto-base or base 16 */
+    switch (base) {
+    case 0:             /* look for leading 0, 0b, 0o or 0x */
+        if (*str == '0') {
+            ++str;
+            if (*str == 'x' || *str == 'X') {
+                /* there must be at least one digit after 0x */
+                if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 16) {
+                    if (ptr)
+                        *ptr = str;
+                    return 0;
+                }
+                ++str;
+                base = 16;
+            } else if (*str == 'o' || *str == 'O') {
+                /* there must be at least one digit after 0o */
+                if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 8) {
+                    if (ptr)
+                        *ptr = str;
+                    return 0;
+                }
+                ++str;
+                base = 8;
+            } else if (*str == 'b' || *str == 'B') {
+                /* there must be at least one digit after 0b */
+                if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 2) {
+                    if (ptr)
+                        *ptr = str;
+                    return 0;
+                }
+                ++str;
+                base = 2;
+            } else {
+                base = 8;
+            }
+        }
+        else
+            base = 10;
+        break;
+
+    case 2:     /* skip leading 0b or 0B */
+        if (*str == '0') {
+            ++str;
+            if (*str == 'b' || *str == 'B') {
+                /* there must be at least one digit after 0b */
+                if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 2) {
+                    if (ptr)
+                        *ptr = str;
+                    return 0;
+                }
+                ++str;
+            }
+        }
+        break;
+
+    case 8:     /* skip leading 0o or 0O */
+        if (*str == '0') {
+            ++str;
+            if (*str == 'o' || *str == 'O') {
+                /* there must be at least one digit after 0o */
+                if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 8) {
+                    if (ptr)
+                        *ptr = str;
+                    return 0;
+                }
+                ++str;
+            }
+        }
+        break;
+
+    case 16:            /* skip leading 0x or 0X */
+        if (*str == '0') {
+            ++str;
+            if (*str == 'x' || *str == 'X') {
+                /* there must be at least one digit after 0x */
+                if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 16) {
+                    if (ptr)
+                        *ptr = str;
+                    return 0;
+                }
+                ++str;
+            }
+        }
+        break;
+    }
+
+    /* catch silly bases */
+    if (base < 2 || base > 36) {
+        if (ptr)
+            *ptr = str;
+        return 0;
+    }
+
+    /* skip leading zeroes */
+    while (*str == '0')
+        ++str;
+
+    /* base is guaranteed to be in [2, 36] at this point */
+    ovlimit = digitlimit[base];
+
+    /* do the conversion until non-digit character encountered */
+    while ((c = _PyLong_DigitValue[Py_CHARMASK(*str)]) < base) {
+        if (ovlimit > 0) /* no overflow check required */
+            result = result * base + c;
+        else { /* requires overflow check */
+            register unsigned long temp_result;
+
+            if (ovlimit < 0) /* guaranteed overflow */
+                goto overflowed;
+
+            /* there could be an overflow */
+            /* check overflow just from shifting */
+            if (result > smallmax[base])
+                goto overflowed;
+
+            result *= base;
+
+            /* check overflow from the digit's value */
+            temp_result = result + c;
+            if (temp_result < result)
+                goto overflowed;
+
+            result = temp_result;
+        }
+
+        ++str;
+        --ovlimit;
+    }
+
+    /* set pointer to point to the last character scanned */
+    if (ptr)
+        *ptr = str;
+
+    return result;
+
+overflowed:
+    if (ptr) {
+        /* spool through remaining digit characters */
+        while (_PyLong_DigitValue[Py_CHARMASK(*str)] < base)
+            ++str;
+        *ptr = str;
+    }
+    errno = ERANGE;
+    return (unsigned long)-1;
+}
+
+/* Checking for overflow in PyOS_strtol is a PITA; see comments
+ * about PY_ABS_LONG_MIN in longobject.c.
+ */
+#define PY_ABS_LONG_MIN         (0-(unsigned long)LONG_MIN)
+
+long
+Ta27OS_strtol(char *str, char **ptr, int base)
+{
+    long result;
+    unsigned long uresult;
+    char sign;
+
+    while (*str && isspace(Py_CHARMASK(*str)))
+        str++;
+
+    sign = *str;
+    if (sign == '+' || sign == '-')
+        str++;
+
+    uresult = Ta27OS_strtoul(str, ptr, base);
+
+    if (uresult <= (unsigned long)LONG_MAX) {
+        result = (long)uresult;
+        if (sign == '-')
+            result = -result;
+    }
+    else if (sign == '-' && uresult == PY_ABS_LONG_MIN) {
+        result = LONG_MIN;
+    }
+    else {
+        errno = ERANGE;
+        result = LONG_MAX;
+    }
+    return result;
+}
diff --git a/ast35/Custom/typed_ast.c b/ast35/Custom/typed_ast.c
new file mode 100644
index 0000000..80172aa
--- /dev/null
+++ b/ast35/Custom/typed_ast.c
@@ -0,0 +1,322 @@
+#include "Python.h"
+#include "Python-ast.h"
+#include "compile.h"
+#include "node.h"
+#include "grammar.h"
+#include "token.h"
+#include "ast.h"
+#include "parsetok.h"
+#include "errcode.h"
+
+extern grammar _Ta35Parser_Grammar; /* from graminit.c */
+
+// from Python/bltinmodule.c
+static const char *
+source_as_string(PyObject *cmd, const char *funcname, const char *what, PyCompilerFlags *cf, PyObject **cmd_copy)
+{
+    const char *str;
+    Py_ssize_t size;
+    Py_buffer view;
+
+    *cmd_copy = NULL;
+    if (PyUnicode_Check(cmd)) {
+        cf->cf_flags |= PyCF_IGNORE_COOKIE;
+        str = PyUnicode_AsUTF8AndSize(cmd, &size);
+        if (str == NULL)
+            return NULL;
+    }
+    else if (PyBytes_Check(cmd)) {
+        str = PyBytes_AS_STRING(cmd);
+        size = PyBytes_GET_SIZE(cmd);
+    }
+    else if (PyByteArray_Check(cmd)) {
+        str = PyByteArray_AS_STRING(cmd);
+        size = PyByteArray_GET_SIZE(cmd);
+    }
+    else if (PyObject_GetBuffer(cmd, &view, PyBUF_SIMPLE) == 0) {
+        /* Copy to NUL-terminated buffer. */
+        *cmd_copy = PyBytes_FromStringAndSize(
+            (const char *)view.buf, view.len);
+        PyBuffer_Release(&view);
+        if (*cmd_copy == NULL) {
+            return NULL;
+        }
+        str = PyBytes_AS_STRING(*cmd_copy);
+        size = PyBytes_GET_SIZE(*cmd_copy);
+    }
+    else {
+        PyErr_Format(PyExc_TypeError,
+          "%s() arg 1 must be a %s object",
+          funcname, what);
+        return NULL;
+    }
+
+    if (strlen(str) != (size_t)size) {
+        PyErr_SetString(PyExc_ValueError,
+                        "source code string cannot contain null bytes");
+        Py_CLEAR(*cmd_copy);
+        return NULL;
+    }
+    return str;
+}
+
+// from Python/pythonrun.c
+/* compute parser flags based on compiler flags */
+static int PARSER_FLAGS(PyCompilerFlags *flags)
+{
+    int parser_flags = 0;
+    if (!flags)
+        return 0;
+    if (flags->cf_flags & PyCF_DONT_IMPLY_DEDENT)
+        parser_flags |= PyPARSE_DONT_IMPLY_DEDENT;
+    if (flags->cf_flags & PyCF_IGNORE_COOKIE)
+        parser_flags |= PyPARSE_IGNORE_COOKIE;
+    if (flags->cf_flags & CO_FUTURE_BARRY_AS_BDFL)
+        parser_flags |= PyPARSE_BARRY_AS_BDFL;
+    return parser_flags;
+}
+
+// from Python/pythonrun.c
+/* Set the error appropriate to the given input error code (see errcode.h) */
+static void
+err_input(perrdetail *err)
+{
+    PyObject *v, *w, *errtype, *errtext;
+    PyObject *msg_obj = NULL;
+    char *msg = NULL;
+    int offset = err->offset;
+
+    errtype = PyExc_SyntaxError;
+    switch (err->error) {
+    case E_ERROR:
+        return;
+    case E_SYNTAX:
+        errtype = PyExc_IndentationError;
+        if (err->expected == INDENT)
+            msg = "expected an indented block";
+        else if (err->token == INDENT)
+            msg = "unexpected indent";
+        else if (err->token == DEDENT)
+            msg = "unexpected unindent";
+        else {
+            errtype = PyExc_SyntaxError;
+            if (err->token == TYPE_COMMENT)
+              msg = "misplaced type annotation";
+            else
+              msg = "invalid syntax";
+        }
+        break;
+    case E_TOKEN:
+        msg = "invalid token";
+        break;
+    case E_EOFS:
+        msg = "EOF while scanning triple-quoted string literal";
+        break;
+    case E_EOLS:
+        msg = "EOL while scanning string literal";
+        break;
+    case E_INTR:
+        if (!PyErr_Occurred())
+            PyErr_SetNone(PyExc_KeyboardInterrupt);
+        goto cleanup;
+    case E_NOMEM:
+        PyErr_NoMemory();
+        goto cleanup;
+    case E_EOF:
+        msg = "unexpected EOF while parsing";
+        break;
+    case E_TABSPACE:
+        errtype = PyExc_TabError;
+        msg = "inconsistent use of tabs and spaces in indentation";
+        break;
+    case E_OVERFLOW:
+        msg = "expression too long";
+        break;
+    case E_DEDENT:
+        errtype = PyExc_IndentationError;
+        msg = "unindent does not match any outer indentation level";
+        break;
+    case E_TOODEEP:
+        errtype = PyExc_IndentationError;
+        msg = "too many levels of indentation";
+        break;
+    case E_DECODE: {
+        PyObject *type, *value, *tb;
+        PyErr_Fetch(&type, &value, &tb);
+        msg = "unknown decode error";
+        if (value != NULL)
+            msg_obj = PyObject_Str(value);
+        Py_XDECREF(type);
+        Py_XDECREF(value);
+        Py_XDECREF(tb);
+        break;
+    }
+    case E_LINECONT:
+        msg = "unexpected character after line continuation character";
+        break;
+
+    case E_IDENTIFIER:
+        msg = "invalid character in identifier";
+        break;
+    case E_BADSINGLE:
+        msg = "multiple statements found while compiling a single statement";
+        break;
+    default:
+        fprintf(stderr, "error=%d\n", err->error);
+        msg = "unknown parsing error";
+        break;
+    }
+    /* err->text may not be UTF-8 in case of decoding errors.
+       Explicitly convert to an object. */
+    if (!err->text) {
+        errtext = Py_None;
+        Py_INCREF(Py_None);
+    } else {
+        errtext = PyUnicode_DecodeUTF8(err->text, err->offset,
+                                       "replace");
+        if (errtext != NULL) {
+            Py_ssize_t len = strlen(err->text);
+            offset = (int)PyUnicode_GET_LENGTH(errtext);
+            if (len != err->offset) {
+                Py_DECREF(errtext);
+                errtext = PyUnicode_DecodeUTF8(err->text, len,
+                                               "replace");
+            }
+        }
+    }
+    v = Py_BuildValue("(OiiN)", err->filename,
+                      err->lineno, offset, errtext);
+    if (v != NULL) {
+        if (msg_obj)
+            w = Py_BuildValue("(OO)", msg_obj, v);
+        else
+            w = Py_BuildValue("(sO)", msg, v);
+    } else
+        w = NULL;
+    Py_XDECREF(v);
+    PyErr_SetObject(errtype, w);
+    Py_XDECREF(w);
+cleanup:
+    Py_XDECREF(msg_obj);
+    if (err->text != NULL) {
+        PyObject_FREE(err->text);
+        err->text = NULL;
+    }
+}
+
+// from Python/pythonrun.c
+static void
+err_free(perrdetail *err)
+{
+    Py_CLEAR(err->filename);
+}
+
+// copy of PyParser_ASTFromStringObject in Python/pythonrun.c
+/* Preferred access to parser is through AST. */
+static mod_ty
+string_object_to_c_ast(const char *s, PyObject *filename, int start,
+                             PyCompilerFlags *flags, PyArena *arena)
+{
+    mod_ty mod;
+    PyCompilerFlags localflags;
+    perrdetail err;
+    int iflags = PARSER_FLAGS(flags);
+
+    node *n = Ta35Parser_ParseStringObject(s, filename,
+                                         &_Ta35Parser_Grammar, start, &err,
+                                         &iflags);
+    if (flags == NULL) {
+        localflags.cf_flags = 0;
+        flags = &localflags;
+    }
+    if (n) {
+        flags->cf_flags |= iflags & PyCF_MASK;
+        mod = Ta35AST_FromNodeObject(n, flags, filename, arena);
+        Ta35Node_Free(n);
+    }
+    else {
+        err_input(&err);
+        mod = NULL;
+    }
+    err_free(&err);
+    return mod;
+}
+
+// adapted from Py_CompileStringObject in Python/pythonrun.c
+static PyObject *
+string_object_to_py_ast(const char *str, PyObject *filename, int start,
+                       PyCompilerFlags *flags)
+{
+    mod_ty mod;
+    PyArena *arena = PyArena_New();
+    if (arena == NULL)
+        return NULL;
+
+    mod = string_object_to_c_ast(str, filename, start, flags, arena);
+    if (mod == NULL) {
+        PyArena_Free(arena);
+        return NULL;
+    }
+
+    PyObject *result = Ta35AST_mod2obj(mod);
+    PyArena_Free(arena);
+    return result;
+}
+
+// adapted from builtin_compile_impl in Python/bltinmodule.c
+static PyObject *
+ast35_parse_impl(PyObject *source,
+                     PyObject *filename, const char *mode)
+{
+    PyObject *source_copy;
+    const char *str;
+    int compile_mode = -1;
+    PyCompilerFlags cf;
+    int start[] = {Py_file_input, Py_eval_input, Py_single_input, Py_func_type_input};
+    PyObject *result;
+
+    cf.cf_flags = PyCF_ONLY_AST | PyCF_SOURCE_IS_UTF8;
+
+    if (strcmp(mode, "exec") == 0)
+        compile_mode = 0;
+    else if (strcmp(mode, "eval") == 0)
+        compile_mode = 1;
+    else if (strcmp(mode, "single") == 0)
+        compile_mode = 2;
+    else if (strcmp(mode, "func_type") == 0)
+        compile_mode = 3;
+    else {
+        PyErr_SetString(PyExc_ValueError,
+                        "parse() mode must be 'exec', 'eval', 'single', for 'func_type'");
+        goto error;
+    }
+
+    str = source_as_string(source, "parse", "string or bytes", &cf, &source_copy);
+    if (str == NULL)
+        goto error;
+
+    result = string_object_to_py_ast(str, filename, start[compile_mode], &cf);
+    Py_XDECREF(source_copy);
+    goto finally;
+
+error:
+    result = NULL;
+finally:
+    Py_DECREF(filename);
+    return result;
+}
+
+// adapted from builtin_compile in Python/clinic/bltinmodule.c.h
+PyObject *
+ast35_parse(PyObject *self, PyObject *args)
+{
+    PyObject *return_value = NULL;
+    PyObject *source;
+    PyObject *filename;
+    const char *mode;
+
+    if (PyArg_ParseTuple(args, "OO&s:parse", &source, PyUnicode_FSDecoder, &filename, &mode))
+        return_value = ast35_parse_impl(source, filename, mode);
+
+    return return_value;
+}
diff --git a/ast35/Grammar/Grammar b/ast35/Grammar/Grammar
new file mode 100644
index 0000000..7aef9be
--- /dev/null
+++ b/ast35/Grammar/Grammar
@@ -0,0 +1,162 @@
+# Grammar for Python
+
+# Note:  Changing the grammar specified in this file will most likely
+#        require corresponding changes in the parser module
+#        (../Modules/parsermodule.c).  If you can't make the changes to
+#        that module yourself, please co-ordinate the required changes
+#        with someone who can; ask around on python-dev for help.  Fred
+#        Drake <fdrake at acm.org> will probably be listening there.
+
+# NOTE WELL: You should also follow all the steps listed at
+# https://docs.python.org/devguide/grammar.html
+
+# Start symbols for the grammar:
+#       single_input is a single interactive statement;
+#       file_input is a module or sequence of commands read from an input file;
+#       eval_input is the input for the eval() functions.
+#       func_type_input is a PEP 484 Python 2 function type comment
+# NB: compound_stmt in single_input is followed by extra NEWLINE!
+# NB: due to the way TYPE_COMMENT is tokenized it will always be followed by a
+#      NEWLINE
+single_input: NEWLINE | simple_stmt | compound_stmt NEWLINE
+file_input: (NEWLINE | stmt)* ENDMARKER
+eval_input: testlist NEWLINE* ENDMARKER
+
+decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE
+decorators: decorator+
+decorated: decorators (classdef | funcdef | async_funcdef)
+
+async_funcdef: ASYNC funcdef
+funcdef: 'def' NAME parameters ['->' test] ':' [TYPE_COMMENT] suite
+
+parameters: '(' [typedargslist] ')'
+typedargslist: (tfpdef ['=' test] (',' [TYPE_COMMENT] tfpdef ['=' test])* [',' [TYPE_COMMENT]
+       ['*' [tfpdef] (',' [TYPE_COMMENT] tfpdef ['=' test])* [',' [TYPE_COMMENT] '**' tfpdef] | '**' tfpdef]] [TYPE_COMMENT]
+     |  '*' [tfpdef] (',' [TYPE_COMMENT] tfpdef ['=' test])* [',' [TYPE_COMMENT] '**' tfpdef] [TYPE_COMMENT]
+     | '**' tfpdef [TYPE_COMMENT])
+tfpdef: NAME [':' test]
+varargslist: (vfpdef ['=' test] (',' vfpdef ['=' test])* [','
+       ['*' [vfpdef] (',' vfpdef ['=' test])* [',' '**' vfpdef] | '**' vfpdef]]
+     |  '*' [vfpdef] (',' vfpdef ['=' test])* [',' '**' vfpdef] | '**' vfpdef)
+vfpdef: NAME
+
+stmt: simple_stmt | compound_stmt
+simple_stmt: small_stmt (';' small_stmt)* [';'] NEWLINE
+small_stmt: (expr_stmt | del_stmt | pass_stmt | flow_stmt |
+             import_stmt | global_stmt | nonlocal_stmt | assert_stmt)
+expr_stmt: testlist_star_expr (augassign (yield_expr|testlist) |
+                     ('=' (yield_expr|testlist_star_expr))* [TYPE_COMMENT])
+testlist_star_expr: (test|star_expr) (',' (test|star_expr))* [',']
+augassign: ('+=' | '-=' | '*=' | '@=' | '/=' | '%=' | '&=' | '|=' | '^=' |
+            '<<=' | '>>=' | '**=' | '//=')
+# For normal assignments, additional restrictions enforced by the interpreter
+del_stmt: 'del' exprlist
+pass_stmt: 'pass'
+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_expr
+raise_stmt: 'raise' [test ['from' test]]
+import_stmt: import_name | import_from
+import_name: 'import' dotted_as_names
+# note below: the ('.' | '...') is necessary because '...' is tokenized as ELLIPSIS
+import_from: ('from' (('.' | '...')* dotted_name | ('.' | '...')+)
+              'import' ('*' | '(' import_as_names ')' | import_as_names))
+import_as_name: NAME ['as' NAME]
+dotted_as_name: dotted_name ['as' NAME]
+import_as_names: import_as_name (',' import_as_name)* [',']
+dotted_as_names: dotted_as_name (',' dotted_as_name)*
+dotted_name: NAME ('.' NAME)*
+global_stmt: 'global' NAME (',' NAME)*
+nonlocal_stmt: 'nonlocal' NAME (',' NAME)*
+assert_stmt: 'assert' test [',' test]
+
+compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt | with_stmt | funcdef | classdef | decorated | async_stmt
+async_stmt: ASYNC (funcdef | with_stmt | for_stmt)
+if_stmt: 'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite]
+while_stmt: 'while' test ':' suite ['else' ':' suite]
+for_stmt: 'for' exprlist 'in' testlist ':' [TYPE_COMMENT] suite ['else' ':' suite]
+try_stmt: ('try' ':' suite
+           ((except_clause ':' suite)+
+            ['else' ':' suite]
+            ['finally' ':' suite] |
+           'finally' ':' suite))
+with_stmt: 'with' with_item (',' with_item)*  ':' [TYPE_COMMENT] suite
+with_item: test ['as' expr]
+# NB compile.c makes sure that the default except clause is last
+except_clause: 'except' [test ['as' NAME]]
+# the TYPE_COMMENT in suites is only parsed for funcdefs, but can't go elsewhere due to ambiguity
+suite: simple_stmt | NEWLINE [TYPE_COMMENT NEWLINE] INDENT stmt+ DEDENT
+
+test: or_test ['if' or_test 'else' test] | lambdef
+test_nocond: or_test | lambdef_nocond
+lambdef: 'lambda' [varargslist] ':' test
+lambdef_nocond: 'lambda' [varargslist] ':' test_nocond
+or_test: and_test ('or' and_test)*
+and_test: not_test ('and' not_test)*
+not_test: 'not' not_test | comparison
+comparison: expr (comp_op expr)*
+# <> isn't actually a valid comparison operator in Python. It's here for the
+# sake of a __future__ import described in PEP 401 (which really works :-)
+comp_op: '<'|'>'|'=='|'>='|'<='|'<>'|'!='|'in'|'not' 'in'|'is'|'is' 'not'
+star_expr: '*' expr
+expr: xor_expr ('|' xor_expr)*
+xor_expr: and_expr ('^' and_expr)*
+and_expr: shift_expr ('&' shift_expr)*
+shift_expr: arith_expr (('<<'|'>>') arith_expr)*
+arith_expr: term (('+'|'-') term)*
+term: factor (('*'|'@'|'/'|'%'|'//') factor)*
+factor: ('+'|'-'|'~') factor | power
+power: atom_expr ['**' factor]
+atom_expr: [AWAIT] atom trailer*
+atom: ('(' [yield_expr|testlist_comp] ')' |
+       '[' [testlist_comp] ']' |
+       '{' [dictorsetmaker] '}' |
+       NAME | NUMBER | STRING+ | '...' | 'None' | 'True' | 'False')
+testlist_comp: (test|star_expr) ( comp_for | (',' (test|star_expr))* [','] )
+trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME
+subscriptlist: subscript (',' subscript)* [',']
+subscript: test | [test] ':' [test] [sliceop]
+sliceop: ':' [test]
+exprlist: (expr|star_expr) (',' (expr|star_expr))* [',']
+testlist: test (',' test)* [',']
+dictorsetmaker: ( ((test ':' test | '**' expr)
+                   (comp_for | (',' (test ':' test | '**' expr))* [','])) |
+                  ((test | star_expr)
+                   (comp_for | (',' (test | star_expr))* [','])) )
+
+classdef: 'class' NAME ['(' [arglist] ')'] ':' suite
+
+arglist: argument (',' argument)*  [',']
+
+# The reason that keywords are test nodes instead of NAME is that using NAME
+# results in an ambiguity. ast.c makes sure it's a NAME.
+# "test '=' test" is really "keyword '=' test", but we have no such token.
+# These need to be in a single rule to avoid grammar that is ambiguous
+# to our LL(1) parser. Even though 'test' includes '*expr' in star_expr,
+# we explicitly match '*' here, too, to give it proper precedence.
+# Illegal combinations and orderings are blocked in ast.c:
+# multiple (test comp_for) arguements are blocked; keyword unpackings
+# that precede iterable unpackings are blocked; etc.
+argument: ( test [comp_for] |
+            test '=' test |
+            '**' test |
+            '*' test )
+
+comp_iter: comp_for | comp_if
+comp_for: 'for' exprlist 'in' or_test [comp_iter]
+comp_if: 'if' test_nocond [comp_iter]
+
+# not used in grammar, but may appear in "node" passed from Parser to Compiler
+encoding_decl: NAME
+
+yield_expr: 'yield' [yield_arg]
+yield_arg: 'from' test | testlist
+
+func_type_input: func_type NEWLINE* ENDMARKER
+func_type: '(' [typelist] ')' '->' test
+# typelist is a modified typedargslist (see above)
+typelist: (test (',' test)* [','
+       ['*' [test] (',' test)* [',' '**' test] | '**' test]]
+     |  '*' [test] (',' test)* [',' '**' test] | '**' test)
diff --git a/ast35/Include/Python-ast.h b/ast35/Include/Python-ast.h
new file mode 100644
index 0000000..83b92ba
--- /dev/null
+++ b/ast35/Include/Python-ast.h
@@ -0,0 +1,633 @@
+/* File automatically generated by Parser/asdl_c.py. */
+
+#include "asdl.h"
+
+typedef struct _mod *mod_ty;
+
+typedef struct _stmt *stmt_ty;
+
+typedef struct _expr *expr_ty;
+
+typedef enum _expr_context { Load=1, Store=2, Del=3, AugLoad=4, AugStore=5,
+                             Param=6 } expr_context_ty;
+
+typedef struct _slice *slice_ty;
+
+typedef enum _boolop { And=1, Or=2 } boolop_ty;
+
+typedef enum _operator { Add=1, Sub=2, Mult=3, MatMult=4, Div=5, Mod=6, Pow=7,
+                         LShift=8, RShift=9, BitOr=10, BitXor=11, BitAnd=12,
+                         FloorDiv=13 } operator_ty;
+
+typedef enum _unaryop { Invert=1, Not=2, UAdd=3, USub=4 } unaryop_ty;
+
+typedef enum _cmpop { Eq=1, NotEq=2, Lt=3, LtE=4, Gt=5, GtE=6, Is=7, IsNot=8,
+                      In=9, NotIn=10 } cmpop_ty;
+
+typedef struct _comprehension *comprehension_ty;
+
+typedef struct _excepthandler *excepthandler_ty;
+
+typedef struct _arguments *arguments_ty;
+
+typedef struct _arg *arg_ty;
+
+typedef struct _keyword *keyword_ty;
+
+typedef struct _alias *alias_ty;
+
+typedef struct _withitem *withitem_ty;
+
+typedef struct _type_ignore *type_ignore_ty;
+
+
+enum _mod_kind {Module_kind=1, Interactive_kind=2, Expression_kind=3,
+                 FunctionType_kind=4, Suite_kind=5};
+struct _mod {
+    enum _mod_kind kind;
+    union {
+        struct {
+            asdl_seq *body;
+            asdl_seq *type_ignores;
+        } Module;
+        
+        struct {
+            asdl_seq *body;
+        } Interactive;
+        
+        struct {
+            expr_ty body;
+        } Expression;
+        
+        struct {
+            asdl_seq *argtypes;
+            expr_ty returns;
+        } FunctionType;
+        
+        struct {
+            asdl_seq *body;
+        } Suite;
+        
+    } v;
+};
+
+enum _stmt_kind {FunctionDef_kind=1, AsyncFunctionDef_kind=2, ClassDef_kind=3,
+                  Return_kind=4, Delete_kind=5, Assign_kind=6,
+                  AugAssign_kind=7, For_kind=8, AsyncFor_kind=9, While_kind=10,
+                  If_kind=11, With_kind=12, AsyncWith_kind=13, Raise_kind=14,
+                  Try_kind=15, Assert_kind=16, Import_kind=17,
+                  ImportFrom_kind=18, Global_kind=19, Nonlocal_kind=20,
+                  Expr_kind=21, Pass_kind=22, Break_kind=23, Continue_kind=24};
+struct _stmt {
+    enum _stmt_kind kind;
+    union {
+        struct {
+            identifier name;
+            arguments_ty args;
+            asdl_seq *body;
+            asdl_seq *decorator_list;
+            expr_ty returns;
+            string type_comment;
+        } FunctionDef;
+        
+        struct {
+            identifier name;
+            arguments_ty args;
+            asdl_seq *body;
+            asdl_seq *decorator_list;
+            expr_ty returns;
+            string type_comment;
+        } AsyncFunctionDef;
+        
+        struct {
+            identifier name;
+            asdl_seq *bases;
+            asdl_seq *keywords;
+            asdl_seq *body;
+            asdl_seq *decorator_list;
+        } ClassDef;
+        
+        struct {
+            expr_ty value;
+        } Return;
+        
+        struct {
+            asdl_seq *targets;
+        } Delete;
+        
+        struct {
+            asdl_seq *targets;
+            expr_ty value;
+            string type_comment;
+        } Assign;
+        
+        struct {
+            expr_ty target;
+            operator_ty op;
+            expr_ty value;
+        } AugAssign;
+        
+        struct {
+            expr_ty target;
+            expr_ty iter;
+            asdl_seq *body;
+            asdl_seq *orelse;
+            string type_comment;
+        } For;
+        
+        struct {
+            expr_ty target;
+            expr_ty iter;
+            asdl_seq *body;
+            asdl_seq *orelse;
+        } AsyncFor;
+        
+        struct {
+            expr_ty test;
+            asdl_seq *body;
+            asdl_seq *orelse;
+        } While;
+        
+        struct {
+            expr_ty test;
+            asdl_seq *body;
+            asdl_seq *orelse;
+        } If;
+        
+        struct {
+            asdl_seq *items;
+            asdl_seq *body;
+            string type_comment;
+        } With;
+        
+        struct {
+            asdl_seq *items;
+            asdl_seq *body;
+        } AsyncWith;
+        
+        struct {
+            expr_ty exc;
+            expr_ty cause;
+        } Raise;
+        
+        struct {
+            asdl_seq *body;
+            asdl_seq *handlers;
+            asdl_seq *orelse;
+            asdl_seq *finalbody;
+        } Try;
+        
+        struct {
+            expr_ty test;
+            expr_ty msg;
+        } Assert;
+        
+        struct {
+            asdl_seq *names;
+        } Import;
+        
+        struct {
+            identifier module;
+            asdl_seq *names;
+            int level;
+        } ImportFrom;
+        
+        struct {
+            asdl_seq *names;
+        } Global;
+        
+        struct {
+            asdl_seq *names;
+        } Nonlocal;
+        
+        struct {
+            expr_ty value;
+        } Expr;
+        
+    } v;
+    int lineno;
+    int col_offset;
+};
+
+enum _expr_kind {BoolOp_kind=1, BinOp_kind=2, UnaryOp_kind=3, Lambda_kind=4,
+                  IfExp_kind=5, Dict_kind=6, Set_kind=7, ListComp_kind=8,
+                  SetComp_kind=9, DictComp_kind=10, GeneratorExp_kind=11,
+                  Await_kind=12, Yield_kind=13, YieldFrom_kind=14,
+                  Compare_kind=15, Call_kind=16, Num_kind=17, Str_kind=18,
+                  Bytes_kind=19, NameConstant_kind=20, Ellipsis_kind=21,
+                  Attribute_kind=22, Subscript_kind=23, Starred_kind=24,
+                  Name_kind=25, List_kind=26, Tuple_kind=27};
+struct _expr {
+    enum _expr_kind kind;
+    union {
+        struct {
+            boolop_ty op;
+            asdl_seq *values;
+        } BoolOp;
+        
+        struct {
+            expr_ty left;
+            operator_ty op;
+            expr_ty right;
+        } BinOp;
+        
+        struct {
+            unaryop_ty op;
+            expr_ty operand;
+        } UnaryOp;
+        
+        struct {
+            arguments_ty args;
+            expr_ty body;
+        } Lambda;
+        
+        struct {
+            expr_ty test;
+            expr_ty body;
+            expr_ty orelse;
+        } IfExp;
+        
+        struct {
+            asdl_seq *keys;
+            asdl_seq *values;
+        } Dict;
+        
+        struct {
+            asdl_seq *elts;
+        } Set;
+        
+        struct {
+            expr_ty elt;
+            asdl_seq *generators;
+        } ListComp;
+        
+        struct {
+            expr_ty elt;
+            asdl_seq *generators;
+        } SetComp;
+        
+        struct {
+            expr_ty key;
+            expr_ty value;
+            asdl_seq *generators;
+        } DictComp;
+        
+        struct {
+            expr_ty elt;
+            asdl_seq *generators;
+        } GeneratorExp;
+        
+        struct {
+            expr_ty value;
+        } Await;
+        
+        struct {
+            expr_ty value;
+        } Yield;
+        
+        struct {
+            expr_ty value;
+        } YieldFrom;
+        
+        struct {
+            expr_ty left;
+            asdl_int_seq *ops;
+            asdl_seq *comparators;
+        } Compare;
+        
+        struct {
+            expr_ty func;
+            asdl_seq *args;
+            asdl_seq *keywords;
+        } Call;
+        
+        struct {
+            object n;
+        } Num;
+        
+        struct {
+            string s;
+        } Str;
+        
+        struct {
+            bytes s;
+        } Bytes;
+        
+        struct {
+            singleton value;
+        } NameConstant;
+        
+        struct {
+            expr_ty value;
+            identifier attr;
+            expr_context_ty ctx;
+        } Attribute;
+        
+        struct {
+            expr_ty value;
+            slice_ty slice;
+            expr_context_ty ctx;
+        } Subscript;
+        
+        struct {
+            expr_ty value;
+            expr_context_ty ctx;
+        } Starred;
+        
+        struct {
+            identifier id;
+            expr_context_ty ctx;
+        } Name;
+        
+        struct {
+            asdl_seq *elts;
+            expr_context_ty ctx;
+        } List;
+        
+        struct {
+            asdl_seq *elts;
+            expr_context_ty ctx;
+        } Tuple;
+        
+    } v;
+    int lineno;
+    int col_offset;
+};
+
+enum _slice_kind {Slice_kind=1, ExtSlice_kind=2, Index_kind=3};
+struct _slice {
+    enum _slice_kind kind;
+    union {
+        struct {
+            expr_ty lower;
+            expr_ty upper;
+            expr_ty step;
+        } Slice;
+        
+        struct {
+            asdl_seq *dims;
+        } ExtSlice;
+        
+        struct {
+            expr_ty value;
+        } Index;
+        
+    } v;
+};
+
+struct _comprehension {
+    expr_ty target;
+    expr_ty iter;
+    asdl_seq *ifs;
+};
+
+enum _excepthandler_kind {ExceptHandler_kind=1};
+struct _excepthandler {
+    enum _excepthandler_kind kind;
+    union {
+        struct {
+            expr_ty type;
+            identifier name;
+            asdl_seq *body;
+        } ExceptHandler;
+        
+    } v;
+    int lineno;
+    int col_offset;
+};
+
+struct _arguments {
+    asdl_seq *args;
+    arg_ty vararg;
+    asdl_seq *kwonlyargs;
+    asdl_seq *kw_defaults;
+    arg_ty kwarg;
+    asdl_seq *defaults;
+};
+
+struct _arg {
+    identifier arg;
+    expr_ty annotation;
+    int lineno;
+    int col_offset;
+};
+
+struct _keyword {
+    identifier arg;
+    expr_ty value;
+};
+
+struct _alias {
+    identifier name;
+    identifier asname;
+};
+
+struct _withitem {
+    expr_ty context_expr;
+    expr_ty optional_vars;
+};
+
+enum _type_ignore_kind {TypeIgnore_kind=1};
+struct _type_ignore {
+    enum _type_ignore_kind kind;
+    union {
+        struct {
+            int lineno;
+        } TypeIgnore;
+        
+    } v;
+};
+
+
+#define Module(a0, a1, a2) _Ta35_Module(a0, a1, a2)
+mod_ty _Ta35_Module(asdl_seq * body, asdl_seq * type_ignores, PyArena *arena);
+#define Interactive(a0, a1) _Ta35_Interactive(a0, a1)
+mod_ty _Ta35_Interactive(asdl_seq * body, PyArena *arena);
+#define Expression(a0, a1) _Ta35_Expression(a0, a1)
+mod_ty _Ta35_Expression(expr_ty body, PyArena *arena);
+#define FunctionType(a0, a1, a2) _Ta35_FunctionType(a0, a1, a2)
+mod_ty _Ta35_FunctionType(asdl_seq * argtypes, expr_ty returns, PyArena *arena);
+#define Suite(a0, a1) _Ta35_Suite(a0, a1)
+mod_ty _Ta35_Suite(asdl_seq * body, PyArena *arena);
+#define FunctionDef(a0, a1, a2, a3, a4, a5, a6, a7, a8) _Ta35_FunctionDef(a0, a1, a2, a3, a4, a5, a6, a7, a8)
+stmt_ty _Ta35_FunctionDef(identifier name, arguments_ty args, asdl_seq * body,
+                          asdl_seq * decorator_list, expr_ty returns, string
+                          type_comment, int lineno, int col_offset, PyArena
+                          *arena);
+#define AsyncFunctionDef(a0, a1, a2, a3, a4, a5, a6, a7, a8) _Ta35_AsyncFunctionDef(a0, a1, a2, a3, a4, a5, a6, a7, a8)
+stmt_ty _Ta35_AsyncFunctionDef(identifier name, arguments_ty args, asdl_seq *
+                               body, asdl_seq * decorator_list, expr_ty
+                               returns, string type_comment, int lineno, int
+                               col_offset, PyArena *arena);
+#define ClassDef(a0, a1, a2, a3, a4, a5, a6, a7) _Ta35_ClassDef(a0, a1, a2, a3, a4, a5, a6, a7)
+stmt_ty _Ta35_ClassDef(identifier name, asdl_seq * bases, asdl_seq * keywords,
+                       asdl_seq * body, asdl_seq * decorator_list, int lineno,
+                       int col_offset, PyArena *arena);
+#define Return(a0, a1, a2, a3) _Ta35_Return(a0, a1, a2, a3)
+stmt_ty _Ta35_Return(expr_ty value, int lineno, int col_offset, PyArena *arena);
+#define Delete(a0, a1, a2, a3) _Ta35_Delete(a0, a1, a2, a3)
+stmt_ty _Ta35_Delete(asdl_seq * targets, int lineno, int col_offset, PyArena
+                     *arena);
+#define Assign(a0, a1, a2, a3, a4, a5) _Ta35_Assign(a0, a1, a2, a3, a4, a5)
+stmt_ty _Ta35_Assign(asdl_seq * targets, expr_ty value, string type_comment,
+                     int lineno, int col_offset, PyArena *arena);
+#define AugAssign(a0, a1, a2, a3, a4, a5) _Ta35_AugAssign(a0, a1, a2, a3, a4, a5)
+stmt_ty _Ta35_AugAssign(expr_ty target, operator_ty op, expr_ty value, int
+                        lineno, int col_offset, PyArena *arena);
+#define For(a0, a1, a2, a3, a4, a5, a6, a7) _Ta35_For(a0, a1, a2, a3, a4, a5, a6, a7)
+stmt_ty _Ta35_For(expr_ty target, expr_ty iter, asdl_seq * body, asdl_seq *
+                  orelse, string type_comment, int lineno, int col_offset,
+                  PyArena *arena);
+#define AsyncFor(a0, a1, a2, a3, a4, a5, a6) _Ta35_AsyncFor(a0, a1, a2, a3, a4, a5, a6)
+stmt_ty _Ta35_AsyncFor(expr_ty target, expr_ty iter, asdl_seq * body, asdl_seq
+                       * orelse, int lineno, int col_offset, PyArena *arena);
+#define While(a0, a1, a2, a3, a4, a5) _Ta35_While(a0, a1, a2, a3, a4, a5)
+stmt_ty _Ta35_While(expr_ty test, asdl_seq * body, asdl_seq * orelse, int
+                    lineno, int col_offset, PyArena *arena);
+#define If(a0, a1, a2, a3, a4, a5) _Ta35_If(a0, a1, a2, a3, a4, a5)
+stmt_ty _Ta35_If(expr_ty test, asdl_seq * body, asdl_seq * orelse, int lineno,
+                 int col_offset, PyArena *arena);
+#define With(a0, a1, a2, a3, a4, a5) _Ta35_With(a0, a1, a2, a3, a4, a5)
+stmt_ty _Ta35_With(asdl_seq * items, asdl_seq * body, string type_comment, int
+                   lineno, int col_offset, PyArena *arena);
+#define AsyncWith(a0, a1, a2, a3, a4) _Ta35_AsyncWith(a0, a1, a2, a3, a4)
+stmt_ty _Ta35_AsyncWith(asdl_seq * items, asdl_seq * body, int lineno, int
+                        col_offset, PyArena *arena);
+#define Raise(a0, a1, a2, a3, a4) _Ta35_Raise(a0, a1, a2, a3, a4)
+stmt_ty _Ta35_Raise(expr_ty exc, expr_ty cause, int lineno, int col_offset,
+                    PyArena *arena);
+#define Try(a0, a1, a2, a3, a4, a5, a6) _Ta35_Try(a0, a1, a2, a3, a4, a5, a6)
+stmt_ty _Ta35_Try(asdl_seq * body, asdl_seq * handlers, asdl_seq * orelse,
+                  asdl_seq * finalbody, int lineno, int col_offset, PyArena
+                  *arena);
+#define Assert(a0, a1, a2, a3, a4) _Ta35_Assert(a0, a1, a2, a3, a4)
+stmt_ty _Ta35_Assert(expr_ty test, expr_ty msg, int lineno, int col_offset,
+                     PyArena *arena);
+#define Import(a0, a1, a2, a3) _Ta35_Import(a0, a1, a2, a3)
+stmt_ty _Ta35_Import(asdl_seq * names, int lineno, int col_offset, PyArena
+                     *arena);
+#define ImportFrom(a0, a1, a2, a3, a4, a5) _Ta35_ImportFrom(a0, a1, a2, a3, a4, a5)
+stmt_ty _Ta35_ImportFrom(identifier module, asdl_seq * names, int level, int
+                         lineno, int col_offset, PyArena *arena);
+#define Global(a0, a1, a2, a3) _Ta35_Global(a0, a1, a2, a3)
+stmt_ty _Ta35_Global(asdl_seq * names, int lineno, int col_offset, PyArena
+                     *arena);
+#define Nonlocal(a0, a1, a2, a3) _Ta35_Nonlocal(a0, a1, a2, a3)
+stmt_ty _Ta35_Nonlocal(asdl_seq * names, int lineno, int col_offset, PyArena
+                       *arena);
+#define Expr(a0, a1, a2, a3) _Ta35_Expr(a0, a1, a2, a3)
+stmt_ty _Ta35_Expr(expr_ty value, int lineno, int col_offset, PyArena *arena);
+#define Pass(a0, a1, a2) _Ta35_Pass(a0, a1, a2)
+stmt_ty _Ta35_Pass(int lineno, int col_offset, PyArena *arena);
+#define Break(a0, a1, a2) _Ta35_Break(a0, a1, a2)
+stmt_ty _Ta35_Break(int lineno, int col_offset, PyArena *arena);
+#define Continue(a0, a1, a2) _Ta35_Continue(a0, a1, a2)
+stmt_ty _Ta35_Continue(int lineno, int col_offset, PyArena *arena);
+#define BoolOp(a0, a1, a2, a3, a4) _Ta35_BoolOp(a0, a1, a2, a3, a4)
+expr_ty _Ta35_BoolOp(boolop_ty op, asdl_seq * values, int lineno, int
+                     col_offset, PyArena *arena);
+#define BinOp(a0, a1, a2, a3, a4, a5) _Ta35_BinOp(a0, a1, a2, a3, a4, a5)
+expr_ty _Ta35_BinOp(expr_ty left, operator_ty op, expr_ty right, int lineno,
+                    int col_offset, PyArena *arena);
+#define UnaryOp(a0, a1, a2, a3, a4) _Ta35_UnaryOp(a0, a1, a2, a3, a4)
+expr_ty _Ta35_UnaryOp(unaryop_ty op, expr_ty operand, int lineno, int
+                      col_offset, PyArena *arena);
+#define Lambda(a0, a1, a2, a3, a4) _Ta35_Lambda(a0, a1, a2, a3, a4)
+expr_ty _Ta35_Lambda(arguments_ty args, expr_ty body, int lineno, int
+                     col_offset, PyArena *arena);
+#define IfExp(a0, a1, a2, a3, a4, a5) _Ta35_IfExp(a0, a1, a2, a3, a4, a5)
+expr_ty _Ta35_IfExp(expr_ty test, expr_ty body, expr_ty orelse, int lineno, int
+                    col_offset, PyArena *arena);
+#define Dict(a0, a1, a2, a3, a4) _Ta35_Dict(a0, a1, a2, a3, a4)
+expr_ty _Ta35_Dict(asdl_seq * keys, asdl_seq * values, int lineno, int
+                   col_offset, PyArena *arena);
+#define Set(a0, a1, a2, a3) _Ta35_Set(a0, a1, a2, a3)
+expr_ty _Ta35_Set(asdl_seq * elts, int lineno, int col_offset, PyArena *arena);
+#define ListComp(a0, a1, a2, a3, a4) _Ta35_ListComp(a0, a1, a2, a3, a4)
+expr_ty _Ta35_ListComp(expr_ty elt, asdl_seq * generators, int lineno, int
+                       col_offset, PyArena *arena);
+#define SetComp(a0, a1, a2, a3, a4) _Ta35_SetComp(a0, a1, a2, a3, a4)
+expr_ty _Ta35_SetComp(expr_ty elt, asdl_seq * generators, int lineno, int
+                      col_offset, PyArena *arena);
+#define DictComp(a0, a1, a2, a3, a4, a5) _Ta35_DictComp(a0, a1, a2, a3, a4, a5)
+expr_ty _Ta35_DictComp(expr_ty key, expr_ty value, asdl_seq * generators, int
+                       lineno, int col_offset, PyArena *arena);
+#define GeneratorExp(a0, a1, a2, a3, a4) _Ta35_GeneratorExp(a0, a1, a2, a3, a4)
+expr_ty _Ta35_GeneratorExp(expr_ty elt, asdl_seq * generators, int lineno, int
+                           col_offset, PyArena *arena);
+#define Await(a0, a1, a2, a3) _Ta35_Await(a0, a1, a2, a3)
+expr_ty _Ta35_Await(expr_ty value, int lineno, int col_offset, PyArena *arena);
+#define Yield(a0, a1, a2, a3) _Ta35_Yield(a0, a1, a2, a3)
+expr_ty _Ta35_Yield(expr_ty value, int lineno, int col_offset, PyArena *arena);
+#define YieldFrom(a0, a1, a2, a3) _Ta35_YieldFrom(a0, a1, a2, a3)
+expr_ty _Ta35_YieldFrom(expr_ty value, int lineno, int col_offset, PyArena
+                        *arena);
+#define Compare(a0, a1, a2, a3, a4, a5) _Ta35_Compare(a0, a1, a2, a3, a4, a5)
+expr_ty _Ta35_Compare(expr_ty left, asdl_int_seq * ops, asdl_seq * comparators,
+                      int lineno, int col_offset, PyArena *arena);
+#define Call(a0, a1, a2, a3, a4, a5) _Ta35_Call(a0, a1, a2, a3, a4, a5)
+expr_ty _Ta35_Call(expr_ty func, asdl_seq * args, asdl_seq * keywords, int
+                   lineno, int col_offset, PyArena *arena);
+#define Num(a0, a1, a2, a3) _Ta35_Num(a0, a1, a2, a3)
+expr_ty _Ta35_Num(object n, int lineno, int col_offset, PyArena *arena);
+#define Str(a0, a1, a2, a3) _Ta35_Str(a0, a1, a2, a3)
+expr_ty _Ta35_Str(string s, int lineno, int col_offset, PyArena *arena);
+#define Bytes(a0, a1, a2, a3) _Ta35_Bytes(a0, a1, a2, a3)
+expr_ty _Ta35_Bytes(bytes s, int lineno, int col_offset, PyArena *arena);
+#define NameConstant(a0, a1, a2, a3) _Ta35_NameConstant(a0, a1, a2, a3)
+expr_ty _Ta35_NameConstant(singleton value, int lineno, int col_offset, PyArena
+                           *arena);
+#define Ellipsis(a0, a1, a2) _Ta35_Ellipsis(a0, a1, a2)
+expr_ty _Ta35_Ellipsis(int lineno, int col_offset, PyArena *arena);
+#define Attribute(a0, a1, a2, a3, a4, a5) _Ta35_Attribute(a0, a1, a2, a3, a4, a5)
+expr_ty _Ta35_Attribute(expr_ty value, identifier attr, expr_context_ty ctx,
+                        int lineno, int col_offset, PyArena *arena);
+#define Subscript(a0, a1, a2, a3, a4, a5) _Ta35_Subscript(a0, a1, a2, a3, a4, a5)
+expr_ty _Ta35_Subscript(expr_ty value, slice_ty slice, expr_context_ty ctx, int
+                        lineno, int col_offset, PyArena *arena);
+#define Starred(a0, a1, a2, a3, a4) _Ta35_Starred(a0, a1, a2, a3, a4)
+expr_ty _Ta35_Starred(expr_ty value, expr_context_ty ctx, int lineno, int
+                      col_offset, PyArena *arena);
+#define Name(a0, a1, a2, a3, a4) _Ta35_Name(a0, a1, a2, a3, a4)
+expr_ty _Ta35_Name(identifier id, expr_context_ty ctx, int lineno, int
+                   col_offset, PyArena *arena);
+#define List(a0, a1, a2, a3, a4) _Ta35_List(a0, a1, a2, a3, a4)
+expr_ty _Ta35_List(asdl_seq * elts, expr_context_ty ctx, int lineno, int
+                   col_offset, PyArena *arena);
+#define Tuple(a0, a1, a2, a3, a4) _Ta35_Tuple(a0, a1, a2, a3, a4)
+expr_ty _Ta35_Tuple(asdl_seq * elts, expr_context_ty ctx, int lineno, int
+                    col_offset, PyArena *arena);
+#define Slice(a0, a1, a2, a3) _Ta35_Slice(a0, a1, a2, a3)
+slice_ty _Ta35_Slice(expr_ty lower, expr_ty upper, expr_ty step, PyArena
+                     *arena);
+#define ExtSlice(a0, a1) _Ta35_ExtSlice(a0, a1)
+slice_ty _Ta35_ExtSlice(asdl_seq * dims, PyArena *arena);
+#define Index(a0, a1) _Ta35_Index(a0, a1)
+slice_ty _Ta35_Index(expr_ty value, PyArena *arena);
+#define comprehension(a0, a1, a2, a3) _Ta35_comprehension(a0, a1, a2, a3)
+comprehension_ty _Ta35_comprehension(expr_ty target, expr_ty iter, asdl_seq *
+                                     ifs, PyArena *arena);
+#define ExceptHandler(a0, a1, a2, a3, a4, a5) _Ta35_ExceptHandler(a0, a1, a2, a3, a4, a5)
+excepthandler_ty _Ta35_ExceptHandler(expr_ty type, identifier name, asdl_seq *
+                                     body, int lineno, int col_offset, PyArena
+                                     *arena);
+#define arguments(a0, a1, a2, a3, a4, a5, a6) _Ta35_arguments(a0, a1, a2, a3, a4, a5, a6)
+arguments_ty _Ta35_arguments(asdl_seq * args, arg_ty vararg, asdl_seq *
+                             kwonlyargs, asdl_seq * kw_defaults, arg_ty kwarg,
+                             asdl_seq * defaults, PyArena *arena);
+#define arg(a0, a1, a2, a3, a4) _Ta35_arg(a0, a1, a2, a3, a4)
+arg_ty _Ta35_arg(identifier arg, expr_ty annotation, int lineno, int
+                 col_offset, PyArena *arena);
+#define keyword(a0, a1, a2) _Ta35_keyword(a0, a1, a2)
+keyword_ty _Ta35_keyword(identifier arg, expr_ty value, PyArena *arena);
+#define alias(a0, a1, a2) _Ta35_alias(a0, a1, a2)
+alias_ty _Ta35_alias(identifier name, identifier asname, PyArena *arena);
+#define withitem(a0, a1, a2) _Ta35_withitem(a0, a1, a2)
+withitem_ty _Ta35_withitem(expr_ty context_expr, expr_ty optional_vars, PyArena
+                           *arena);
+#define TypeIgnore(a0, a1) _Ta35_TypeIgnore(a0, a1)
+type_ignore_ty _Ta35_TypeIgnore(int lineno, PyArena *arena);
+
+PyObject* Ta35AST_mod2obj(mod_ty t);
+mod_ty Ta35AST_obj2mod(PyObject* ast, PyArena* arena, int mode);
+int Ta35AST_Check(PyObject* obj);
diff --git a/ast35/Include/asdl.h b/ast35/Include/asdl.h
new file mode 100644
index 0000000..d74d182
--- /dev/null
+++ b/ast35/Include/asdl.h
@@ -0,0 +1,50 @@
+#ifndef Ta35_ASDL_H
+#define Ta35_ASDL_H
+
+typedef PyObject * identifier;
+typedef PyObject * string;
+typedef PyObject * bytes;
+typedef PyObject * object;
+typedef PyObject * singleton;
+
+/* It would be nice if the code generated by asdl_c.py was completely
+   independent of Python, but it is a goal the requires too much work
+   at this stage.  So, for example, I'll represent identifiers as
+   interned Python strings.
+*/
+
+/* XXX A sequence should be typed so that its use can be typechecked. */
+
+typedef struct {
+    Py_ssize_t size;
+    void *elements[1];
+} asdl_seq;
+
+typedef struct {
+    Py_ssize_t size;
+    int elements[1];
+} asdl_int_seq;
+
+
+#if PY_MINOR_VERSION < 4
+#define _Py_asdl_seq_new asdl_seq_new
+#define _Py_asdl_int_seq_new asdl_int_seq_new
+#endif
+asdl_seq *_Py_asdl_seq_new(Py_ssize_t size, PyArena *arena);
+asdl_int_seq *_Py_asdl_int_seq_new(Py_ssize_t size, PyArena *arena);
+
+#define asdl_seq_GET(S, I) (S)->elements[(I)]
+#define asdl_seq_LEN(S) ((S) == NULL ? 0 : (S)->size)
+#ifdef Py_DEBUG
+#define asdl_seq_SET(S, I, V) \
+    do { \
+        Py_ssize_t _asdl_i = (I); \
+        assert((S) != NULL); \
+        assert(_asdl_i < (S)->size); \
+        (S)->elements[_asdl_i] = (V); \
+    } while (0)
+#else
+#define asdl_seq_SET(S, I, V) (S)->elements[I] = (V)
+#endif
+
+#endif /* !Ta35_ASDL_H */
diff --git a/ast35/Include/ast.h b/ast35/Include/ast.h
new file mode 100644
index 0000000..d9926d4
--- /dev/null
+++ b/ast35/Include/ast.h
@@ -0,0 +1,22 @@
+#ifndef Ta35_AST_H
+#define Ta35_AST_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+PyAPI_FUNC(int) Ta35AST_Validate(mod_ty);
+PyAPI_FUNC(mod_ty) Ta35AST_FromNode(
+    const node *n,
+    PyCompilerFlags *flags,
+    const char *filename,       /* decoded from the filesystem encoding */
+    PyArena *arena);
+PyAPI_FUNC(mod_ty) Ta35AST_FromNodeObject(
+    const node *n,
+    PyCompilerFlags *flags,
+    PyObject *filename,
+    PyArena *arena);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* !Ta35_AST_H */
diff --git a/ast35/Include/bitset.h b/ast35/Include/bitset.h
new file mode 100644
index 0000000..7a4c966
--- /dev/null
+++ b/ast35/Include/bitset.h
@@ -0,0 +1,32 @@
+
+#ifndef Ta35_BITSET_H
+#define Ta35_BITSET_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Bitset interface */
+
+#define BYTE		char
+
+typedef BYTE *bitset;
+
+bitset newbitset(int nbits);
+void delbitset(bitset bs);
+#define testbit(ss, ibit) (((ss)[BIT2BYTE(ibit)] & BIT2MASK(ibit)) != 0)
+int addbit(bitset bs, int ibit); /* Returns 0 if already set */
+int samebitset(bitset bs1, bitset bs2, int nbits);
+void mergebitset(bitset bs1, bitset bs2, int nbits);
+
+#define BITSPERBYTE	(8*sizeof(BYTE))
+#define NBYTES(nbits)	(((nbits) + BITSPERBYTE - 1) / BITSPERBYTE)
+
+#define BIT2BYTE(ibit)	((ibit) / BITSPERBYTE)
+#define BIT2SHIFT(ibit)	((ibit) % BITSPERBYTE)
+#define BIT2MASK(ibit)	(1 << BIT2SHIFT(ibit))
+#define BYTE2BIT(ibyte)	((ibyte) * BITSPERBYTE)
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* !Ta35_BITSET_H */
diff --git a/ast35/Include/compile.h b/ast35/Include/compile.h
new file mode 100644
index 0000000..88a9387
--- /dev/null
+++ b/ast35/Include/compile.h
@@ -0,0 +1,11 @@
+#ifndef Ta35_COMPILE_H
+#define Ta35_COMPILE_H
+
+/* These definitions must match corresponding definitions in graminit.h.
+   There's code in compile.c that checks that they are the same. */
+#define Py_single_input 256
+#define Py_file_input 257
+#define Py_eval_input 258
+#define Py_func_type_input 341
+
+#endif /* !Ta35_COMPILE_H */
diff --git a/ast35/Include/errcode.h b/ast35/Include/errcode.h
new file mode 100644
index 0000000..1b62b92
--- /dev/null
+++ b/ast35/Include/errcode.h
@@ -0,0 +1,38 @@
+#ifndef Ta35_ERRCODE_H
+#define Ta35_ERRCODE_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* Error codes passed around between file input, tokenizer, parser and
+   interpreter.  This is necessary so we can turn them into Python
+   exceptions at a higher level.  Note that some errors have a
+   slightly different meaning when passed from the tokenizer to the
+   parser than when passed from the parser to the interpreter; e.g.
+   the parser only returns E_EOF when it hits EOF immediately, and it
+   never returns E_OK. */
+
+#define E_OK		10	/* No error */
+#define E_EOF		11	/* End Of File */
+#define E_INTR		12	/* Interrupted */
+#define E_TOKEN		13	/* Bad token */
+#define E_SYNTAX	14	/* Syntax error */
+#define E_NOMEM		15	/* Ran out of memory */
+#define E_DONE		16	/* Parsing complete */
+#define E_ERROR		17	/* Execution error */
+#define E_TABSPACE	18	/* Inconsistent mixing of tabs and spaces */
+#define E_OVERFLOW      19	/* Node had too many children */
+#define E_TOODEEP	20	/* Too many indentation levels */
+#define E_DEDENT	21	/* No matching outer block for dedent */
+#define E_DECODE	22	/* Error in decoding into Unicode */
+#define E_EOFS		23	/* EOF in triple-quoted string */
+#define E_EOLS		24	/* EOL in single-quoted string */
+#define E_LINECONT	25	/* Unexpected characters after a line continuation */
+#define E_IDENTIFIER    26      /* Invalid characters in identifier */
+#define E_BADSINGLE	27	/* Ill-formed single statement input */
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* !Ta35_ERRCODE_H */
diff --git a/ast35/Include/graminit.h b/ast35/Include/graminit.h
new file mode 100644
index 0000000..69d0372
--- /dev/null
+++ b/ast35/Include/graminit.h
@@ -0,0 +1,90 @@
+/* Generated by Parser/pgen */
+
+#define single_input 256
+#define file_input 257
+#define eval_input 258
+#define decorator 259
+#define decorators 260
+#define decorated 261
+#define async_funcdef 262
+#define funcdef 263
+#define parameters 264
+#define typedargslist 265
+#define tfpdef 266
+#define varargslist 267
+#define vfpdef 268
+#define stmt 269
+#define simple_stmt 270
+#define small_stmt 271
+#define expr_stmt 272
+#define testlist_star_expr 273
+#define augassign 274
+#define del_stmt 275
+#define pass_stmt 276
+#define flow_stmt 277
+#define break_stmt 278
+#define continue_stmt 279
+#define return_stmt 280
+#define yield_stmt 281
+#define raise_stmt 282
+#define import_stmt 283
+#define import_name 284
+#define import_from 285
+#define import_as_name 286
+#define dotted_as_name 287
+#define import_as_names 288
+#define dotted_as_names 289
+#define dotted_name 290
+#define global_stmt 291
+#define nonlocal_stmt 292
+#define assert_stmt 293
+#define compound_stmt 294
+#define async_stmt 295
+#define if_stmt 296
+#define while_stmt 297
+#define for_stmt 298
+#define try_stmt 299
+#define with_stmt 300
+#define with_item 301
+#define except_clause 302
+#define suite 303
+#define test 304
+#define test_nocond 305
+#define lambdef 306
+#define lambdef_nocond 307
+#define or_test 308
+#define and_test 309
+#define not_test 310
+#define comparison 311
+#define comp_op 312
+#define star_expr 313
+#define expr 314
+#define xor_expr 315
+#define and_expr 316
+#define shift_expr 317
+#define arith_expr 318
+#define term 319
+#define factor 320
+#define power 321
+#define atom_expr 322
+#define atom 323
+#define testlist_comp 324
+#define trailer 325
+#define subscriptlist 326
+#define subscript 327
+#define sliceop 328
+#define exprlist 329
+#define testlist 330
+#define dictorsetmaker 331
+#define classdef 332
+#define arglist 333
+#define argument 334
+#define comp_iter 335
+#define comp_for 336
+#define comp_if 337
+#define encoding_decl 338
+#define yield_expr 339
+#define yield_arg 340
+#define func_type_input 341
+#define func_type 342
+#define typelist 343
diff --git a/ast35/Include/grammar.h b/ast35/Include/grammar.h
new file mode 100644
index 0000000..5f9b25d
--- /dev/null
+++ b/ast35/Include/grammar.h
@@ -0,0 +1,93 @@
+
+/* Grammar interface */
+
+#ifndef Ta35_GRAMMAR_H
+#define Ta35_GRAMMAR_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "bitset.h" /* Sigh... */
+
+/* A label of an arc */
+
+typedef struct {
+    int		 lb_type;
+    char	*lb_str;
+} label;
+
+#define EMPTY 0		/* Label number 0 is by definition the empty label */
+
+/* A list of labels */
+
+typedef struct {
+    int		 ll_nlabels;
+    label	*ll_label;
+} labellist;
+
+/* An arc from one state to another */
+
+typedef struct {
+    short	a_lbl;		/* Label of this arc */
+    short	a_arrow;	/* State where this arc goes to */
+} arc;
+
+/* A state in a DFA */
+
+typedef struct {
+    int		 s_narcs;
+    arc		*s_arc;		/* Array of arcs */
+
+    /* Optional accelerators */
+    int		 s_lower;	/* Lowest label index */
+    int		 s_upper;	/* Highest label index */
+    int		*s_accel;	/* Accelerator */
+    int		 s_accept;	/* Nonzero for accepting state */
+} state;
+
+/* A DFA */
+
+typedef struct {
+    int		 d_type;	/* Non-terminal this represents */
+    char	*d_name;	/* For printing */
+    int		 d_initial;	/* Initial state */
+    int		 d_nstates;
+    state	*d_state;	/* Array of states */
+    bitset	 d_first;
+} dfa;
+
+/* A grammar */
+
+typedef struct {
+    int		 g_ndfas;
+    dfa		*g_dfa;		/* Array of DFAs */
+    labellist	 g_ll;
+    int		 g_start;	/* Start symbol of the grammar */
+    int		 g_accel;	/* Set if accelerators present */
+} grammar;
+
+/* FUNCTIONS */
+
+grammar *newgrammar(int start);
+dfa *adddfa(grammar *g, int type, const char *name);
+int addstate(dfa *d);
+void addarc(dfa *d, int from, int to, int lbl);
+dfa *Ta35Grammar_FindDFA(grammar *g, int type);
+
+int addlabel(labellist *ll, int type, const char *str);
+int findlabel(labellist *ll, int type, const char *str);
+const char *Ta35Grammar_LabelRepr(label *lb);
+void translatelabels(grammar *g);
+
+void addfirstsets(grammar *g);
+
+void Ta35Grammar_AddAccelerators(grammar *g);
+void Ta35Grammar_RemoveAccelerators(grammar *);
+
+void printgrammar(grammar *g, FILE *fp);
+void printnonterminals(grammar *g, FILE *fp);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* !Ta35_GRAMMAR_H */
diff --git a/ast35/Include/node.h b/ast35/Include/node.h
new file mode 100644
index 0000000..82f23c3
--- /dev/null
+++ b/ast35/Include/node.h
@@ -0,0 +1,44 @@
+
+/* Parse tree node interface */
+
+#ifndef Ta35_NODE_H
+#define Ta35_NODE_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct _node {
+    short		n_type;
+    char		*n_str;
+    int			n_lineno;
+    int			n_col_offset;
+    int			n_nchildren;
+    struct _node	*n_child;
+} node;
+
+PyAPI_FUNC(node *) Ta35Node_New(int type);
+PyAPI_FUNC(int) Ta35Node_AddChild(node *n, int type,
+                                      char *str, int lineno, int col_offset);
+PyAPI_FUNC(void) Ta35Node_Free(node *n);
+#ifndef Py_LIMITED_API
+PyAPI_FUNC(Py_ssize_t) _Ta35Node_SizeOf(node *n);
+#endif
+
+/* Node access functions */
+#define NCH(n)		((n)->n_nchildren)
+
+#define CHILD(n, i)	(&(n)->n_child[i])
+#define RCHILD(n, i)	(CHILD(n, NCH(n) + i))
+#define TYPE(n)		((n)->n_type)
+#define STR(n)		((n)->n_str)
+#define LINENO(n)       ((n)->n_lineno)
+
+/* Assert that the type of a node is what we expect */
+#define REQ(n, type) assert(TYPE(n) == (type))
+
+PyAPI_FUNC(void) Ta35Node_ListTree(node *);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* !Ta35_NODE_H */
diff --git a/ast35/Include/parsetok.h b/ast35/Include/parsetok.h
new file mode 100644
index 0000000..cacc492
--- /dev/null
+++ b/ast35/Include/parsetok.h
@@ -0,0 +1,108 @@
+
+/* Parser-tokenizer link interface */
+#ifndef Py_LIMITED_API
+#ifndef Ta35_PARSETOK_H
+#define Ta35_PARSETOK_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct {
+    int error;
+#ifndef PGEN
+    /* The filename is useless for pgen, see comment in tok_state structure */
+    PyObject *filename;
+#endif
+    int lineno;
+    int offset;
+    char *text;                 /* UTF-8-encoded string */
+    int token;
+    int expected;
+} perrdetail;
+
+#if 0
+#define PyPARSE_YIELD_IS_KEYWORD	0x0001
+#endif
+
+#define PyPARSE_DONT_IMPLY_DEDENT	0x0002
+
+#if 0
+#define PyPARSE_WITH_IS_KEYWORD		0x0003
+#define PyPARSE_PRINT_IS_FUNCTION       0x0004
+#define PyPARSE_UNICODE_LITERALS        0x0008
+#endif
+
+#define PyPARSE_IGNORE_COOKIE 0x0010
+#define PyPARSE_BARRY_AS_BDFL 0x0020
+
+PyAPI_FUNC(node *) Ta35Parser_ParseString(const char *, grammar *, int,
+                                              perrdetail *);
+PyAPI_FUNC(node *) Ta35Parser_ParseFile (FILE *, const char *, grammar *, int,
+                                             const char *, const char *,
+                                             perrdetail *);
+
+PyAPI_FUNC(node *) Ta35Parser_ParseStringFlags(const char *, grammar *, int,
+                                              perrdetail *, int);
+PyAPI_FUNC(node *) Ta35Parser_ParseFileFlags(
+    FILE *fp,
+    const char *filename,       /* decoded from the filesystem encoding */
+    const char *enc,
+    grammar *g,
+    int start,
+    const char *ps1,
+    const char *ps2,
+    perrdetail *err_ret,
+    int flags);
+PyAPI_FUNC(node *) Ta35Parser_ParseFileFlagsEx(
+    FILE *fp,
+    const char *filename,       /* decoded from the filesystem encoding */
+    const char *enc,
+    grammar *g,
+    int start,
+    const char *ps1,
+    const char *ps2,
+    perrdetail *err_ret,
+    int *flags);
+PyAPI_FUNC(node *) Ta35Parser_ParseFileObject(
+    FILE *fp,
+    PyObject *filename,
+    const char *enc,
+    grammar *g,
+    int start,
+    const char *ps1,
+    const char *ps2,
+    perrdetail *err_ret,
+    int *flags);
+
+PyAPI_FUNC(node *) Ta35Parser_ParseStringFlagsFilename(
+    const char *s,
+    const char *filename,       /* decoded from the filesystem encoding */
+    grammar *g,
+    int start,
+    perrdetail *err_ret,
+    int flags);
+PyAPI_FUNC(node *) Ta35Parser_ParseStringFlagsFilenameEx(
+    const char *s,
+    const char *filename,       /* decoded from the filesystem encoding */
+    grammar *g,
+    int start,
+    perrdetail *err_ret,
+    int *flags);
+PyAPI_FUNC(node *) Ta35Parser_ParseStringObject(
+    const char *s,
+    PyObject *filename,
+    grammar *g,
+    int start,
+    perrdetail *err_ret,
+    int *flags);
+
+/* Note that the following functions are defined in pythonrun.c,
+   not in parsetok.c */
+PyAPI_FUNC(void) PyParser_SetError(perrdetail *);
+PyAPI_FUNC(void) PyParser_ClearError(perrdetail *);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* !Ta35_PARSETOK_H */
+#endif /* !Py_LIMITED_API */
diff --git a/ast35/Include/token.h b/ast35/Include/token.h
new file mode 100644
index 0000000..3a79705
--- /dev/null
+++ b/ast35/Include/token.h
@@ -0,0 +1,92 @@
+
+/* Token types */
+#ifndef Py_LIMITED_API
+#ifndef Ta35_TOKEN_H
+#define Ta35_TOKEN_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#undef TILDE   /* Prevent clash of our definition with system macro. Ex AIX, ioctl.h */
+
+#define ENDMARKER	0
+#define NAME		1
+#define NUMBER		2
+#define STRING		3
+#define NEWLINE		4
+#define INDENT		5
+#define DEDENT		6
+#define LPAR		7
+#define RPAR		8
+#define LSQB		9
+#define RSQB		10
+#define COLON		11
+#define COMMA		12
+#define SEMI		13
+#define PLUS		14
+#define MINUS		15
+#define STAR		16
+#define SLASH		17
+#define VBAR		18
+#define AMPER		19
+#define LESS		20
+#define GREATER		21
+#define EQUAL		22
+#define DOT		23
+#define PERCENT		24
+#define LBRACE		25
+#define RBRACE		26
+#define EQEQUAL		27
+#define NOTEQUAL	28
+#define LESSEQUAL	29
+#define GREATEREQUAL	30
+#define TILDE		31
+#define CIRCUMFLEX	32
+#define LEFTSHIFT	33
+#define RIGHTSHIFT	34
+#define DOUBLESTAR	35
+#define PLUSEQUAL	36
+#define MINEQUAL	37
+#define STAREQUAL	38
+#define SLASHEQUAL	39
+#define PERCENTEQUAL	40
+#define AMPEREQUAL	41
+#define VBAREQUAL	42
+#define CIRCUMFLEXEQUAL	43
+#define LEFTSHIFTEQUAL	44
+#define RIGHTSHIFTEQUAL	45
+#define DOUBLESTAREQUAL	46
+#define DOUBLESLASH	47
+#define DOUBLESLASHEQUAL 48
+#define AT              49
+#define ATEQUAL		50
+#define RARROW          51
+#define ELLIPSIS        52
+/* Don't forget to update the table _Ta35Parser_TokenNames in tokenizer.c! */
+#define OP		53
+#define AWAIT		54
+#define ASYNC		55
+#define TYPE_IGNORE	56
+#define TYPE_COMMENT	57
+#define ERRORTOKEN	58
+#define N_TOKENS	59
+
+/* Special definitions for cooperation with parser */
+
+#define NT_OFFSET		256
+
+#define ISTERMINAL(x)		((x) < NT_OFFSET)
+#define ISNONTERMINAL(x)	((x) >= NT_OFFSET)
+#define ISEOF(x)		((x) == ENDMARKER)
+
+
+PyAPI_DATA(const char *) _Ta35Parser_TokenNames[]; /* Token names */
+PyAPI_FUNC(int) Ta35Token_OneChar(int);
+PyAPI_FUNC(int) Ta35Token_TwoChars(int, int);
+PyAPI_FUNC(int) Ta35Token_ThreeChars(int, int, int);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* !Ta35_TOKEN_H */
+#endif /* Py_LIMITED_API */
diff --git a/ast35/Parser/Python.asdl b/ast35/Parser/Python.asdl
new file mode 100644
index 0000000..e493725
--- /dev/null
+++ b/ast35/Parser/Python.asdl
@@ -0,0 +1,126 @@
+-- ASDL's six builtin types are identifier, int, string, bytes, object, singleton
+
+module Python
+{
+    mod = Module(stmt* body, type_ignore *type_ignores)
+        | Interactive(stmt* body)
+        | Expression(expr body)
+        | FunctionType(expr* argtypes, expr returns)
+
+        -- not really an actual node but useful in Jython's typesystem.
+        | Suite(stmt* body)
+
+    stmt = FunctionDef(identifier name, arguments args,
+                       stmt* body, expr* decorator_list, expr? returns, string? type_comment)
+          | AsyncFunctionDef(identifier name, arguments args,
+                             stmt* body, expr* decorator_list, expr? returns, string? type_comment)
+
+          | ClassDef(identifier name,
+             expr* bases,
+             keyword* keywords,
+             stmt* body,
+             expr* decorator_list)
+          | Return(expr? value)
+
+          | Delete(expr* targets)
+          | Assign(expr* targets, expr value, string? type_comment)
+          | AugAssign(expr target, operator op, expr value)
+
+          -- use 'orelse' because else is a keyword in target languages
+          | For(expr target, expr iter, stmt* body, stmt* orelse, string? type_comment)
+          | AsyncFor(expr target, expr iter, stmt* body, stmt* orelse)
+          | While(expr test, stmt* body, stmt* orelse)
+          | If(expr test, stmt* body, stmt* orelse)
+          | With(withitem* items, stmt* body, string? type_comment)
+          | AsyncWith(withitem* items, stmt* body)
+
+          | Raise(expr? exc, expr? cause)
+          | Try(stmt* body, excepthandler* handlers, stmt* orelse, stmt* finalbody)
+          | Assert(expr test, expr? msg)
+
+          | Import(alias* names)
+          | ImportFrom(identifier? module, alias* names, int? level)
+
+          | Global(identifier* names)
+          | Nonlocal(identifier* names)
+          | Expr(expr value)
+          | Pass | Break | Continue
+
+          -- XXX Jython will be different
+          -- col_offset is the byte offset in the utf8 string the parser uses
+          attributes (int lineno, int col_offset)
+
+          -- BoolOp() can use left & right?
+    expr = BoolOp(boolop op, expr* values)
+         | BinOp(expr left, operator op, expr right)
+         | UnaryOp(unaryop op, expr operand)
+         | Lambda(arguments args, expr body)
+         | IfExp(expr test, expr body, expr orelse)
+         | Dict(expr* keys, expr* values)
+         | Set(expr* elts)
+         | ListComp(expr elt, comprehension* generators)
+         | SetComp(expr elt, comprehension* generators)
+         | DictComp(expr key, expr value, comprehension* generators)
+         | GeneratorExp(expr elt, comprehension* generators)
+         -- the grammar constrains where yield expressions can occur
+         | Await(expr value)
+         | Yield(expr? value)
+         | YieldFrom(expr value)
+         -- need sequences for compare to distinguish between
+         -- x < 4 < 3 and (x < 4) < 3
+         | Compare(expr left, cmpop* ops, expr* comparators)
+         | Call(expr func, expr* args, keyword* keywords)
+         | Num(object n) -- a number as a PyObject.
+         | Str(string s) -- need to specify raw, unicode, etc?
+         | Bytes(bytes s)
+         | NameConstant(singleton value)
+         | Ellipsis
+
+         -- the following expression can appear in assignment context
+         | Attribute(expr value, identifier attr, expr_context ctx)
+         | Subscript(expr value, slice slice, expr_context ctx)
+         | Starred(expr value, expr_context ctx)
+         | Name(identifier id, expr_context ctx)
+         | List(expr* elts, expr_context ctx)
+         | Tuple(expr* elts, expr_context ctx)
+
+          -- col_offset is the byte offset in the utf8 string the parser uses
+          attributes (int lineno, int col_offset)
+
+    expr_context = Load | Store | Del | AugLoad | AugStore | Param
+
+    slice = Slice(expr? lower, expr? upper, expr? step)
+          | ExtSlice(slice* dims)
+          | Index(expr value)
+
+    boolop = And | Or
+
+    operator = Add | Sub | Mult | MatMult | Div | Mod | Pow | LShift
+                 | RShift | BitOr | BitXor | BitAnd | FloorDiv
+
+    unaryop = Invert | Not | UAdd | USub
+
+    cmpop = Eq | NotEq | Lt | LtE | Gt | GtE | Is | IsNot | In | NotIn
+
+    comprehension = (expr target, expr iter, expr* ifs)
+
+    excepthandler = ExceptHandler(expr? type, identifier? name, stmt* body)
+                    attributes (int lineno, int col_offset)
+
+    arguments = (arg* args, arg? vararg, arg* kwonlyargs, expr* kw_defaults,
+                 arg? kwarg, expr* defaults)
+
+    arg = (identifier arg, expr? annotation)
+           attributes (int lineno, int col_offset)
+
+    -- keyword arguments supplied to call (NULL identifier for **kwargs)
+    keyword = (identifier? arg, expr value)
+
+    -- import name with optional 'as' alias.
+    alias = (identifier name, identifier? asname)
+
+    withitem = (expr context_expr, expr? optional_vars)
+
+    type_ignore = TypeIgnore(int lineno)
+}
+
diff --git a/ast35/Parser/acceler.c b/ast35/Parser/acceler.c
new file mode 100644
index 0000000..15b6fab
--- /dev/null
+++ b/ast35/Parser/acceler.c
@@ -0,0 +1,125 @@
+
+/* Parser accelerator module */
+
+/* The parser as originally conceived had disappointing performance.
+   This module does some precomputation that speeds up the selection
+   of a DFA based upon a token, turning a search through an array
+   into a simple indexing operation.  The parser now cannot work
+   without the accelerators installed.  Note that the accelerators
+   are installed dynamically when the parser is initialized, they
+   are not part of the static data structure written on graminit.[ch]
+   by the parser generator. */
+
+#include "pgenheaders.h"
+#include "grammar.h"
+#include "node.h"
+#include "token.h"
+#include "parser.h"
+
+/* Forward references */
+static void fixdfa(grammar *, dfa *);
+static void fixstate(grammar *, state *);
+
+void
+Ta35Grammar_AddAccelerators(grammar *g)
+{
+    dfa *d;
+    int i;
+    d = g->g_dfa;
+    for (i = g->g_ndfas; --i >= 0; d++)
+        fixdfa(g, d);
+    g->g_accel = 1;
+}
+
+void
+Ta35Grammar_RemoveAccelerators(grammar *g)
+{
+    dfa *d;
+    int i;
+    g->g_accel = 0;
+    d = g->g_dfa;
+    for (i = g->g_ndfas; --i >= 0; d++) {
+        state *s;
+        int j;
+        s = d->d_state;
+        for (j = 0; j < d->d_nstates; j++, s++) {
+            if (s->s_accel)
+                PyObject_FREE(s->s_accel);
+            s->s_accel = NULL;
+        }
+    }
+}
+
+static void
+fixdfa(grammar *g, dfa *d)
+{
+    state *s;
+    int j;
+    s = d->d_state;
+    for (j = 0; j < d->d_nstates; j++, s++)
+        fixstate(g, s);
+}
+
+static void
+fixstate(grammar *g, state *s)
+{
+    arc *a;
+    int k;
+    int *accel;
+    int nl = g->g_ll.ll_nlabels;
+    s->s_accept = 0;
+    accel = (int *) PyObject_MALLOC(nl * sizeof(int));
+    if (accel == NULL) {
+        fprintf(stderr, "no mem to build parser accelerators\n");
+        exit(1);
+    }
+    for (k = 0; k < nl; k++)
+        accel[k] = -1;
+    a = s->s_arc;
+    for (k = s->s_narcs; --k >= 0; a++) {
+        int lbl = a->a_lbl;
+        label *l = &g->g_ll.ll_label[lbl];
+        int type = l->lb_type;
+        if (a->a_arrow >= (1 << 7)) {
+            printf("XXX too many states!\n");
+            continue;
+        }
+        if (ISNONTERMINAL(type)) {
+            dfa *d1 = Ta35Grammar_FindDFA(g, type);
+            int ibit;
+            if (type - NT_OFFSET >= (1 << 7)) {
+                printf("XXX too high nonterminal number!\n");
+                continue;
+            }
+            for (ibit = 0; ibit < g->g_ll.ll_nlabels; ibit++) {
+                if (testbit(d1->d_first, ibit)) {
+                    if (accel[ibit] != -1)
+                        printf("XXX ambiguity!\n");
+                    accel[ibit] = a->a_arrow | (1 << 7) |
+                        ((type - NT_OFFSET) << 8);
+                }
+            }
+        }
+        else if (lbl == EMPTY)
+            s->s_accept = 1;
+        else if (lbl >= 0 && lbl < nl)
+            accel[lbl] = a->a_arrow;
+    }
+    while (nl > 0 && accel[nl-1] == -1)
+        nl--;
+    for (k = 0; k < nl && accel[k] == -1;)
+        k++;
+    if (k < nl) {
+        int i;
+        s->s_accel = (int *) PyObject_MALLOC((nl-k) * sizeof(int));
+        if (s->s_accel == NULL) {
+            fprintf(stderr, "no mem to add parser accelerators\n");
+            exit(1);
+        }
+        s->s_lower = k;
+        s->s_upper = nl;
+        for (i = 0; k < nl; i++, k++)
+            s->s_accel[i] = accel[k];
+    }
+    PyObject_FREE(accel);
+}
diff --git a/ast35/Parser/asdl.py b/ast35/Parser/asdl.py
new file mode 100644
index 0000000..121cdab
--- /dev/null
+++ b/ast35/Parser/asdl.py
@@ -0,0 +1,375 @@
+#-------------------------------------------------------------------------------
+# Parser for ASDL [1] definition files. Reads in an ASDL description and parses
+# it into an AST that describes it.
+#
+# The EBNF we're parsing here: Figure 1 of the paper [1]. Extended to support
+# modules and attributes after a product. Words starting with Capital letters
+# are terminals. Literal tokens are in "double quotes". Others are
+# non-terminals. Id is either TokenId or ConstructorId.
+#
+# module        ::= "module" Id "{" [definitions] "}"
+# definitions   ::= { TypeId "=" type }
+# type          ::= product | sum
+# product       ::= fields ["attributes" fields]
+# fields        ::= "(" { field, "," } field ")"
+# field         ::= TypeId ["?" | "*"] [Id]
+# sum           ::= constructor { "|" constructor } ["attributes" fields]
+# constructor   ::= ConstructorId [fields]
+#
+# [1] "The Zephyr Abstract Syntax Description Language" by Wang, et. al. See
+#     http://asdl.sourceforge.net/
+#-------------------------------------------------------------------------------
+from collections import namedtuple
+import re
+
+__all__ = [
+    'builtin_types', 'parse', 'AST', 'Module', 'Type', 'Constructor',
+    'Field', 'Sum', 'Product', 'VisitorBase', 'Check', 'check']
+
+# The following classes define nodes into which the ASDL description is parsed.
+# Note: this is a "meta-AST". ASDL files (such as Python.asdl) describe the AST
+# structure used by a programming language. But ASDL files themselves need to be
+# parsed. This module parses ASDL files and uses a simple AST to represent them.
+# See the EBNF at the top of the file to understand the logical connection
+# between the various node types.
+
+builtin_types = {'identifier', 'string', 'bytes', 'int', 'object', 'singleton'}
+
+class AST:
+    def __repr__(self):
+        raise NotImplementedError
+
+class Module(AST):
+    def __init__(self, name, dfns):
+        self.name = name
+        self.dfns = dfns
+        self.types = {type.name: type.value for type in dfns}
+
+    def __repr__(self):
+        return 'Module({0.name}, {0.dfns})'.format(self)
+
+class Type(AST):
+    def __init__(self, name, value):
+        self.name = name
+        self.value = value
+
+    def __repr__(self):
+        return 'Type({0.name}, {0.value})'.format(self)
+
+class Constructor(AST):
+    def __init__(self, name, fields=None):
+        self.name = name
+        self.fields = fields or []
+
+    def __repr__(self):
+        return 'Constructor({0.name}, {0.fields})'.format(self)
+
+class Field(AST):
+    def __init__(self, type, name=None, seq=False, opt=False):
+        self.type = type
+        self.name = name
+        self.seq = seq
+        self.opt = opt
+
+    def __repr__(self):
+        if self.seq:
+            extra = ", seq=True"
+        elif self.opt:
+            extra = ", opt=True"
+        else:
+            extra = ""
+        if self.name is None:
+            return 'Field({0.type}{1})'.format(self, extra)
+        else:
+            return 'Field({0.type}, {0.name}{1})'.format(self, extra)
+
+class Sum(AST):
+    def __init__(self, types, attributes=None):
+        self.types = types
+        self.attributes = attributes or []
+
+    def __repr__(self):
+        if self.attributes:
+            return 'Sum({0.types}, {0.attributes})'.format(self)
+        else:
+            return 'Sum({0.types})'.format(self)
+
+class Product(AST):
+    def __init__(self, fields, attributes=None):
+        self.fields = fields
+        self.attributes = attributes or []
+
+    def __repr__(self):
+        if self.attributes:
+            return 'Product({0.fields}, {0.attributes})'.format(self)
+        else:
+            return 'Product({0.fields})'.format(self)
+
+# A generic visitor for the meta-AST that describes ASDL. This can be used by
+# emitters. Note that this visitor does not provide a generic visit method, so a
+# subclass needs to define visit methods from visitModule to as deep as the
+# interesting node.
+# We also define a Check visitor that makes sure the parsed ASDL is well-formed.
+
+class VisitorBase(object):
+    """Generic tree visitor for ASTs."""
+    def __init__(self):
+        self.cache = {}
+
+    def visit(self, obj, *args):
+        klass = obj.__class__
+        meth = self.cache.get(klass)
+        if meth is None:
+            methname = "visit" + klass.__name__
+            meth = getattr(self, methname, None)
+            self.cache[klass] = meth
+        if meth:
+            try:
+                meth(obj, *args)
+            except Exception as e:
+                print("Error visiting %r: %s" % (obj, e))
+                raise
+
+class Check(VisitorBase):
+    """A visitor that checks a parsed ASDL tree for correctness.
+
+    Errors are printed and accumulated.
+    """
+    def __init__(self):
+        super(Check, self).__init__()
+        self.cons = {}
+        self.errors = 0
+        self.types = {}
+
+    def visitModule(self, mod):
+        for dfn in mod.dfns:
+            self.visit(dfn)
+
+    def visitType(self, type):
+        self.visit(type.value, str(type.name))
+
+    def visitSum(self, sum, name):
+        for t in sum.types:
+            self.visit(t, name)
+
+    def visitConstructor(self, cons, name):
+        key = str(cons.name)
+        conflict = self.cons.get(key)
+        if conflict is None:
+            self.cons[key] = name
+        else:
+            print('Redefinition of constructor {}'.format(key))
+            print('Defined in {} and {}'.format(conflict, name))
+            self.errors += 1
+        for f in cons.fields:
+            self.visit(f, key)
+
+    def visitField(self, field, name):
+        key = str(field.type)
+        l = self.types.setdefault(key, [])
+        l.append(name)
+
+    def visitProduct(self, prod, name):
+        for f in prod.fields:
+            self.visit(f, name)
+
+def check(mod):
+    """Check the parsed ASDL tree for correctness.
+
+    Return True if success. For failure, the errors are printed out and False
+    is returned.
+    """
+    v = Check()
+    v.visit(mod)
+
+    for t in v.types:
+        if t not in mod.types and not t in builtin_types:
+            v.errors += 1
+            uses = ", ".join(v.types[t])
+            print('Undefined type {}, used in {}'.format(t, uses))
+    return not v.errors
+
+# The ASDL parser itself comes next. The only interesting external interface
+# here is the top-level parse function.
+
+def parse(filename):
+    """Parse ASDL from the given file and return a Module node describing it."""
+    with open(filename) as f:
+        parser = ASDLParser()
+        return parser.parse(f.read())
+
+# Types for describing tokens in an ASDL specification.
+class TokenKind:
+    """TokenKind is provides a scope for enumerated token kinds."""
+    (ConstructorId, TypeId, Equals, Comma, Question, Pipe, Asterisk,
+     LParen, RParen, LBrace, RBrace) = range(11)
+
+    operator_table = {
+        '=': Equals, ',': Comma,    '?': Question, '|': Pipe,    '(': LParen,
+        ')': RParen, '*': Asterisk, '{': LBrace,   '}': RBrace}
+
+Token = namedtuple('Token', 'kind value lineno')
+
+class ASDLSyntaxError(Exception):
+    def __init__(self, msg, lineno=None):
+        self.msg = msg
+        self.lineno = lineno or '<unknown>'
+
+    def __str__(self):
+        return 'Syntax error on line {0.lineno}: {0.msg}'.format(self)
+
+def tokenize_asdl(buf):
+    """Tokenize the given buffer. Yield Token objects."""
+    for lineno, line in enumerate(buf.splitlines(), 1):
+        for m in re.finditer(r'\s*(\w+|--.*|.)', line.strip()):
+            c = m.group(1)
+            if c[0].isalpha():
+                # Some kind of identifier
+                if c[0].isupper():
+                    yield Token(TokenKind.ConstructorId, c, lineno)
+                else:
+                    yield Token(TokenKind.TypeId, c, lineno)
+            elif c[:2] == '--':
+                # Comment
+                break
+            else:
+                # Operators
+                try:
+                    op_kind = TokenKind.operator_table[c]
+                except KeyError:
+                    raise ASDLSyntaxError('Invalid operator %s' % c, lineno)
+                yield Token(op_kind, c, lineno)
+
+class ASDLParser:
+    """Parser for ASDL files.
+
+    Create, then call the parse method on a buffer containing ASDL.
+    This is a simple recursive descent parser that uses tokenize_asdl for the
+    lexing.
+    """
+    def __init__(self):
+        self._tokenizer = None
+        self.cur_token = None
+
+    def parse(self, buf):
+        """Parse the ASDL in the buffer and return an AST with a Module root.
+        """
+        self._tokenizer = tokenize_asdl(buf)
+        self._advance()
+        return self._parse_module()
+
+    def _parse_module(self):
+        if self._at_keyword('module'):
+            self._advance()
+        else:
+            raise ASDLSyntaxError(
+                'Expected "module" (found {})'.format(self.cur_token.value),
+                self.cur_token.lineno)
+        name = self._match(self._id_kinds)
+        self._match(TokenKind.LBrace)
+        defs = self._parse_definitions()
+        self._match(TokenKind.RBrace)
+        return Module(name, defs)
+
+    def _parse_definitions(self):
+        defs = []
+        while self.cur_token.kind == TokenKind.TypeId:
+            typename = self._advance()
+            self._match(TokenKind.Equals)
+            type = self._parse_type()
+            defs.append(Type(typename, type))
+        return defs
+
+    def _parse_type(self):
+        if self.cur_token.kind == TokenKind.LParen:
+            # If we see a (, it's a product
+            return self._parse_product()
+        else:
+            # Otherwise it's a sum. Look for ConstructorId
+            sumlist = [Constructor(self._match(TokenKind.ConstructorId),
+                                   self._parse_optional_fields())]
+            while self.cur_token.kind  == TokenKind.Pipe:
+                # More constructors
+                self._advance()
+                sumlist.append(Constructor(
+                                self._match(TokenKind.ConstructorId),
+                                self._parse_optional_fields()))
+            return Sum(sumlist, self._parse_optional_attributes())
+
+    def _parse_product(self):
+        return Product(self._parse_fields(), self._parse_optional_attributes())
+
+    def _parse_fields(self):
+        fields = []
+        self._match(TokenKind.LParen)
+        while self.cur_token.kind == TokenKind.TypeId:
+            typename = self._advance()
+            is_seq, is_opt = self._parse_optional_field_quantifier()
+            id = (self._advance() if self.cur_token.kind in self._id_kinds
+                                  else None)
+            fields.append(Field(typename, id, seq=is_seq, opt=is_opt))
+            if self.cur_token.kind == TokenKind.RParen:
+                break
+            elif self.cur_token.kind == TokenKind.Comma:
+                self._advance()
+        self._match(TokenKind.RParen)
+        return fields
+
+    def _parse_optional_fields(self):
+        if self.cur_token.kind == TokenKind.LParen:
+            return self._parse_fields()
+        else:
+            return None
+
+    def _parse_optional_attributes(self):
+        if self._at_keyword('attributes'):
+            self._advance()
+            return self._parse_fields()
+        else:
+            return None
+
+    def _parse_optional_field_quantifier(self):
+        is_seq, is_opt = False, False
+        if self.cur_token.kind == TokenKind.Asterisk:
+            is_seq = True
+            self._advance()
+        elif self.cur_token.kind == TokenKind.Question:
+            is_opt = True
+            self._advance()
+        return is_seq, is_opt
+
+    def _advance(self):
+        """ Return the value of the current token and read the next one into
+            self.cur_token.
+        """
+        cur_val = None if self.cur_token is None else self.cur_token.value
+        try:
+            self.cur_token = next(self._tokenizer)
+        except StopIteration:
+            self.cur_token = None
+        return cur_val
+
+    _id_kinds = (TokenKind.ConstructorId, TokenKind.TypeId)
+
+    def _match(self, kind):
+        """The 'match' primitive of RD parsers.
+
+        * Verifies that the current token is of the given kind (kind can
+          be a tuple, in which the kind must match one of its members).
+        * Returns the value of the current token
+        * Reads in the next token
+        """
+        if (isinstance(kind, tuple) and self.cur_token.kind in kind or
+            self.cur_token.kind == kind
+            ):
+            value = self.cur_token.value
+            self._advance()
+            return value
+        else:
+            raise ASDLSyntaxError(
+                'Unmatched {} (found {})'.format(kind, self.cur_token.kind),
+                self.cur_token.lineno)
+
+    def _at_keyword(self, keyword):
+        return (self.cur_token.kind == TokenKind.TypeId and
+                self.cur_token.value == keyword)
diff --git a/ast35/Parser/asdl_c.py b/ast35/Parser/asdl_c.py
new file mode 100755
index 0000000..cabc241
--- /dev/null
+++ b/ast35/Parser/asdl_c.py
@@ -0,0 +1,1326 @@
+#! /usr/bin/env python
+"""Generate C code from an ASDL description."""
+
+import os, sys
+
+import asdl
+
+TABSIZE = 4
+MAX_COL = 80
+
+def get_c_type(name):
+    """Return a string for the C name of the type.
+
+    This function special cases the default types provided by asdl.
+    """
+    if name in asdl.builtin_types:
+        return name
+    else:
+        return "%s_ty" % name
+
+def reflow_lines(s, depth):
+    """Reflow the line s indented depth tabs.
+
+    Return a sequence of lines where no line extends beyond MAX_COL
+    when properly indented.  The first line is properly indented based
+    exclusively on depth * TABSIZE.  All following lines -- these are
+    the reflowed lines generated by this function -- start at the same
+    column as the first character beyond the opening { in the first
+    line.
+    """
+    size = MAX_COL - depth * TABSIZE
+    if len(s) < size:
+        return [s]
+
+    lines = []
+    cur = s
+    padding = ""
+    while len(cur) > size:
+        i = cur.rfind(' ', 0, size)
+        # XXX this should be fixed for real
+        if i == -1 and 'GeneratorExp' in cur:
+            i = size + 3
+        assert i != -1, "Impossible line %d to reflow: %r" % (size, s)
+        lines.append(padding + cur[:i])
+        if len(lines) == 1:
+            # find new size based on brace
+            j = cur.find('{', 0, i)
+            if j >= 0:
+                j += 2 # account for the brace and the space after it
+                size -= j
+                padding = " " * j
+            else:
+                j = cur.find('(', 0, i)
+                if j >= 0:
+                    j += 1 # account for the paren (no space after it)
+                    size -= j
+                    padding = " " * j
+        cur = cur[i+1:]
+    else:
+        lines.append(padding + cur)
+    return lines
+
+def is_simple(sum):
+    """Return True if a sum is a simple.
+
+    A sum is simple if its types have no fields, e.g.
+    unaryop = Invert | Not | UAdd | USub
+    """
+    for t in sum.types:
+        if t.fields:
+            return False
+    return True
+
+
+class EmitVisitor(asdl.VisitorBase):
+    """Visit that emits lines"""
+
+    def __init__(self, file):
+        self.file = file
+        self.identifiers = set()
+        super(EmitVisitor, self).__init__()
+
+    def emit_identifier(self, name):
+        name = str(name)
+        if name in self.identifiers:
+            return
+        self.emit("_Py_IDENTIFIER(%s);" % name, 0)
+        self.identifiers.add(name)
+
+    def emit(self, s, depth, reflow=True):
+        # XXX reflow long lines?
+        if reflow:
+            lines = reflow_lines(s, depth)
+        else:
+            lines = [s]
+        for line in lines:
+            line = (" " * TABSIZE * depth) + line + "\n"
+            self.file.write(line)
+
+
+class TypeDefVisitor(EmitVisitor):
+    def visitModule(self, mod):
+        for dfn in mod.dfns:
+            self.visit(dfn)
+
+    def visitType(self, type, depth=0):
+        self.visit(type.value, type.name, depth)
+
+    def visitSum(self, sum, name, depth):
+        if is_simple(sum):
+            self.simple_sum(sum, name, depth)
+        else:
+            self.sum_with_constructors(sum, name, depth)
+
+    def simple_sum(self, sum, name, depth):
+        enum = []
+        for i in range(len(sum.types)):
+            type = sum.types[i]
+            enum.append("%s=%d" % (type.name, i + 1))
+        enums = ", ".join(enum)
+        ctype = get_c_type(name)
+        s = "typedef enum _%s { %s } %s;" % (name, enums, ctype)
+        self.emit(s, depth)
+        self.emit("", depth)
+
+    def sum_with_constructors(self, sum, name, depth):
+        ctype = get_c_type(name)
+        s = "typedef struct _%(name)s *%(ctype)s;" % locals()
+        self.emit(s, depth)
+        self.emit("", depth)
+
+    def visitProduct(self, product, name, depth):
+        ctype = get_c_type(name)
+        s = "typedef struct _%(name)s *%(ctype)s;" % locals()
+        self.emit(s, depth)
+        self.emit("", depth)
+
+
+class StructVisitor(EmitVisitor):
+    """Visitor to generate typedefs for AST."""
+
+    def visitModule(self, mod):
+        for dfn in mod.dfns:
+            self.visit(dfn)
+
+    def visitType(self, type, depth=0):
+        self.visit(type.value, type.name, depth)
+
+    def visitSum(self, sum, name, depth):
+        if not is_simple(sum):
+            self.sum_with_constructors(sum, name, depth)
+
+    def sum_with_constructors(self, sum, name, depth):
+        def emit(s, depth=depth):
+            self.emit(s % sys._getframe(1).f_locals, depth)
+        enum = []
+        for i in range(len(sum.types)):
+            type = sum.types[i]
+            enum.append("%s_kind=%d" % (type.name, i + 1))
+
+        emit("enum _%(name)s_kind {" + ", ".join(enum) + "};")
+
+        emit("struct _%(name)s {")
+        emit("enum _%(name)s_kind kind;", depth + 1)
+        emit("union {", depth + 1)
+        for t in sum.types:
+            self.visit(t, depth + 2)
+        emit("} v;", depth + 1)
+        for field in sum.attributes:
+            # rudimentary attribute handling
+            type = str(field.type)
+            assert type in asdl.builtin_types, type
+            emit("%s %s;" % (type, field.name), depth + 1);
+        emit("};")
+        emit("")
+
+    def visitConstructor(self, cons, depth):
+        if cons.fields:
+            self.emit("struct {", depth)
+            for f in cons.fields:
+                self.visit(f, depth + 1)
+            self.emit("} %s;" % cons.name, depth)
+            self.emit("", depth)
+
+    def visitField(self, field, depth):
+        # XXX need to lookup field.type, because it might be something
+        # like a builtin...
+        ctype = get_c_type(field.type)
+        name = field.name
+        if field.seq:
+            if field.type == 'cmpop':
+                self.emit("asdl_int_seq *%(name)s;" % locals(), depth)
+            else:
+                self.emit("asdl_seq *%(name)s;" % locals(), depth)
+        else:
+            self.emit("%(ctype)s %(name)s;" % locals(), depth)
+
+    def visitProduct(self, product, name, depth):
+        self.emit("struct _%(name)s {" % locals(), depth)
+        for f in product.fields:
+            self.visit(f, depth + 1)
+        for field in product.attributes:
+            # rudimentary attribute handling
+            type = str(field.type)
+            assert type in asdl.builtin_types, type
+            self.emit("%s %s;" % (type, field.name), depth + 1);
+        self.emit("};", depth)
+        self.emit("", depth)
+
+
+class PrototypeVisitor(EmitVisitor):
+    """Generate function prototypes for the .h file"""
+
+    def visitModule(self, mod):
+        for dfn in mod.dfns:
+            self.visit(dfn)
+
+    def visitType(self, type):
+        self.visit(type.value, type.name)
+
+    def visitSum(self, sum, name):
+        if is_simple(sum):
+            pass # XXX
+        else:
+            for t in sum.types:
+                self.visit(t, name, sum.attributes)
+
+    def get_args(self, fields):
+        """Return list of C argument into, one for each field.
+
+        Argument info is 3-tuple of a C type, variable name, and flag
+        that is true if type can be NULL.
+        """
+        args = []
+        unnamed = {}
+        for f in fields:
+            if f.name is None:
+                name = f.type
+                c = unnamed[name] = unnamed.get(name, 0) + 1
+                if c > 1:
+                    name = "name%d" % (c - 1)
+            else:
+                name = f.name
+            # XXX should extend get_c_type() to handle this
+            if f.seq:
+                if f.type == 'cmpop':
+                    ctype = "asdl_int_seq *"
+                else:
+                    ctype = "asdl_seq *"
+            else:
+                ctype = get_c_type(f.type)
+            args.append((ctype, name, f.opt or f.seq))
+        return args
+
+    def visitConstructor(self, cons, type, attrs):
+        args = self.get_args(cons.fields)
+        attrs = self.get_args(attrs)
+        ctype = get_c_type(type)
+        self.emit_function(cons.name, ctype, args, attrs)
+
+    def emit_function(self, name, ctype, args, attrs, union=True):
+        args = args + attrs
+        if args:
+            argstr = ", ".join(["%s %s" % (atype, aname)
+                                for atype, aname, opt in args])
+            argstr += ", PyArena *arena"
+        else:
+            argstr = "PyArena *arena"
+        margs = "a0"
+        for i in range(1, len(args)+1):
+            margs += ", a%d" % i
+        self.emit("#define %s(%s) _Ta35_%s(%s)" % (name, margs, name, margs), 0,
+                reflow=False)
+        self.emit("%s _Ta35_%s(%s);" % (ctype, name, argstr), False)
+
+    def visitProduct(self, prod, name):
+        self.emit_function(name, get_c_type(name),
+                           self.get_args(prod.fields),
+                           self.get_args(prod.attributes),
+                           union=False)
+
+
+class FunctionVisitor(PrototypeVisitor):
+    """Visitor to generate constructor functions for AST."""
+
+    def emit_function(self, name, ctype, args, attrs, union=True):
+        def emit(s, depth=0, reflow=True):
+            self.emit(s, depth, reflow)
+        argstr = ", ".join(["%s %s" % (atype, aname)
+                            for atype, aname, opt in args + attrs])
+        if argstr:
+            argstr += ", PyArena *arena"
+        else:
+            argstr = "PyArena *arena"
+        self.emit("%s" % ctype, 0)
+        emit("%s(%s)" % (name, argstr))
+        emit("{")
+        emit("%s p;" % ctype, 1)
+        for argtype, argname, opt in args:
+            if not opt and argtype != "int":
+                emit("if (!%s) {" % argname, 1)
+                emit("PyErr_SetString(PyExc_ValueError,", 2)
+                msg = "field %s is required for %s" % (argname, name)
+                emit('                "%s");' % msg,
+                     2, reflow=False)
+                emit('return NULL;', 2)
+                emit('}', 1)
+
+        emit("p = (%s)PyArena_Malloc(arena, sizeof(*p));" % ctype, 1);
+        emit("if (!p)", 1)
+        emit("return NULL;", 2)
+        if union:
+            self.emit_body_union(name, args, attrs)
+        else:
+            self.emit_body_struct(name, args, attrs)
+        emit("return p;", 1)
+        emit("}")
+        emit("")
+
+    def emit_body_union(self, name, args, attrs):
+        def emit(s, depth=0, reflow=True):
+            self.emit(s, depth, reflow)
+        emit("p->kind = %s_kind;" % name, 1)
+        for argtype, argname, opt in args:
+            emit("p->v.%s.%s = %s;" % (name, argname, argname), 1)
+        for argtype, argname, opt in attrs:
+            emit("p->%s = %s;" % (argname, argname), 1)
+
+    def emit_body_struct(self, name, args, attrs):
+        def emit(s, depth=0, reflow=True):
+            self.emit(s, depth, reflow)
+        for argtype, argname, opt in args:
+            emit("p->%s = %s;" % (argname, argname), 1)
+        for argtype, argname, opt in attrs:
+            emit("p->%s = %s;" % (argname, argname), 1)
+
+
+class PickleVisitor(EmitVisitor):
+
+    def visitModule(self, mod):
+        for dfn in mod.dfns:
+            self.visit(dfn)
+
+    def visitType(self, type):
+        self.visit(type.value, type.name)
+
+    def visitSum(self, sum, name):
+        pass
+
+    def visitProduct(self, sum, name):
+        pass
+
+    def visitConstructor(self, cons, name):
+        pass
+
+    def visitField(self, sum):
+        pass
+
+
+class Obj2ModPrototypeVisitor(PickleVisitor):
+    def visitProduct(self, prod, name):
+        code = "static int obj2ast_%s(PyObject* obj, %s* out, PyArena* arena);"
+        self.emit(code % (name, get_c_type(name)), 0)
+
+    visitSum = visitProduct
+
+
+class Obj2ModVisitor(PickleVisitor):
+    def funcHeader(self, name):
+        ctype = get_c_type(name)
+        self.emit("int", 0)
+        self.emit("obj2ast_%s(PyObject* obj, %s* out, PyArena* arena)" % (name, ctype), 0)
+        self.emit("{", 0)
+        self.emit("int isinstance;", 1)
+        self.emit("", 0)
+
+    def sumTrailer(self, name, add_label=False):
+        self.emit("", 0)
+        # there's really nothing more we can do if this fails ...
+        error = "expected some sort of %s, but got %%R" % name
+        format = "PyErr_Format(PyExc_TypeError, \"%s\", obj);"
+        self.emit(format % error, 1, reflow=False)
+        if add_label:
+            self.emit("failed:", 1)
+            self.emit("Py_XDECREF(tmp);", 1)
+        self.emit("return 1;", 1)
+        self.emit("}", 0)
+        self.emit("", 0)
+
+    def simpleSum(self, sum, name):
+        self.funcHeader(name)
+        for t in sum.types:
+            line = ("isinstance = PyObject_IsInstance(obj, "
+                    "(PyObject *)%s_type);")
+            self.emit(line % (t.name,), 1)
+            self.emit("if (isinstance == -1) {", 1)
+            self.emit("return 1;", 2)
+            self.emit("}", 1)
+            self.emit("if (isinstance) {", 1)
+            self.emit("*out = %s;" % t.name, 2)
+            self.emit("return 0;", 2)
+            self.emit("}", 1)
+        self.sumTrailer(name)
+
+    def buildArgs(self, fields):
+        return ", ".join(fields + ["arena"])
+
+    def complexSum(self, sum, name):
+        self.funcHeader(name)
+        self.emit("PyObject *tmp = NULL;", 1)
+        for a in sum.attributes:
+            self.visitAttributeDeclaration(a, name, sum=sum)
+        self.emit("", 0)
+        # XXX: should we only do this for 'expr'?
+        self.emit("if (obj == Py_None) {", 1)
+        self.emit("*out = NULL;", 2)
+        self.emit("return 0;", 2)
+        self.emit("}", 1)
+        for a in sum.attributes:
+            self.visitField(a, name, sum=sum, depth=1)
+        for t in sum.types:
+            line = "isinstance = PyObject_IsInstance(obj, (PyObject*)%s_type);"
+            self.emit(line % (t.name,), 1)
+            self.emit("if (isinstance == -1) {", 1)
+            self.emit("return 1;", 2)
+            self.emit("}", 1)
+            self.emit("if (isinstance) {", 1)
+            for f in t.fields:
+                self.visitFieldDeclaration(f, t.name, sum=sum, depth=2)
+            self.emit("", 0)
+            for f in t.fields:
+                self.visitField(f, t.name, sum=sum, depth=2)
+            args = [f.name for f in t.fields] + [a.name for a in sum.attributes]
+            self.emit("*out = %s(%s);" % (t.name, self.buildArgs(args)), 2)
+            self.emit("if (*out == NULL) goto failed;", 2)
+            self.emit("return 0;", 2)
+            self.emit("}", 1)
+        self.sumTrailer(name, True)
+
+    def visitAttributeDeclaration(self, a, name, sum=sum):
+        ctype = get_c_type(a.type)
+        self.emit("%s %s;" % (ctype, a.name), 1)
+
+    def visitSum(self, sum, name):
+        if is_simple(sum):
+            self.simpleSum(sum, name)
+        else:
+            self.complexSum(sum, name)
+
+    def visitProduct(self, prod, name):
+        ctype = get_c_type(name)
+        self.emit("int", 0)
+        self.emit("obj2ast_%s(PyObject* obj, %s* out, PyArena* arena)" % (name, ctype), 0)
+        self.emit("{", 0)
+        self.emit("PyObject* tmp = NULL;", 1)
+        for f in prod.fields:
+            self.visitFieldDeclaration(f, name, prod=prod, depth=1)
+        for a in prod.attributes:
+            self.visitFieldDeclaration(a, name, prod=prod, depth=1)
+        self.emit("", 0)
+        for f in prod.fields:
+            self.visitField(f, name, prod=prod, depth=1)
+        for a in prod.attributes:
+            self.visitField(a, name, prod=prod, depth=1)
+        args = [f.name for f in prod.fields]
+        args.extend([a.name for a in prod.attributes])
+        self.emit("*out = %s(%s);" % (name, self.buildArgs(args)), 1)
+        self.emit("return 0;", 1)
+        self.emit("failed:", 0)
+        self.emit("Py_XDECREF(tmp);", 1)
+        self.emit("return 1;", 1)
+        self.emit("}", 0)
+        self.emit("", 0)
+
+    def visitFieldDeclaration(self, field, name, sum=None, prod=None, depth=0):
+        ctype = get_c_type(field.type)
+        if field.seq:
+            if self.isSimpleType(field):
+                self.emit("asdl_int_seq* %s;" % field.name, depth)
+            else:
+                self.emit("asdl_seq* %s;" % field.name, depth)
+        else:
+            ctype = get_c_type(field.type)
+            self.emit("%s %s;" % (ctype, field.name), depth)
+
+    def isSimpleSum(self, field):
+        # XXX can the members of this list be determined automatically?
+        return field.type in ('expr_context', 'boolop', 'operator',
+                              'unaryop', 'cmpop')
+
+    def isNumeric(self, field):
+        return get_c_type(field.type) in ("int", "bool")
+
+    def isSimpleType(self, field):
+        return self.isSimpleSum(field) or self.isNumeric(field)
+
+    def visitField(self, field, name, sum=None, prod=None, depth=0):
+        ctype = get_c_type(field.type)
+        if field.opt:
+            check = "exists_not_none(obj, &PyId_%s)" % (field.name,)
+        else:
+            check = "_PyObject_HasAttrId(obj, &PyId_%s)" % (field.name,)
+        self.emit("if (%s) {" % (check,), depth, reflow=False)
+        self.emit("int res;", depth+1)
+        if field.seq:
+            self.emit("Py_ssize_t len;", depth+1)
+            self.emit("Py_ssize_t i;", depth+1)
+        self.emit("tmp = _PyObject_GetAttrId(obj, &PyId_%s);" % field.name, depth+1)
+        self.emit("if (tmp == NULL) goto failed;", depth+1)
+        if field.seq:
+            self.emit("if (!PyList_Check(tmp)) {", depth+1)
+            self.emit("PyErr_Format(PyExc_TypeError, \"%s field \\\"%s\\\" must "
+                      "be a list, not a %%.200s\", tmp->ob_type->tp_name);" %
+                      (name, field.name),
+                      depth+2, reflow=False)
+            self.emit("goto failed;", depth+2)
+            self.emit("}", depth+1)
+            self.emit("len = PyList_GET_SIZE(tmp);", depth+1)
+            if self.isSimpleType(field):
+                self.emit("%s = _Py_asdl_int_seq_new(len, arena);" % field.name, depth+1)
+            else:
+                self.emit("%s = _Py_asdl_seq_new(len, arena);" % field.name, depth+1)
+            self.emit("if (%s == NULL) goto failed;" % field.name, depth+1)
+            self.emit("for (i = 0; i < len; i++) {", depth+1)
+            self.emit("%s value;" % ctype, depth+2)
+            self.emit("res = obj2ast_%s(PyList_GET_ITEM(tmp, i), &value, arena);" %
+                      field.type, depth+2, reflow=False)
+            self.emit("if (res != 0) goto failed;", depth+2)
+            self.emit("asdl_seq_SET(%s, i, value);" % field.name, depth+2)
+            self.emit("}", depth+1)
+        else:
+            self.emit("res = obj2ast_%s(tmp, &%s, arena);" %
+                      (field.type, field.name), depth+1)
+            self.emit("if (res != 0) goto failed;", depth+1)
+
+        self.emit("Py_CLEAR(tmp);", depth+1)
+        self.emit("} else {", depth)
+        if not field.opt:
+            message = "required field \\\"%s\\\" missing from %s" % (field.name, name)
+            format = "PyErr_SetString(PyExc_TypeError, \"%s\");"
+            self.emit(format % message, depth+1, reflow=False)
+            self.emit("return 1;", depth+1)
+        else:
+            if self.isNumeric(field):
+                self.emit("%s = 0;" % field.name, depth+1)
+            elif not self.isSimpleType(field):
+                self.emit("%s = NULL;" % field.name, depth+1)
+            else:
+                raise TypeError("could not determine the default value for %s" % field.name)
+        self.emit("}", depth)
+
+
+class MarshalPrototypeVisitor(PickleVisitor):
+
+    def prototype(self, sum, name):
+        ctype = get_c_type(name)
+        self.emit("static int marshal_write_%s(PyObject **, int *, %s);"
+                  % (name, ctype), 0)
+
+    visitProduct = visitSum = prototype
+
+
+class PyTypesDeclareVisitor(PickleVisitor):
+
+    def visitProduct(self, prod, name):
+        self.emit("static PyTypeObject *%s_type;" % name, 0)
+        self.emit("static PyObject* ast2obj_%s(void*);" % name, 0)
+        if prod.attributes:
+            for a in prod.attributes:
+                self.emit_identifier(a.name)
+            self.emit("static char *%s_attributes[] = {" % name, 0)
+            for a in prod.attributes:
+                self.emit('"%s",' % a.name, 1)
+            self.emit("};", 0)
+        if prod.fields:
+            for f in prod.fields:
+                self.emit_identifier(f.name)
+            self.emit("static char *%s_fields[]={" % name,0)
+            for f in prod.fields:
+                self.emit('"%s",' % f.name, 1)
+            self.emit("};", 0)
+
+    def visitSum(self, sum, name):
+        self.emit("static PyTypeObject *%s_type;" % name, 0)
+        if sum.attributes:
+            for a in sum.attributes:
+                self.emit_identifier(a.name)
+            self.emit("static char *%s_attributes[] = {" % name, 0)
+            for a in sum.attributes:
+                self.emit('"%s",' % a.name, 1)
+            self.emit("};", 0)
+        ptype = "void*"
+        if is_simple(sum):
+            ptype = get_c_type(name)
+            tnames = []
+            for t in sum.types:
+                tnames.append(str(t.name)+"_singleton")
+            tnames = ", *".join(tnames)
+            self.emit("static PyObject *%s;" % tnames, 0)
+        self.emit("static PyObject* ast2obj_%s(%s);" % (name, ptype), 0)
+        for t in sum.types:
+            self.visitConstructor(t, name)
+
+    def visitConstructor(self, cons, name):
+        self.emit("static PyTypeObject *%s_type;" % cons.name, 0)
+        if cons.fields:
+            for t in cons.fields:
+                self.emit_identifier(t.name)
+            self.emit("static char *%s_fields[]={" % cons.name, 0)
+            for t in cons.fields:
+                self.emit('"%s",' % t.name, 1)
+            self.emit("};",0)
+
+class PyTypesVisitor(PickleVisitor):
+
+    def visitModule(self, mod):
+        self.emit("""
+typedef struct {
+    PyObject_HEAD
+    PyObject *dict;
+} AST_object;
+
+static void
+ast_dealloc(AST_object *self)
+{
+    Py_CLEAR(self->dict);
+    Py_TYPE(self)->tp_free(self);
+}
+
+static int
+ast_traverse(AST_object *self, visitproc visit, void *arg)
+{
+    Py_VISIT(self->dict);
+    return 0;
+}
+
+static void
+ast_clear(AST_object *self)
+{
+    Py_CLEAR(self->dict);
+}
+
+static int
+ast_type_init(PyObject *self, PyObject *args, PyObject *kw)
+{
+    _Py_IDENTIFIER(_fields);
+    Py_ssize_t i, numfields = 0;
+    int res = -1;
+    PyObject *key, *value, *fields;
+    fields = _PyObject_GetAttrId((PyObject*)Py_TYPE(self), &PyId__fields);
+    if (!fields)
+        PyErr_Clear();
+    if (fields) {
+        numfields = PySequence_Size(fields);
+        if (numfields == -1)
+            goto cleanup;
+    }
+    res = 0; /* if no error occurs, this stays 0 to the end */
+    if (PyTuple_GET_SIZE(args) > 0) {
+        if (numfields != PyTuple_GET_SIZE(args)) {
+            PyErr_Format(PyExc_TypeError, "%.400s constructor takes %s"
+                         "%zd positional argument%s",
+                         Py_TYPE(self)->tp_name,
+                         numfields == 0 ? "" : "either 0 or ",
+                         numfields, numfields == 1 ? "" : "s");
+            res = -1;
+            goto cleanup;
+        }
+        for (i = 0; i < PyTuple_GET_SIZE(args); i++) {
+            /* cannot be reached when fields is NULL */
+            PyObject *name = PySequence_GetItem(fields, i);
+            if (!name) {
+                res = -1;
+                goto cleanup;
+            }
+            res = PyObject_SetAttr(self, name, PyTuple_GET_ITEM(args, i));
+            Py_DECREF(name);
+            if (res < 0)
+                goto cleanup;
+        }
+    }
+    if (kw) {
+        i = 0;  /* needed by PyDict_Next */
+        while (PyDict_Next(kw, &i, &key, &value)) {
+            res = PyObject_SetAttr(self, key, value);
+            if (res < 0)
+                goto cleanup;
+        }
+    }
+  cleanup:
+    Py_XDECREF(fields);
+    return res;
+}
+
+/* Pickling support */
+static PyObject *
+ast_type_reduce(PyObject *self, PyObject *unused)
+{
+    PyObject *res;
+    _Py_IDENTIFIER(__dict__);
+    PyObject *dict = _PyObject_GetAttrId(self, &PyId___dict__);
+    if (dict == NULL) {
+        if (PyErr_ExceptionMatches(PyExc_AttributeError))
+            PyErr_Clear();
+        else
+            return NULL;
+    }
+    if (dict) {
+        res = Py_BuildValue("O()O", Py_TYPE(self), dict);
+        Py_DECREF(dict);
+        return res;
+    }
+    return Py_BuildValue("O()", Py_TYPE(self));
+}
+
+static PyMethodDef ast_type_methods[] = {
+    {"__reduce__", ast_type_reduce, METH_NOARGS, NULL},
+    {NULL}
+};
+
+static PyGetSetDef ast_type_getsets[] = {
+    {"__dict__", PyObject_GenericGetDict, PyObject_GenericSetDict},
+    {NULL}
+};
+
+static PyTypeObject AST_type = {
+    PyVarObject_HEAD_INIT(&PyType_Type, 0)
+    "_ast35.AST",
+    sizeof(AST_object),
+    0,
+    (destructor)ast_dealloc, /* tp_dealloc */
+    0,                       /* tp_print */
+    0,                       /* tp_getattr */
+    0,                       /* tp_setattr */
+    0,                       /* tp_reserved */
+    0,                       /* tp_repr */
+    0,                       /* tp_as_number */
+    0,                       /* tp_as_sequence */
+    0,                       /* tp_as_mapping */
+    0,                       /* tp_hash */
+    0,                       /* tp_call */
+    0,                       /* tp_str */
+    PyObject_GenericGetAttr, /* tp_getattro */
+    PyObject_GenericSetAttr, /* tp_setattro */
+    0,                       /* tp_as_buffer */
+    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /* tp_flags */
+    0,                       /* tp_doc */
+    (traverseproc)ast_traverse, /* tp_traverse */
+    (inquiry)ast_clear,      /* tp_clear */
+    0,                       /* tp_richcompare */
+    0,                       /* tp_weaklistoffset */
+    0,                       /* tp_iter */
+    0,                       /* tp_iternext */
+    ast_type_methods,        /* tp_methods */
+    0,                       /* tp_members */
+    ast_type_getsets,        /* tp_getset */
+    0,                       /* tp_base */
+    0,                       /* tp_dict */
+    0,                       /* tp_descr_get */
+    0,                       /* tp_descr_set */
+    offsetof(AST_object, dict),/* tp_dictoffset */
+    (initproc)ast_type_init, /* tp_init */
+    PyType_GenericAlloc,     /* tp_alloc */
+    PyType_GenericNew,       /* tp_new */
+    PyObject_GC_Del,         /* tp_free */
+};
+
+
+static PyTypeObject* make_type(char *type, PyTypeObject* base, char**fields, int num_fields)
+{
+    PyObject *fnames, *result;
+    int i;
+    fnames = PyTuple_New(num_fields);
+    if (!fnames) return NULL;
+    for (i = 0; i < num_fields; i++) {
+        PyObject *field = PyUnicode_FromString(fields[i]);
+        if (!field) {
+            Py_DECREF(fnames);
+            return NULL;
+        }
+        PyTuple_SET_ITEM(fnames, i, field);
+    }
+    result = PyObject_CallFunction((PyObject*)&PyType_Type, "s(O){sOss}",
+                    type, base, "_fields", fnames, "__module__", "_ast35");
+    Py_DECREF(fnames);
+    return (PyTypeObject*)result;
+}
+
+static int add_attributes(PyTypeObject* type, char**attrs, int num_fields)
+{
+    int i, result;
+    _Py_IDENTIFIER(_attributes);
+    PyObject *s, *l = PyTuple_New(num_fields);
+    if (!l)
+        return 0;
+    for (i = 0; i < num_fields; i++) {
+        s = PyUnicode_FromString(attrs[i]);
+        if (!s) {
+            Py_DECREF(l);
+            return 0;
+        }
+        PyTuple_SET_ITEM(l, i, s);
+    }
+    result = _PyObject_SetAttrId((PyObject*)type, &PyId__attributes, l) >= 0;
+    Py_DECREF(l);
+    return result;
+}
+
+/* Conversion AST -> Python */
+
+static PyObject* ast2obj_list(asdl_seq *seq, PyObject* (*func)(void*))
+{
+    Py_ssize_t i, n = asdl_seq_LEN(seq);
+    PyObject *result = PyList_New(n);
+    PyObject *value;
+    if (!result)
+        return NULL;
+    for (i = 0; i < n; i++) {
+        value = func(asdl_seq_GET(seq, i));
+        if (!value) {
+            Py_DECREF(result);
+            return NULL;
+        }
+        PyList_SET_ITEM(result, i, value);
+    }
+    return result;
+}
+
+static PyObject* ast2obj_object(void *o)
+{
+    if (!o)
+        o = Py_None;
+    Py_INCREF((PyObject*)o);
+    return (PyObject*)o;
+}
+#define ast2obj_singleton ast2obj_object
+#define ast2obj_identifier ast2obj_object
+#define ast2obj_string ast2obj_object
+#define ast2obj_bytes ast2obj_object
+
+static PyObject* ast2obj_int(long b)
+{
+    return PyLong_FromLong(b);
+}
+
+/* Conversion Python -> AST */
+
+static int obj2ast_singleton(PyObject *obj, PyObject** out, PyArena* arena)
+{
+    if (obj != Py_None && obj != Py_True && obj != Py_False) {
+        PyErr_SetString(PyExc_ValueError,
+                        "AST singleton must be True, False, or None");
+        return 1;
+    }
+    *out = obj;
+    return 0;
+}
+
+static int obj2ast_object(PyObject* obj, PyObject** out, PyArena* arena)
+{
+    if (obj == Py_None)
+        obj = NULL;
+    if (obj) {
+        if (PyArena_AddPyObject(arena, obj) < 0) {
+            *out = NULL;
+            return -1;
+        }
+        Py_INCREF(obj);
+    }
+    *out = obj;
+    return 0;
+}
+
+static int obj2ast_identifier(PyObject* obj, PyObject** out, PyArena* arena)
+{
+    if (!PyUnicode_CheckExact(obj) && obj != Py_None) {
+        PyErr_SetString(PyExc_TypeError, "AST identifier must be of type str");
+        return 1;
+    }
+    return obj2ast_object(obj, out, arena);
+}
+
+static int obj2ast_string(PyObject* obj, PyObject** out, PyArena* arena)
+{
+    if (!PyUnicode_CheckExact(obj) && !PyBytes_CheckExact(obj)) {
+        PyErr_SetString(PyExc_TypeError, "AST string must be of type str");
+        return 1;
+    }
+    return obj2ast_object(obj, out, arena);
+}
+
+static int obj2ast_bytes(PyObject* obj, PyObject** out, PyArena* arena)
+{
+    if (!PyBytes_CheckExact(obj)) {
+        PyErr_SetString(PyExc_TypeError, "AST bytes must be of type bytes");
+        return 1;
+    }
+    return obj2ast_object(obj, out, arena);
+}
+
+static int obj2ast_int(PyObject* obj, int* out, PyArena* arena)
+{
+    int i;
+    if (!PyLong_Check(obj)) {
+        PyErr_Format(PyExc_ValueError, "invalid integer value: %R", obj);
+        return 1;
+    }
+
+    i = (int)PyLong_AsLong(obj);
+    if (i == -1 && PyErr_Occurred())
+        return 1;
+    *out = i;
+    return 0;
+}
+
+static int add_ast_fields(void)
+{
+    PyObject *empty_tuple, *d;
+    if (PyType_Ready(&AST_type) < 0)
+        return -1;
+    d = AST_type.tp_dict;
+    empty_tuple = PyTuple_New(0);
+    if (!empty_tuple ||
+        PyDict_SetItemString(d, "_fields", empty_tuple) < 0 ||
+        PyDict_SetItemString(d, "_attributes", empty_tuple) < 0) {
+        Py_XDECREF(empty_tuple);
+        return -1;
+    }
+    Py_DECREF(empty_tuple);
+    return 0;
+}
+
+static int exists_not_none(PyObject *obj, _Py_Identifier *id)
+{
+    int isnone;
+    PyObject *attr = _PyObject_GetAttrId(obj, id);
+    if (!attr) {
+        PyErr_Clear();
+        return 0;
+    }
+    isnone = attr == Py_None;
+    Py_DECREF(attr);
+    return !isnone;
+}
+
+""", 0, reflow=False)
+
+        self.emit("static int init_types(void)",0)
+        self.emit("{", 0)
+        self.emit("static int initialized;", 1)
+        self.emit("if (initialized) return 1;", 1)
+        self.emit("if (add_ast_fields() < 0) return 0;", 1)
+        for dfn in mod.dfns:
+            self.visit(dfn)
+        self.emit("initialized = 1;", 1)
+        self.emit("return 1;", 1);
+        self.emit("}", 0)
+
+    def visitProduct(self, prod, name):
+        if prod.fields:
+            fields = name+"_fields"
+        else:
+            fields = "NULL"
+        self.emit('%s_type = make_type("%s", &AST_type, %s, %d);' %
+                        (name, name, fields, len(prod.fields)), 1)
+        self.emit("if (!%s_type) return 0;" % name, 1)
+        if prod.attributes:
+            self.emit("if (!add_attributes(%s_type, %s_attributes, %d)) return 0;" %
+                            (name, name, len(prod.attributes)), 1)
+        else:
+            self.emit("if (!add_attributes(%s_type, NULL, 0)) return 0;" % name, 1)
+
+    def visitSum(self, sum, name):
+        self.emit('%s_type = make_type("%s", &AST_type, NULL, 0);' %
+                  (name, name), 1)
+        self.emit("if (!%s_type) return 0;" % name, 1)
+        if sum.attributes:
+            self.emit("if (!add_attributes(%s_type, %s_attributes, %d)) return 0;" %
+                            (name, name, len(sum.attributes)), 1)
+        else:
+            self.emit("if (!add_attributes(%s_type, NULL, 0)) return 0;" % name, 1)
+        simple = is_simple(sum)
+        for t in sum.types:
+            self.visitConstructor(t, name, simple)
+
+    def visitConstructor(self, cons, name, simple):
+        if cons.fields:
+            fields = cons.name+"_fields"
+        else:
+            fields = "NULL"
+        self.emit('%s_type = make_type("%s", %s_type, %s, %d);' %
+                            (cons.name, cons.name, name, fields, len(cons.fields)), 1)
+        self.emit("if (!%s_type) return 0;" % cons.name, 1)
+        if simple:
+            self.emit("%s_singleton = PyType_GenericNew(%s_type, NULL, NULL);" %
+                             (cons.name, cons.name), 1)
+            self.emit("if (!%s_singleton) return 0;" % cons.name, 1)
+
+
+class ASTModuleVisitor(PickleVisitor):
+
+    def visitModule(self, mod):
+        # add parse method to module
+        self.emit('PyObject *ast35_parse(PyObject *self, PyObject *args);', 0)
+        self.emit('static PyMethodDef ast35_methods[] = {', 0)
+        self.emit('{"_parse",  ast35_parse, METH_VARARGS, "Parse string into typed AST."},', 1)
+        self.emit('{NULL, NULL, 0, NULL}', 1)
+        self.emit('};', 0)
+
+        self.emit("static struct PyModuleDef _astmodule35 = {", 0)
+        self.emit('  PyModuleDef_HEAD_INIT, "_ast35", NULL, 0, ast35_methods', 0)
+        self.emit("};", 0)
+        self.emit("PyMODINIT_FUNC", 0)
+        self.emit("PyInit__ast35(void)", 0)
+        self.emit("{", 0)
+        self.emit("PyObject *m, *d;", 1)
+        self.emit("if (!init_types()) return NULL;", 1)
+        self.emit('m = PyModule_Create(&_astmodule35);', 1)
+        self.emit("if (!m) return NULL;", 1)
+        self.emit("d = PyModule_GetDict(m);", 1)
+        self.emit('if (PyDict_SetItemString(d, "AST", (PyObject*)&AST_type) < 0) return NULL;', 1)
+        self.emit('if (PyModule_AddIntMacro(m, PyCF_ONLY_AST) < 0)', 1)
+        self.emit("return NULL;", 2)
+        for dfn in mod.dfns:
+            self.visit(dfn)
+        self.emit("return m;", 1)
+        self.emit("}", 0)
+
+    def visitProduct(self, prod, name):
+        self.addObj(name)
+
+    def visitSum(self, sum, name):
+        self.addObj(name)
+        for t in sum.types:
+            self.visitConstructor(t, name)
+
+    def visitConstructor(self, cons, name):
+        self.addObj(cons.name)
+
+    def addObj(self, name):
+        self.emit('if (PyDict_SetItemString(d, "%s", (PyObject*)%s_type) < 0) return NULL;' % (name, name), 1)
+
+
+_SPECIALIZED_SEQUENCES = ('stmt', 'expr')
+
+def find_sequence(fields, doing_specialization):
+    """Return True if any field uses a sequence."""
+    for f in fields:
+        if f.seq:
+            if not doing_specialization:
+                return True
+            if str(f.type) not in _SPECIALIZED_SEQUENCES:
+                return True
+    return False
+
+def has_sequence(types, doing_specialization):
+    for t in types:
+        if find_sequence(t.fields, doing_specialization):
+            return True
+    return False
+
+
+class StaticVisitor(PickleVisitor):
+    CODE = '''Very simple, always emit this static code.  Override CODE'''
+
+    def visit(self, object):
+        self.emit(self.CODE, 0, reflow=False)
+
+
+class ObjVisitor(PickleVisitor):
+
+    def func_begin(self, name):
+        ctype = get_c_type(name)
+        self.emit("PyObject*", 0)
+        self.emit("ast2obj_%s(void* _o)" % (name), 0)
+        self.emit("{", 0)
+        self.emit("%s o = (%s)_o;" % (ctype, ctype), 1)
+        self.emit("PyObject *result = NULL, *value = NULL;", 1)
+        self.emit('if (!o) {', 1)
+        self.emit("Py_INCREF(Py_None);", 2)
+        self.emit('return Py_None;', 2)
+        self.emit("}", 1)
+        self.emit('', 0)
+
+    def func_end(self):
+        self.emit("return result;", 1)
+        self.emit("failed:", 0)
+        self.emit("Py_XDECREF(value);", 1)
+        self.emit("Py_XDECREF(result);", 1)
+        self.emit("return NULL;", 1)
+        self.emit("}", 0)
+        self.emit("", 0)
+
+    def visitSum(self, sum, name):
+        if is_simple(sum):
+            self.simpleSum(sum, name)
+            return
+        self.func_begin(name)
+        self.emit("switch (o->kind) {", 1)
+        for i in range(len(sum.types)):
+            t = sum.types[i]
+            self.visitConstructor(t, i + 1, name)
+        self.emit("}", 1)
+        for a in sum.attributes:
+            self.emit("value = ast2obj_%s(o->%s);" % (a.type, a.name), 1)
+            self.emit("if (!value) goto failed;", 1)
+            self.emit('if (_PyObject_SetAttrId(result, &PyId_%s, value) < 0)' % a.name, 1)
+            self.emit('goto failed;', 2)
+            self.emit('Py_DECREF(value);', 1)
+        self.func_end()
+
+    def simpleSum(self, sum, name):
+        self.emit("PyObject* ast2obj_%s(%s_ty o)" % (name, name), 0)
+        self.emit("{", 0)
+        self.emit("switch(o) {", 1)
+        for t in sum.types:
+            self.emit("case %s:" % t.name, 2)
+            self.emit("Py_INCREF(%s_singleton);" % t.name, 3)
+            self.emit("return %s_singleton;" % t.name, 3)
+        self.emit("default:", 2)
+        self.emit('/* should never happen, but just in case ... */', 3)
+        code = "PyErr_Format(PyExc_SystemError, \"unknown %s found\");" % name
+        self.emit(code, 3, reflow=False)
+        self.emit("return NULL;", 3)
+        self.emit("}", 1)
+        self.emit("}", 0)
+
+    def visitProduct(self, prod, name):
+        self.func_begin(name)
+        self.emit("result = PyType_GenericNew(%s_type, NULL, NULL);" % name, 1);
+        self.emit("if (!result) return NULL;", 1)
+        for field in prod.fields:
+            self.visitField(field, name, 1, True)
+        for a in prod.attributes:
+            self.emit("value = ast2obj_%s(o->%s);" % (a.type, a.name), 1)
+            self.emit("if (!value) goto failed;", 1)
+            self.emit('if (_PyObject_SetAttrId(result, &PyId_%s, value) < 0)' % a.name, 1)
+            self.emit('goto failed;', 2)
+            self.emit('Py_DECREF(value);', 1)
+        self.func_end()
+
+    def visitConstructor(self, cons, enum, name):
+        self.emit("case %s_kind:" % cons.name, 1)
+        self.emit("result = PyType_GenericNew(%s_type, NULL, NULL);" % cons.name, 2);
+        self.emit("if (!result) goto failed;", 2)
+        for f in cons.fields:
+            self.visitField(f, cons.name, 2, False)
+        self.emit("break;", 2)
+
+    def visitField(self, field, name, depth, product):
+        def emit(s, d):
+            self.emit(s, depth + d)
+        if product:
+            value = "o->%s" % field.name
+        else:
+            value = "o->v.%s.%s" % (name, field.name)
+        self.set(field, value, depth)
+        emit("if (!value) goto failed;", 0)
+        emit('if (_PyObject_SetAttrId(result, &PyId_%s, value) == -1)' % field.name, 0)
+        emit("goto failed;", 1)
+        emit("Py_DECREF(value);", 0)
+
+    def emitSeq(self, field, value, depth, emit):
+        emit("seq = %s;" % value, 0)
+        emit("n = asdl_seq_LEN(seq);", 0)
+        emit("value = PyList_New(n);", 0)
+        emit("if (!value) goto failed;", 0)
+        emit("for (i = 0; i < n; i++) {", 0)
+        self.set("value", field, "asdl_seq_GET(seq, i)", depth + 1)
+        emit("if (!value1) goto failed;", 1)
+        emit("PyList_SET_ITEM(value, i, value1);", 1)
+        emit("value1 = NULL;", 1)
+        emit("}", 0)
+
+    def set(self, field, value, depth):
+        if field.seq:
+            # XXX should really check for is_simple, but that requires a symbol table
+            if field.type == "cmpop":
+                # While the sequence elements are stored as void*,
+                # ast2obj_cmpop expects an enum
+                self.emit("{", depth)
+                self.emit("Py_ssize_t i, n = asdl_seq_LEN(%s);" % value, depth+1)
+                self.emit("value = PyList_New(n);", depth+1)
+                self.emit("if (!value) goto failed;", depth+1)
+                self.emit("for(i = 0; i < n; i++)", depth+1)
+                # This cannot fail, so no need for error handling
+                self.emit("PyList_SET_ITEM(value, i, ast2obj_cmpop((cmpop_ty)asdl_seq_GET(%s, i)));" % value,
+                          depth+2, reflow=False)
+                self.emit("}", depth)
+            else:
+                self.emit("value = ast2obj_list(%s, ast2obj_%s);" % (value, field.type), depth)
+        else:
+            ctype = get_c_type(field.type)
+            self.emit("value = ast2obj_%s(%s);" % (field.type, value), depth, reflow=False)
+
+
+class PartingShots(StaticVisitor):
+
+    CODE = """
+PyObject* Ta35AST_mod2obj(mod_ty t)
+{
+    if (!init_types())
+        return NULL;
+    return ast2obj_mod(t);
+}
+
+/* mode is 0 for "exec", 1 for "eval" and 2 for "single" input */
+mod_ty Ta35AST_obj2mod(PyObject* ast, PyArena* arena, int mode)
+{
+    mod_ty res;
+    PyObject *req_type[3];
+    char *req_name[] = {"Module", "Expression", "Interactive"};
+    int isinstance;
+
+    req_type[0] = (PyObject*)Module_type;
+    req_type[1] = (PyObject*)Expression_type;
+    req_type[2] = (PyObject*)Interactive_type;
+
+    assert(0 <= mode && mode <= 2);
+
+    if (!init_types())
+        return NULL;
+
+    isinstance = PyObject_IsInstance(ast, req_type[mode]);
+    if (isinstance == -1)
+        return NULL;
+    if (!isinstance) {
+        PyErr_Format(PyExc_TypeError, "expected %s node, got %.400s",
+                     req_name[mode], Py_TYPE(ast)->tp_name);
+        return NULL;
+    }
+    if (obj2ast_mod(ast, &res, arena) != 0)
+        return NULL;
+    else
+        return res;
+}
+
+int Ta35AST_Check(PyObject* obj)
+{
+    if (!init_types())
+        return -1;
+    return PyObject_IsInstance(obj, (PyObject*)&AST_type);
+}
+"""
+
+class ChainOfVisitors:
+    def __init__(self, *visitors):
+        self.visitors = visitors
+
+    def visit(self, object):
+        for v in self.visitors:
+            v.visit(object)
+            v.emit("", 0)
+
+common_msg = "/* File automatically generated by %s. */\n\n"
+
+def main(srcfile, dump_module=False):
+    argv0 = sys.argv[0]
+    components = argv0.split(os.sep)
+    argv0 = os.sep.join(components[-2:])
+    auto_gen_msg = common_msg % argv0
+    mod = asdl.parse(srcfile)
+    if dump_module:
+        print('Parsed Module:')
+        print(mod)
+    if not asdl.check(mod):
+        sys.exit(1)
+    if INC_DIR:
+        p = "%s/%s-ast.h" % (INC_DIR, mod.name)
+        f = open(p, "w")
+        f.write(auto_gen_msg)
+        f.write('#include "asdl.h"\n\n')
+        c = ChainOfVisitors(TypeDefVisitor(f),
+                            StructVisitor(f),
+                            PrototypeVisitor(f),
+                            )
+        c.visit(mod)
+        f.write("PyObject* Ta35AST_mod2obj(mod_ty t);\n")
+        f.write("mod_ty Ta35AST_obj2mod(PyObject* ast, PyArena* arena, int mode);\n")
+        f.write("int Ta35AST_Check(PyObject* obj);\n")
+        f.close()
+
+    if SRC_DIR:
+        p = os.path.join(SRC_DIR, str(mod.name) + "-ast.c")
+        f = open(p, "w")
+        f.write(auto_gen_msg)
+        f.write('#include <stddef.h>\n')
+        f.write('\n')
+        f.write('#include "Python.h"\n')
+        f.write('#include "%s-ast.h"\n' % mod.name)
+        f.write('\n')
+        f.write("static PyTypeObject AST_type;\n")
+        v = ChainOfVisitors(
+            PyTypesDeclareVisitor(f),
+            PyTypesVisitor(f),
+            Obj2ModPrototypeVisitor(f),
+            FunctionVisitor(f),
+            ObjVisitor(f),
+            Obj2ModVisitor(f),
+            ASTModuleVisitor(f),
+            PartingShots(f),
+            )
+        v.visit(mod)
+        f.close()
+
+if __name__ == "__main__":
+    import getopt
+
+    INC_DIR = ''
+    SRC_DIR = ''
+    dump_module = False
+    opts, args = getopt.getopt(sys.argv[1:], "dh:c:")
+    for o, v in opts:
+        if o == '-h':
+            INC_DIR = v
+        if o == '-c':
+            SRC_DIR = v
+        if o == '-d':
+            dump_module = True
+    if INC_DIR and SRC_DIR:
+        print('Must specify exactly one output file')
+        sys.exit(1)
+    elif len(args) != 1:
+        print('Must specify single input file')
+        sys.exit(1)
+    main(args[0], dump_module)
diff --git a/ast35/Parser/bitset.c b/ast35/Parser/bitset.c
new file mode 100644
index 0000000..f5bfd41
--- /dev/null
+++ b/ast35/Parser/bitset.c
@@ -0,0 +1,66 @@
+
+/* Bitset primitives used by the parser generator */
+
+#include "pgenheaders.h"
+#include "bitset.h"
+
+bitset
+newbitset(int nbits)
+{
+    int nbytes = NBYTES(nbits);
+    bitset ss = (char *)PyObject_MALLOC(sizeof(BYTE) *  nbytes);
+
+    if (ss == NULL)
+        Py_FatalError("no mem for bitset");
+
+    ss += nbytes;
+    while (--nbytes >= 0)
+        *--ss = 0;
+    return ss;
+}
+
+void
+delbitset(bitset ss)
+{
+    PyObject_FREE(ss);
+}
+
+int
+addbit(bitset ss, int ibit)
+{
+    int ibyte = BIT2BYTE(ibit);
+    BYTE mask = BIT2MASK(ibit);
+
+    if (ss[ibyte] & mask)
+        return 0; /* Bit already set */
+    ss[ibyte] |= mask;
+    return 1;
+}
+
+#if 0 /* Now a macro */
+int
+testbit(bitset ss, int ibit)
+{
+    return (ss[BIT2BYTE(ibit)] & BIT2MASK(ibit)) != 0;
+}
+#endif
+
+int
+samebitset(bitset ss1, bitset ss2, int nbits)
+{
+    int i;
+
+    for (i = NBYTES(nbits); --i >= 0; )
+        if (*ss1++ != *ss2++)
+            return 0;
+    return 1;
+}
+
+void
+mergebitset(bitset ss1, bitset ss2, int nbits)
+{
+    int i;
+
+    for (i = NBYTES(nbits); --i >= 0; )
+        *ss1++ |= *ss2++;
+}
diff --git a/ast35/Parser/grammar.c b/ast35/Parser/grammar.c
new file mode 100644
index 0000000..f6c91c5
--- /dev/null
+++ b/ast35/Parser/grammar.c
@@ -0,0 +1,250 @@
+
+/* Grammar implementation */
+
+#include "Python.h"
+#include "pgenheaders.h"
+
+#include <ctype.h>
+
+#include "token.h"
+#include "grammar.h"
+
+extern int Py_DebugFlag;
+
+grammar *
+newgrammar(int start)
+{
+    grammar *g;
+
+    g = (grammar *)PyObject_MALLOC(sizeof(grammar));
+    if (g == NULL)
+        Py_FatalError("no mem for new grammar");
+    g->g_ndfas = 0;
+    g->g_dfa = NULL;
+    g->g_start = start;
+    g->g_ll.ll_nlabels = 0;
+    g->g_ll.ll_label = NULL;
+    g->g_accel = 0;
+    return g;
+}
+
+dfa *
+adddfa(grammar *g, int type, const char *name)
+{
+    dfa *d;
+
+    g->g_dfa = (dfa *)PyObject_REALLOC(g->g_dfa,
+                                        sizeof(dfa) * (g->g_ndfas + 1));
+    if (g->g_dfa == NULL)
+        Py_FatalError("no mem to resize dfa in adddfa");
+    d = &g->g_dfa[g->g_ndfas++];
+    d->d_type = type;
+    d->d_name = strdup(name);
+    d->d_nstates = 0;
+    d->d_state = NULL;
+    d->d_initial = -1;
+    d->d_first = NULL;
+    return d; /* Only use while fresh! */
+}
+
+int
+addstate(dfa *d)
+{
+    state *s;
+
+    d->d_state = (state *)PyObject_REALLOC(d->d_state,
+                                  sizeof(state) * (d->d_nstates + 1));
+    if (d->d_state == NULL)
+        Py_FatalError("no mem to resize state in addstate");
+    s = &d->d_state[d->d_nstates++];
+    s->s_narcs = 0;
+    s->s_arc = NULL;
+    s->s_lower = 0;
+    s->s_upper = 0;
+    s->s_accel = NULL;
+    s->s_accept = 0;
+    return Py_SAFE_DOWNCAST(s - d->d_state, Py_intptr_t, int);
+}
+
+void
+addarc(dfa *d, int from, int to, int lbl)
+{
+    state *s;
+    arc *a;
+
+    assert(0 <= from && from < d->d_nstates);
+    assert(0 <= to && to < d->d_nstates);
+
+    s = &d->d_state[from];
+    s->s_arc = (arc *)PyObject_REALLOC(s->s_arc, sizeof(arc) * (s->s_narcs + 1));
+    if (s->s_arc == NULL)
+        Py_FatalError("no mem to resize arc list in addarc");
+    a = &s->s_arc[s->s_narcs++];
+    a->a_lbl = lbl;
+    a->a_arrow = to;
+}
+
+int
+addlabel(labellist *ll, int type, const char *str)
+{
+    int i;
+    label *lb;
+
+    for (i = 0; i < ll->ll_nlabels; i++) {
+        if (ll->ll_label[i].lb_type == type &&
+            strcmp(ll->ll_label[i].lb_str, str) == 0)
+            return i;
+    }
+    ll->ll_label = (label *)PyObject_REALLOC(ll->ll_label,
+                                    sizeof(label) * (ll->ll_nlabels + 1));
+    if (ll->ll_label == NULL)
+        Py_FatalError("no mem to resize labellist in addlabel");
+    lb = &ll->ll_label[ll->ll_nlabels++];
+    lb->lb_type = type;
+    lb->lb_str = strdup(str);
+    if (Py_DebugFlag)
+        printf("Label @ %8p, %d: %s\n", ll, ll->ll_nlabels,
+               Ta35Grammar_LabelRepr(lb));
+    return Py_SAFE_DOWNCAST(lb - ll->ll_label, Py_intptr_t, int);
+}
+
+/* Same, but rather dies than adds */
+
+int
+findlabel(labellist *ll, int type, const char *str)
+{
+    int i;
+
+    for (i = 0; i < ll->ll_nlabels; i++) {
+        if (ll->ll_label[i].lb_type == type /*&&
+            strcmp(ll->ll_label[i].lb_str, str) == 0*/)
+            return i;
+    }
+    fprintf(stderr, "Label %d/'%s' not found\n", type, str);
+    Py_FatalError("grammar.c:findlabel()");
+    return 0; /* Make gcc -Wall happy */
+}
+
+/* Forward */
+static void translabel(grammar *, label *);
+
+void
+translatelabels(grammar *g)
+{
+    int i;
+
+#ifdef Py_DEBUG
+    printf("Translating labels ...\n");
+#endif
+    /* Don't translate EMPTY */
+    for (i = EMPTY+1; i < g->g_ll.ll_nlabels; i++)
+        translabel(g, &g->g_ll.ll_label[i]);
+}
+
+static void
+translabel(grammar *g, label *lb)
+{
+    int i;
+
+    if (Py_DebugFlag)
+        printf("Translating label %s ...\n", Ta35Grammar_LabelRepr(lb));
+
+    if (lb->lb_type == NAME) {
+        for (i = 0; i < g->g_ndfas; i++) {
+            if (strcmp(lb->lb_str, g->g_dfa[i].d_name) == 0) {
+                if (Py_DebugFlag)
+                    printf(
+                        "Label %s is non-terminal %d.\n",
+                        lb->lb_str,
+                        g->g_dfa[i].d_type);
+                lb->lb_type = g->g_dfa[i].d_type;
+                free(lb->lb_str);
+                lb->lb_str = NULL;
+                return;
+            }
+        }
+        for (i = 0; i < (int)N_TOKENS; i++) {
+            if (strcmp(lb->lb_str, _Ta35Parser_TokenNames[i]) == 0) {
+                if (Py_DebugFlag)
+                    printf("Label %s is terminal %d.\n",
+                        lb->lb_str, i);
+                lb->lb_type = i;
+                free(lb->lb_str);
+                lb->lb_str = NULL;
+                return;
+            }
+        }
+        printf("Can't translate NAME label '%s'\n", lb->lb_str);
+        return;
+    }
+
+    if (lb->lb_type == STRING) {
+        if (isalpha(Py_CHARMASK(lb->lb_str[1])) ||
+            lb->lb_str[1] == '_') {
+            char *p;
+            char *src;
+            char *dest;
+            size_t name_len;
+            if (Py_DebugFlag)
+                printf("Label %s is a keyword\n", lb->lb_str);
+            lb->lb_type = NAME;
+            src = lb->lb_str + 1;
+            p = strchr(src, '\'');
+            if (p)
+                name_len = p - src;
+            else
+                name_len = strlen(src);
+            dest = (char *)malloc(name_len + 1);
+            if (!dest) {
+                printf("Can't alloc dest '%s'\n", src);
+                return;
+            }
+            strncpy(dest, src, name_len);
+            dest[name_len] = '\0';
+            free(lb->lb_str);
+            lb->lb_str = dest;
+        }
+        else if (lb->lb_str[2] == lb->lb_str[0]) {
+            int type = (int) Ta35Token_OneChar(lb->lb_str[1]);
+            if (type != OP) {
+                lb->lb_type = type;
+                free(lb->lb_str);
+                lb->lb_str = NULL;
+            }
+            else
+                printf("Unknown OP label %s\n",
+                    lb->lb_str);
+        }
+        else if (lb->lb_str[2] && lb->lb_str[3] == lb->lb_str[0]) {
+            int type = (int) Ta35Token_TwoChars(lb->lb_str[1],
+                                       lb->lb_str[2]);
+            if (type != OP) {
+                lb->lb_type = type;
+                free(lb->lb_str);
+                lb->lb_str = NULL;
+            }
+            else
+                printf("Unknown OP label %s\n",
+                    lb->lb_str);
+        }
+        else if (lb->lb_str[2] && lb->lb_str[3] && lb->lb_str[4] == lb->lb_str[0]) {
+            int type = (int) Ta35Token_ThreeChars(lb->lb_str[1],
+                                                lb->lb_str[2],
+                                                lb->lb_str[3]);
+            if (type != OP) {
+                lb->lb_type = type;
+                free(lb->lb_str);
+                lb->lb_str = NULL;
+            }
+            else
+                printf("Unknown OP label %s\n",
+                    lb->lb_str);
+        }
+        else
+            printf("Can't translate STRING label %s\n",
+                lb->lb_str);
+    }
+    else
+        printf("Can't translate label '%s'\n",
+               Ta35Grammar_LabelRepr(lb));
+}
diff --git a/ast35/Parser/grammar1.c b/ast35/Parser/grammar1.c
new file mode 100644
index 0000000..cbeaf06
--- /dev/null
+++ b/ast35/Parser/grammar1.c
@@ -0,0 +1,61 @@
+
+/* Grammar subroutines needed by parser */
+
+#include "Python.h"
+#include "pgenheaders.h"
+#include "grammar.h"
+#include "token.h"
+
+/* Return the DFA for the given type */
+
+dfa *
+Ta35Grammar_FindDFA(grammar *g, int type)
+{
+    dfa *d;
+#if 1
+    /* Massive speed-up */
+    d = &g->g_dfa[type - NT_OFFSET];
+    assert(d->d_type == type);
+    return d;
+#else
+    /* Old, slow version */
+    int i;
+
+    for (i = g->g_ndfas, d = g->g_dfa; --i >= 0; d++) {
+        if (d->d_type == type)
+            return d;
+    }
+    assert(0);
+    /* NOTREACHED */
+#endif
+}
+
+const char *
+Ta35Grammar_LabelRepr(label *lb)
+{
+    static char buf[100];
+
+    if (lb->lb_type == ENDMARKER)
+        return "EMPTY";
+    else if (ISNONTERMINAL(lb->lb_type)) {
+        if (lb->lb_str == NULL) {
+            PyOS_snprintf(buf, sizeof(buf), "NT%d", lb->lb_type);
+            return buf;
+        }
+        else
+            return lb->lb_str;
+    }
+    else if (lb->lb_type < N_TOKENS) {
+        if (lb->lb_str == NULL)
+            return _Ta35Parser_TokenNames[lb->lb_type];
+        else {
+            PyOS_snprintf(buf, sizeof(buf), "%.32s(%.32s)",
+                _Ta35Parser_TokenNames[lb->lb_type], lb->lb_str);
+            return buf;
+        }
+    }
+    else {
+        Py_FatalError("invalid label");
+        return NULL;
+    }
+}
diff --git a/ast35/Parser/node.c b/ast35/Parser/node.c
new file mode 100644
index 0000000..9747c2e
--- /dev/null
+++ b/ast35/Parser/node.c
@@ -0,0 +1,169 @@
+/* Parse tree node implementation */
+
+#include "Python.h"
+#include "node.h"
+#include "errcode.h"
+
+#if PY_MINOR_VERSION < 3
+#define _Py_SIZE_ROUND_UP(n, a) (((size_t)(n) + \
+        (size_t)((a) - 1)) & ~(size_t)((a) - 1))
+#endif
+
+node *
+Ta35Node_New(int type)
+{
+    node *n = (node *) PyObject_MALLOC(1 * sizeof(node));
+    if (n == NULL)
+        return NULL;
+    n->n_type = type;
+    n->n_str = NULL;
+    n->n_lineno = 0;
+    n->n_nchildren = 0;
+    n->n_child = NULL;
+    return n;
+}
+
+/* See comments at XXXROUNDUP below.  Returns -1 on overflow. */
+static int
+fancy_roundup(int n)
+{
+    /* Round up to the closest power of 2 >= n. */
+    int result = 256;
+    assert(n > 128);
+    while (result < n) {
+        result <<= 1;
+        if (result <= 0)
+            return -1;
+    }
+    return result;
+}
+
+/* A gimmick to make massive numbers of reallocs quicker.  The result is
+ * a number >= the input.  In Ta35Node_AddChild, it's used like so, when
+ * we're about to add child number current_size + 1:
+ *
+ *     if XXXROUNDUP(current_size) < XXXROUNDUP(current_size + 1):
+ *         allocate space for XXXROUNDUP(current_size + 1) total children
+ *     else:
+ *         we already have enough space
+ *
+ * Since a node starts out empty, we must have
+ *
+ *     XXXROUNDUP(0) < XXXROUNDUP(1)
+ *
+ * so that we allocate space for the first child.  One-child nodes are very
+ * common (presumably that would change if we used a more abstract form
+ * of syntax tree), so to avoid wasting memory it's desirable that
+ * XXXROUNDUP(1) == 1.  That in turn forces XXXROUNDUP(0) == 0.
+ *
+ * Else for 2 <= n <= 128, we round up to the closest multiple of 4.  Why 4?
+ * Rounding up to a multiple of an exact power of 2 is very efficient, and
+ * most nodes with more than one child have <= 4 kids.
+ *
+ * Else we call fancy_roundup() to grow proportionately to n.  We've got an
+ * extreme case then (like test_longexp.py), and on many platforms doing
+ * anything less than proportional growth leads to exorbitant runtime
+ * (e.g., MacPython), or extreme fragmentation of user address space (e.g.,
+ * Win98).
+ *
+ * In a run of compileall across the 2.3a0 Lib directory, Andrew MacIntyre
+ * reported that, with this scheme, 89% of PyObject_REALLOC calls in
+ * Ta35Node_AddChild passed 1 for the size, and 9% passed 4.  So this usually
+ * wastes very little memory, but is very effective at sidestepping
+ * platform-realloc disasters on vulnerable platforms.
+ *
+ * Note that this would be straightforward if a node stored its current
+ * capacity.  The code is tricky to avoid that.
+ */
+#define XXXROUNDUP(n) ((n) <= 1 ? (n) :                         \
+               (n) <= 128 ? (int)_Py_SIZE_ROUND_UP((n), 4) :    \
+               fancy_roundup(n))
+
+
+int
+Ta35Node_AddChild(node *n1, int type, char *str, int lineno, int col_offset)
+{
+    const int nch = n1->n_nchildren;
+    int current_capacity;
+    int required_capacity;
+    node *n;
+
+    if (nch == INT_MAX || nch < 0)
+        return E_OVERFLOW;
+
+    current_capacity = XXXROUNDUP(nch);
+    required_capacity = XXXROUNDUP(nch + 1);
+    if (current_capacity < 0 || required_capacity < 0)
+        return E_OVERFLOW;
+    if (current_capacity < required_capacity) {
+        if ((size_t)required_capacity > PY_SIZE_MAX / sizeof(node)) {
+            return E_NOMEM;
+        }
+        n = n1->n_child;
+        n = (node *) PyObject_REALLOC(n,
+                                      required_capacity * sizeof(node));
+        if (n == NULL)
+            return E_NOMEM;
+        n1->n_child = n;
+    }
+
+    n = &n1->n_child[n1->n_nchildren++];
+    n->n_type = type;
+    n->n_str = str;
+    n->n_lineno = lineno;
+    n->n_col_offset = col_offset;
+    n->n_nchildren = 0;
+    n->n_child = NULL;
+    return 0;
+}
+
+/* Forward */
+static void freechildren(node *);
+static Py_ssize_t sizeofchildren(node *n);
+
+
+void
+Ta35Node_Free(node *n)
+{
+    if (n != NULL) {
+        freechildren(n);
+        PyObject_FREE(n);
+    }
+}
+
+Py_ssize_t
+_Ta35Node_SizeOf(node *n)
+{
+    Py_ssize_t res = 0;
+
+    if (n != NULL)
+        res = sizeof(node) + sizeofchildren(n);
+    return res;
+}
+
+static void
+freechildren(node *n)
+{
+    int i;
+    for (i = NCH(n); --i >= 0; )
+        freechildren(CHILD(n, i));
+    if (n->n_child != NULL)
+        PyObject_FREE(n->n_child);
+    if (STR(n) != NULL)
+        PyObject_FREE(STR(n));
+}
+
+static Py_ssize_t
+sizeofchildren(node *n)
+{
+    Py_ssize_t res = 0;
+    int i;
+    for (i = NCH(n); --i >= 0; )
+        res += sizeofchildren(CHILD(n, i));
+    if (n->n_child != NULL)
+        /* allocated size of n->n_child array */
+        res += XXXROUNDUP(NCH(n)) * sizeof(node);
+    if (STR(n) != NULL)
+        res += strlen(STR(n)) + 1;
+    return res;
+}
diff --git a/ast35/Parser/parser.c b/ast35/Parser/parser.c
new file mode 100644
index 0000000..c3cd9e8
--- /dev/null
+++ b/ast35/Parser/parser.c
@@ -0,0 +1,448 @@
+
+/* Parser implementation */
+
+/* For a description, see the comments at end of this file */
+
+/* XXX To do: error recovery */
+
+#include "Python.h"
+#include "pgenheaders.h"
+#include "token.h"
+#include "grammar.h"
+#include "node.h"
+#include "parser.h"
+#include "errcode.h"
+
+
+#ifdef Py_DEBUG
+extern int Py_DebugFlag;
+#define D(x) if (!Py_DebugFlag); else x
+#else
+#define D(x)
+#endif
+
+
+/* STACK DATA TYPE */
+
+static void s_reset(stack *);
+
+static void
+s_reset(stack *s)
+{
+    s->s_top = &s->s_base[MAXSTACK];
+}
+
+#define s_empty(s) ((s)->s_top == &(s)->s_base[MAXSTACK])
+
+static int
+s_push(stack *s, dfa *d, node *parent)
+{
+    stackentry *top;
+    if (s->s_top == s->s_base) {
+        fprintf(stderr, "s_push: parser stack overflow\n");
+        return E_NOMEM;
+    }
+    top = --s->s_top;
+    top->s_dfa = d;
+    top->s_parent = parent;
+    top->s_state = 0;
+    return 0;
+}
+
+#ifdef Py_DEBUG
+
+static void
+s_pop(stack *s)
+{
+    if (s_empty(s))
+        Py_FatalError("s_pop: parser stack underflow -- FATAL");
+    s->s_top++;
+}
+
+#else /* !Py_DEBUG */
+
+#define s_pop(s) (s)->s_top++
+
+#endif
+
+
+/* PARSER CREATION */
+
+parser_state *
+Ta35Parser_New(grammar *g, int start)
+{
+    parser_state *ps;
+
+    if (!g->g_accel)
+        Ta35Grammar_AddAccelerators(g);
+    ps = (parser_state *)PyMem_MALLOC(sizeof(parser_state));
+    if (ps == NULL)
+        return NULL;
+    ps->p_grammar = g;
+#ifdef PY_PARSER_REQUIRES_FUTURE_KEYWORD
+    ps->p_flags = 0;
+#endif
+    ps->p_tree = Ta35Node_New(start);
+    if (ps->p_tree == NULL) {
+        PyMem_FREE(ps);
+        return NULL;
+    }
+    s_reset(&ps->p_stack);
+    (void) s_push(&ps->p_stack, Ta35Grammar_FindDFA(g, start), ps->p_tree);
+    return ps;
+}
+
+void
+Ta35Parser_Delete(parser_state *ps)
+{
+    /* NB If you want to save the parse tree,
+       you must set p_tree to NULL before calling delparser! */
+    Ta35Node_Free(ps->p_tree);
+    PyMem_FREE(ps);
+}
+
+
+/* PARSER STACK OPERATIONS */
+
+static int
+shift(stack *s, int type, char *str, int newstate, int lineno, int col_offset)
+{
+    int err;
+    assert(!s_empty(s));
+    err = Ta35Node_AddChild(s->s_top->s_parent, type, str, lineno, col_offset);
+    if (err)
+        return err;
+    s->s_top->s_state = newstate;
+    return 0;
+}
+
+static int
+push(stack *s, int type, dfa *d, int newstate, int lineno, int col_offset)
+{
+    int err;
+    node *n;
+    n = s->s_top->s_parent;
+    assert(!s_empty(s));
+    err = Ta35Node_AddChild(n, type, (char *)NULL, lineno, col_offset);
+    if (err)
+        return err;
+    s->s_top->s_state = newstate;
+    return s_push(s, d, CHILD(n, NCH(n)-1));
+}
+
+
+/* PARSER PROPER */
+
+static int
+classify(parser_state *ps, int type, const char *str)
+{
+    grammar *g = ps->p_grammar;
+    int n = g->g_ll.ll_nlabels;
+
+    if (type == NAME) {
+        const char *s = str;
+        label *l = g->g_ll.ll_label;
+        int i;
+        for (i = n; i > 0; i--, l++) {
+            if (l->lb_type != NAME || l->lb_str == NULL ||
+                l->lb_str[0] != s[0] ||
+                strcmp(l->lb_str, s) != 0)
+                continue;
+#ifdef PY_PARSER_REQUIRES_FUTURE_KEYWORD
+#if 0
+            /* Leaving this in as an example */
+            if (!(ps->p_flags & CO_FUTURE_WITH_STATEMENT)) {
+                if (s[0] == 'w' && strcmp(s, "with") == 0)
+                    break; /* not a keyword yet */
+                else if (s[0] == 'a' && strcmp(s, "as") == 0)
+                    break; /* not a keyword yet */
+            }
+#endif
+#endif
+            D(printf("It's a keyword\n"));
+            return n - i;
+        }
+    }
+
+    {
+        label *l = g->g_ll.ll_label;
+        int i;
+        for (i = n; i > 0; i--, l++) {
+            if (l->lb_type == type && l->lb_str == NULL) {
+                D(printf("It's a token we know\n"));
+                return n - i;
+            }
+        }
+    }
+
+    D(printf("Illegal token\n"));
+    return -1;
+}
+
+#ifdef PY_PARSER_REQUIRES_FUTURE_KEYWORD
+#if 0
+/* Leaving this in as an example */
+static void
+future_hack(parser_state *ps)
+{
+    node *n = ps->p_stack.s_top->s_parent;
+    node *ch, *cch;
+    int i;
+
+    /* from __future__ import ..., must have at least 4 children */
+    n = CHILD(n, 0);
+    if (NCH(n) < 4)
+        return;
+    ch = CHILD(n, 0);
+    if (STR(ch) == NULL || strcmp(STR(ch), "from") != 0)
+        return;
+    ch = CHILD(n, 1);
+    if (NCH(ch) == 1 && STR(CHILD(ch, 0)) &&
+        strcmp(STR(CHILD(ch, 0)), "__future__") != 0)
+        return;
+    ch = CHILD(n, 3);
+    /* ch can be a star, a parenthesis or import_as_names */
+    if (TYPE(ch) == STAR)
+        return;
+    if (TYPE(ch) == LPAR)
+        ch = CHILD(n, 4);
+
+    for (i = 0; i < NCH(ch); i += 2) {
+        cch = CHILD(ch, i);
+        if (NCH(cch) >= 1 && TYPE(CHILD(cch, 0)) == NAME) {
+            char *str_ch = STR(CHILD(cch, 0));
+            if (strcmp(str_ch, FUTURE_WITH_STATEMENT) == 0) {
+                ps->p_flags |= CO_FUTURE_WITH_STATEMENT;
+            } else if (strcmp(str_ch, FUTURE_PRINT_FUNCTION) == 0) {
+                ps->p_flags |= CO_FUTURE_PRINT_FUNCTION;
+            } else if (strcmp(str_ch, FUTURE_UNICODE_LITERALS) == 0) {
+                ps->p_flags |= CO_FUTURE_UNICODE_LITERALS;
+            }
+        }
+    }
+}
+#endif
+#endif /* future keyword */
+
+int
+Ta35Parser_AddToken(parser_state *ps, int type, char *str,
+                  int lineno, int col_offset, int *expected_ret)
+{
+    int ilabel;
+    int err;
+
+    D(printf("Token %s/'%s' ... ", _Ta35Parser_TokenNames[type], str));
+
+    /* Find out which label this token is */
+    ilabel = classify(ps, type, str);
+    if (ilabel < 0)
+        return E_SYNTAX;
+
+    /* Loop until the token is shifted or an error occurred */
+    for (;;) {
+        /* Fetch the current dfa and state */
+        dfa *d = ps->p_stack.s_top->s_dfa;
+        state *s = &d->d_state[ps->p_stack.s_top->s_state];
+
+        D(printf(" DFA '%s', state %d:",
+            d->d_name, ps->p_stack.s_top->s_state));
+
+        /* Check accelerator */
+        if (s->s_lower <= ilabel && ilabel < s->s_upper) {
+            int x = s->s_accel[ilabel - s->s_lower];
+            if (x != -1) {
+                if (x & (1<<7)) {
+                    /* Push non-terminal */
+                    int nt = (x >> 8) + NT_OFFSET;
+                    int arrow = x & ((1<<7)-1);
+                    dfa *d1 = Ta35Grammar_FindDFA(
+                        ps->p_grammar, nt);
+                    if ((err = push(&ps->p_stack, nt, d1,
+                        arrow, lineno, col_offset)) > 0) {
+                        D(printf(" MemError: push\n"));
+                        return err;
+                    }
+                    D(printf(" Push ...\n"));
+                    continue;
+                }
+
+                /* Shift the token */
+                if ((err = shift(&ps->p_stack, type, str,
+                                x, lineno, col_offset)) > 0) {
+                    D(printf(" MemError: shift.\n"));
+                    return err;
+                }
+                D(printf(" Shift.\n"));
+                /* Pop while we are in an accept-only state */
+                while (s = &d->d_state
+                                [ps->p_stack.s_top->s_state],
+                    s->s_accept && s->s_narcs == 1) {
+                    D(printf("  DFA '%s', state %d: "
+                             "Direct pop.\n",
+                             d->d_name,
+                             ps->p_stack.s_top->s_state));
+#ifdef PY_PARSER_REQUIRES_FUTURE_KEYWORD
+#if 0
+                    if (d->d_name[0] == 'i' &&
+                        strcmp(d->d_name,
+                           "import_stmt") == 0)
+                        future_hack(ps);
+#endif
+#endif
+                    s_pop(&ps->p_stack);
+                    if (s_empty(&ps->p_stack)) {
+                        D(printf("  ACCEPT.\n"));
+                        return E_DONE;
+                    }
+                    d = ps->p_stack.s_top->s_dfa;
+                }
+                return E_OK;
+            }
+        }
+
+        if (s->s_accept) {
+#ifdef PY_PARSER_REQUIRES_FUTURE_KEYWORD
+#if 0
+            if (d->d_name[0] == 'i' &&
+                strcmp(d->d_name, "import_stmt") == 0)
+                future_hack(ps);
+#endif
+#endif
+            /* Pop this dfa and try again */
+            s_pop(&ps->p_stack);
+            D(printf(" Pop ...\n"));
+            if (s_empty(&ps->p_stack)) {
+                D(printf(" Error: bottom of stack.\n"));
+                return E_SYNTAX;
+            }
+            continue;
+        }
+
+        /* Stuck, report syntax error */
+        D(printf(" Error.\n"));
+        if (expected_ret) {
+            if (s->s_lower == s->s_upper - 1) {
+                /* Only one possible expected token */
+                *expected_ret = ps->p_grammar->
+                    g_ll.ll_label[s->s_lower].lb_type;
+            }
+            else
+                *expected_ret = -1;
+        }
+        return E_SYNTAX;
+    }
+}
+
+
+#ifdef Py_DEBUG
+
+/* DEBUG OUTPUT */
+
+void
+dumptree(grammar *g, node *n)
+{
+    int i;
+
+    if (n == NULL)
+        printf("NIL");
+    else {
+        label l;
+        l.lb_type = TYPE(n);
+        l.lb_str = STR(n);
+        printf("%s", Ta35Grammar_LabelRepr(&l));
+        if (ISNONTERMINAL(TYPE(n))) {
+            printf("(");
+            for (i = 0; i < NCH(n); i++) {
+                if (i > 0)
+                    printf(",");
+                dumptree(g, CHILD(n, i));
+            }
+            printf(")");
+        }
+    }
+}
+
+void
+showtree(grammar *g, node *n)
+{
+    int i;
+
+    if (n == NULL)
+        return;
+    if (ISNONTERMINAL(TYPE(n))) {
+        for (i = 0; i < NCH(n); i++)
+            showtree(g, CHILD(n, i));
+    }
+    else if (ISTERMINAL(TYPE(n))) {
+        printf("%s", _Ta35Parser_TokenNames[TYPE(n)]);
+        if (TYPE(n) == NUMBER || TYPE(n) == NAME)
+            printf("(%s)", STR(n));
+        printf(" ");
+    }
+    else
+        printf("? ");
+}
+
+void
+printtree(parser_state *ps)
+{
+    if (Py_DebugFlag) {
+        printf("Parse tree:\n");
+        dumptree(ps->p_grammar, ps->p_tree);
+        printf("\n");
+        printf("Tokens:\n");
+        showtree(ps->p_grammar, ps->p_tree);
+        printf("\n");
+    }
+    printf("Listing:\n");
+    Ta35Node_ListTree(ps->p_tree);
+    printf("\n");
+}
+
+#endif /* Py_DEBUG */
+
+/*
+
+Description
+-----------
+
+The parser's interface is different than usual: the function addtoken()
+must be called for each token in the input.  This makes it possible to
+turn it into an incremental parsing system later.  The parsing system
+constructs a parse tree as it goes.
+
+A parsing rule is represented as a Deterministic Finite-state Automaton
+(DFA).  A node in a DFA represents a state of the parser; an arc represents
+a transition.  Transitions are either labeled with terminal symbols or
+with non-terminals.  When the parser decides to follow an arc labeled
+with a non-terminal, it is invoked recursively with the DFA representing
+the parsing rule for that as its initial state; when that DFA accepts,
+the parser that invoked it continues.  The parse tree constructed by the
+recursively called parser is inserted as a child in the current parse tree.
+
+The DFA's can be constructed automatically from a more conventional
+language description.  An extended LL(1) grammar (ELL(1)) is suitable.
+Certain restrictions make the parser's life easier: rules that can produce
+the empty string should be outlawed (there are other ways to put loops
+or optional parts in the language).  To avoid the need to construct
+FIRST sets, we can require that all but the last alternative of a rule
+(really: arc going out of a DFA's state) must begin with a terminal
+symbol.
+
+As an example, consider this grammar:
+
+expr:   term (OP term)*
+term:   CONSTANT | '(' expr ')'
+
+The DFA corresponding to the rule for expr is:
+
+------->.---term-->.------->
+    ^          |
+    |          |
+    \----OP----/
+
+The parse tree generated for the input a+b is:
+
+(expr: (term: (NAME: a)), (OP: +), (term: (NAME: b)))
+
+*/
diff --git a/ast35/Parser/parser.h b/ast35/Parser/parser.h
new file mode 100644
index 0000000..cfb926e
--- /dev/null
+++ b/ast35/Parser/parser.h
@@ -0,0 +1,42 @@
+#ifndef Ta35_PARSER_H
+#define Ta35_PARSER_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* Parser interface */
+
+#define MAXSTACK 1500
+
+typedef struct {
+	int		 s_state;	/* State in current DFA */
+	dfa		*s_dfa;		/* Current DFA */
+	struct _node	*s_parent;	/* Where to add next node */
+} stackentry;
+
+typedef struct {
+	stackentry	*s_top;		/* Top entry */
+	stackentry	 s_base[MAXSTACK];/* Array of stack entries */
+					/* NB The stack grows down */
+} stack;
+
+typedef struct {
+	stack	 	p_stack;	/* Stack of parser states */
+	grammar		*p_grammar;	/* Grammar to use */
+	node		*p_tree;	/* Top of parse tree */
+#ifdef PY_PARSER_REQUIRES_FUTURE_KEYWORD
+	unsigned long	p_flags;	/* see co_flags in Include/code.h */
+#endif
+} parser_state;
+
+parser_state *Ta35Parser_New(grammar *g, int start);
+void Ta35Parser_Delete(parser_state *ps);
+int Ta35Parser_AddToken(parser_state *ps, int type, char *str, int lineno, int col_offset,
+                      int *expected_ret);
+void Ta35Grammar_AddAccelerators(grammar *g);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* !Ta35_PARSER_H */
diff --git a/ast35/Parser/parsetok.c b/ast35/Parser/parsetok.c
new file mode 100644
index 0000000..252471d
--- /dev/null
+++ b/ast35/Parser/parsetok.c
@@ -0,0 +1,446 @@
+
+/* Parser-tokenizer link implementation */
+
+#include "pgenheaders.h"
+#include "tokenizer.h"
+#include "node.h"
+#include "grammar.h"
+#include "parser.h"
+#include "parsetok.h"
+#include "errcode.h"
+#include "graminit.h"
+
+
+/* Forward */
+static node *parsetok(struct tok_state *, grammar *, int, perrdetail *, int *);
+static int initerr(perrdetail *err_ret, PyObject * filename);
+
+/* Parse input coming from a string.  Return error code, print some errors. */
+node *
+Ta35Parser_ParseString(const char *s, grammar *g, int start, perrdetail *err_ret)
+{
+    return Ta35Parser_ParseStringFlagsFilename(s, NULL, g, start, err_ret, 0);
+}
+
+node *
+Ta35Parser_ParseStringFlags(const char *s, grammar *g, int start,
+                          perrdetail *err_ret, int flags)
+{
+    return Ta35Parser_ParseStringFlagsFilename(s, NULL,
+                                             g, start, err_ret, flags);
+}
+
+node *
+Ta35Parser_ParseStringFlagsFilename(const char *s, const char *filename,
+                          grammar *g, int start,
+                          perrdetail *err_ret, int flags)
+{
+    int iflags = flags;
+    return Ta35Parser_ParseStringFlagsFilenameEx(s, filename, g, start,
+                                               err_ret, &iflags);
+}
+
+node *
+Ta35Parser_ParseStringObject(const char *s, PyObject *filename,
+                           grammar *g, int start,
+                           perrdetail *err_ret, int *flags)
+{
+    struct tok_state *tok;
+    int exec_input = start == file_input;
+
+    if (initerr(err_ret, filename) < 0)
+        return NULL;
+
+    if (*flags & PyPARSE_IGNORE_COOKIE)
+        tok = Ta35Tokenizer_FromUTF8(s, exec_input);
+    else
+        tok = Ta35Tokenizer_FromString(s, exec_input);
+    if (tok == NULL) {
+        err_ret->error = PyErr_Occurred() ? E_DECODE : E_NOMEM;
+        return NULL;
+    }
+
+#ifndef PGEN
+    Py_INCREF(err_ret->filename);
+    tok->filename = err_ret->filename;
+#endif
+    return parsetok(tok, g, start, err_ret, flags);
+}
+
+node *
+Ta35Parser_ParseStringFlagsFilenameEx(const char *s, const char *filename_str,
+                          grammar *g, int start,
+                          perrdetail *err_ret, int *flags)
+{
+    node *n;
+    PyObject *filename = NULL;
+#ifndef PGEN
+    if (filename_str != NULL) {
+        filename = PyUnicode_DecodeFSDefault(filename_str);
+        if (filename == NULL) {
+            err_ret->error = E_ERROR;
+            return NULL;
+        }
+    }
+#endif
+    n = Ta35Parser_ParseStringObject(s, filename, g, start, err_ret, flags);
+#ifndef PGEN
+    Py_XDECREF(filename);
+#endif
+    return n;
+}
+
+/* Parse input coming from a file.  Return error code, print some errors. */
+
+node *
+Ta35Parser_ParseFile(FILE *fp, const char *filename, grammar *g, int start,
+                   const char *ps1, const char *ps2,
+                   perrdetail *err_ret)
+{
+    return Ta35Parser_ParseFileFlags(fp, filename, NULL,
+                                   g, start, ps1, ps2, err_ret, 0);
+}
+
+node *
+Ta35Parser_ParseFileFlags(FILE *fp, const char *filename, const char *enc,
+                        grammar *g, int start,
+                        const char *ps1, const char *ps2,
+                        perrdetail *err_ret, int flags)
+{
+    int iflags = flags;
+    return Ta35Parser_ParseFileFlagsEx(fp, filename, enc, g, start, ps1,
+                                     ps2, err_ret, &iflags);
+}
+
+node *
+Ta35Parser_ParseFileObject(FILE *fp, PyObject *filename,
+                         const char *enc, grammar *g, int start,
+                         const char *ps1, const char *ps2,
+                         perrdetail *err_ret, int *flags)
+{
+    struct tok_state *tok;
+
+    if (initerr(err_ret, filename) < 0)
+        return NULL;
+
+    if ((tok = Ta35Tokenizer_FromFile(fp, enc, ps1, ps2)) == NULL) {
+        err_ret->error = E_NOMEM;
+        return NULL;
+    }
+#ifndef PGEN
+    Py_INCREF(err_ret->filename);
+    tok->filename = err_ret->filename;
+#endif
+    return parsetok(tok, g, start, err_ret, flags);
+}
+
+node *
+Ta35Parser_ParseFileFlagsEx(FILE *fp, const char *filename,
+                          const char *enc, grammar *g, int start,
+                          const char *ps1, const char *ps2,
+                          perrdetail *err_ret, int *flags)
+{
+    node *n;
+    PyObject *fileobj = NULL;
+#ifndef PGEN
+    if (filename != NULL) {
+        fileobj = PyUnicode_DecodeFSDefault(filename);
+        if (fileobj == NULL) {
+            err_ret->error = E_ERROR;
+            return NULL;
+        }
+    }
+#endif
+    n = Ta35Parser_ParseFileObject(fp, fileobj, enc, g,
+                                 start, ps1, ps2, err_ret, flags);
+#ifndef PGEN
+    Py_XDECREF(fileobj);
+#endif
+    return n;
+}
+
+#ifdef PY_PARSER_REQUIRES_FUTURE_KEYWORD
+#if 0
+static char with_msg[] =
+"%s:%d: Warning: 'with' will become a reserved keyword in Python 2.6\n";
+
+static char as_msg[] =
+"%s:%d: Warning: 'as' will become a reserved keyword in Python 2.6\n";
+
+static void
+warn(const char *msg, const char *filename, int lineno)
+{
+    if (filename == NULL)
+        filename = "<string>";
+    PySys_WriteStderr(msg, filename, lineno);
+}
+#endif
+#endif
+
+typedef struct {
+    int *items;
+    size_t size;
+    size_t num_items;
+} growable_int_array;
+
+int growable_int_array_init(growable_int_array *arr, size_t initial_size) {
+    assert(initial_size > 0);
+    arr->items = malloc(initial_size * sizeof(*arr->items));
+    arr->size = initial_size;
+    arr->num_items = 0;
+
+    return arr->items != NULL;
+}
+
+int growable_int_array_add(growable_int_array *arr, int item) {
+    if (arr->num_items >= arr->size) {
+        arr->size *= 2;
+        arr->items = realloc(arr->items, arr->size * sizeof(*arr->items));
+        if (!arr->items)
+            return 0;
+    }
+
+    arr->items[arr->num_items] = item;
+    arr->num_items++;
+    return 1;
+}
+
+void growable_int_array_deallocate(growable_int_array *arr) {
+    free(arr->items);
+}
+
+/* Parse input coming from the given tokenizer structure.
+   Return error code. */
+
+static node *
+parsetok(struct tok_state *tok, grammar *g, int start, perrdetail *err_ret,
+         int *flags)
+{
+    parser_state *ps;
+    node *n;
+    int started = 0;
+
+    growable_int_array type_ignores;
+    if (!growable_int_array_init(&type_ignores, 10)) {
+        err_ret->error = E_NOMEM;
+        Ta35Tokenizer_Free(tok);
+        return NULL;
+    }
+
+    if ((ps = Ta35Parser_New(g, start)) == NULL) {
+        err_ret->error = E_NOMEM;
+        Ta35Tokenizer_Free(tok);
+        return NULL;
+    }
+#ifdef PY_PARSER_REQUIRES_FUTURE_KEYWORD
+    if (*flags & PyPARSE_BARRY_AS_BDFL)
+        ps->p_flags |= CO_FUTURE_BARRY_AS_BDFL;
+#endif
+
+    for (;;) {
+        char *a, *b;
+        int type;
+        size_t len;
+        char *str;
+        int col_offset;
+
+        type = Ta35Tokenizer_Get(tok, &a, &b);
+        if (type == ERRORTOKEN) {
+            err_ret->error = tok->done;
+            break;
+        }
+        if (type == ENDMARKER && started) {
+            type = NEWLINE; /* Add an extra newline */
+            started = 0;
+            /* Add the right number of dedent tokens,
+               except if a certain flag is given --
+               codeop.py uses this. */
+            if (tok->indent &&
+                !(*flags & PyPARSE_DONT_IMPLY_DEDENT))
+            {
+                tok->pendin = -tok->indent;
+                tok->indent = 0;
+            }
+        }
+        else
+            started = 1;
+        len = b - a; /* XXX this may compute NULL - NULL */
+        str = (char *) PyObject_MALLOC(len + 1);
+        if (str == NULL) {
+            err_ret->error = E_NOMEM;
+            break;
+        }
+        if (len > 0)
+            strncpy(str, a, len);
+        str[len] = '\0';
+
+#ifdef PY_PARSER_REQUIRES_FUTURE_KEYWORD
+        if (type == NOTEQUAL) {
+            if (!(ps->p_flags & CO_FUTURE_BARRY_AS_BDFL) &&
+                            strcmp(str, "!=")) {
+                PyObject_FREE(str);
+                err_ret->error = E_SYNTAX;
+                break;
+            }
+            else if ((ps->p_flags & CO_FUTURE_BARRY_AS_BDFL) &&
+                            strcmp(str, "<>")) {
+                PyObject_FREE(str);
+                err_ret->text = "with Barry as BDFL, use '<>' "
+                                "instead of '!='";
+                err_ret->error = E_SYNTAX;
+                break;
+            }
+        }
+#endif
+        if (a >= tok->line_start)
+            col_offset = Py_SAFE_DOWNCAST(a - tok->line_start,
+                                          Py_intptr_t, int);
+        else
+            col_offset = -1;
+
+        if (type == TYPE_IGNORE) {
+            if (!growable_int_array_add(&type_ignores, tok->lineno)) {
+                err_ret->error = E_NOMEM;
+                break;
+            }
+            continue;
+        }
+
+        if ((err_ret->error =
+             Ta35Parser_AddToken(ps, (int)type, str,
+                               tok->lineno, col_offset,
+                               &(err_ret->expected))) != E_OK) {
+            if (err_ret->error != E_DONE) {
+                PyObject_FREE(str);
+                err_ret->token = type;
+            }
+            break;
+        }
+    }
+
+    if (err_ret->error == E_DONE) {
+        n = ps->p_tree;
+        ps->p_tree = NULL;
+
+        if (n->n_type == file_input) {
+            /* Put type_ignore nodes in the ENDMARKER of file_input. */
+            int num;
+            node *ch;
+            size_t i;
+
+            num = NCH(n);
+            ch = CHILD(n, num - 1);
+            REQ(ch, ENDMARKER);
+
+            for (i = 0; i < type_ignores.num_items; i++) {
+                Ta35Node_AddChild(ch, TYPE_IGNORE, NULL, type_ignores.items[i], 0);
+            }
+        }
+        growable_int_array_deallocate(&type_ignores);
+
+#ifndef PGEN
+        /* Check that the source for a single input statement really
+           is a single statement by looking at what is left in the
+           buffer after parsing.  Trailing whitespace and comments
+           are OK.  */
+        if (start == single_input) {
+            char *cur = tok->cur;
+            char c = *tok->cur;
+
+            for (;;) {
+                while (c == ' ' || c == '\t' || c == '\n' || c == '\014')
+                    c = *++cur;
+
+                if (!c)
+                    break;
+
+                if (c != '#') {
+                    err_ret->error = E_BADSINGLE;
+                    Ta35Node_Free(n);
+                    n = NULL;
+                    break;
+                }
+
+                /* Suck up comment. */
+                while (c && c != '\n')
+                    c = *++cur;
+            }
+        }
+#endif
+    }
+    else
+        n = NULL;
+
+#ifdef PY_PARSER_REQUIRES_FUTURE_KEYWORD
+    *flags = ps->p_flags;
+#endif
+    Ta35Parser_Delete(ps);
+
+    if (n == NULL) {
+        if (tok->done == E_EOF)
+            err_ret->error = E_EOF;
+        err_ret->lineno = tok->lineno;
+        if (tok->buf != NULL) {
+            size_t len;
+            assert(tok->cur - tok->buf < INT_MAX);
+            err_ret->offset = (int)(tok->cur - tok->buf);
+            len = tok->inp - tok->buf;
+            err_ret->text = (char *) PyObject_MALLOC(len + 1);
+            if (err_ret->text != NULL) {
+                if (len > 0)
+                    strncpy(err_ret->text, tok->buf, len);
+                err_ret->text[len] = '\0';
+            }
+        }
+    } else if (tok->encoding != NULL) {
+        /* 'nodes->n_str' uses PyObject_*, while 'tok->encoding' was
+         * allocated using PyMem_
+         */
+        node* r = Ta35Node_New(encoding_decl);
+        if (r)
+            r->n_str = PyObject_MALLOC(strlen(tok->encoding)+1);
+        if (!r || !r->n_str) {
+            err_ret->error = E_NOMEM;
+            if (r)
+                PyObject_FREE(r);
+            n = NULL;
+            goto done;
+        }
+        strcpy(r->n_str, tok->encoding);
+        PyMem_FREE(tok->encoding);
+        tok->encoding = NULL;
+        r->n_nchildren = 1;
+        r->n_child = n;
+        n = r;
+    }
+
+done:
+    Ta35Tokenizer_Free(tok);
+
+    return n;
+}
+
+static int
+initerr(perrdetail *err_ret, PyObject *filename)
+{
+    err_ret->error = E_OK;
+    err_ret->lineno = 0;
+    err_ret->offset = 0;
+    err_ret->text = NULL;
+    err_ret->token = -1;
+    err_ret->expected = -1;
+#ifndef PGEN
+    if (filename) {
+        Py_INCREF(filename);
+        err_ret->filename = filename;
+    }
+    else {
+        err_ret->filename = PyUnicode_FromString("<string>");
+        if (err_ret->filename == NULL) {
+            err_ret->error = E_ERROR;
+            return -1;
+        }
+    }
+#endif
+    return 0;
+}
diff --git a/ast35/Parser/tokenizer.c b/ast35/Parser/tokenizer.c
new file mode 100644
index 0000000..a23546e
--- /dev/null
+++ b/ast35/Parser/tokenizer.c
@@ -0,0 +1,1952 @@
+
+/* Tokenizer implementation */
+
+#include "Python.h"
+#include "pgenheaders.h"
+
+#include <ctype.h>
+#include <assert.h>
+
+#include "tokenizer.h"
+#include "errcode.h"
+
+#ifndef PGEN
+#include "unicodeobject.h"
+#include "bytesobject.h"
+#include "fileobject.h"
+#include "codecs.h"
+#include "abstract.h"
+#endif /* PGEN */
+
+#define is_potential_identifier_start(c) (\
+              (c >= 'a' && c <= 'z')\
+               || (c >= 'A' && c <= 'Z')\
+               || c == '_'\
+               || (c >= 128))
+
+#define is_potential_identifier_char(c) (\
+              (c >= 'a' && c <= 'z')\
+               || (c >= 'A' && c <= 'Z')\
+               || (c >= '0' && c <= '9')\
+               || c == '_'\
+               || (c >= 128))
+
+#if PY_MINOR_VERSION >= 4
+extern char *PyOS_Readline(FILE *, FILE *, const char *);
+#else
+extern char *PyOS_Readline(FILE *, FILE *, char *);
+#endif
+/* Return malloc'ed string including trailing \n;
+   empty malloc'ed string for EOF;
+   NULL if interrupted */
+
+/* Don't ever change this -- it would break the portability of Python code */
+#define TABSIZE 8
+
+/* Forward */
+static struct tok_state *tok_new(void);
+static int tok_nextc(struct tok_state *tok);
+static void tok_backup(struct tok_state *tok, int c);
+
+
+/* Token names */
+
+const char *_Ta35Parser_TokenNames[] = {
+    "ENDMARKER",
+    "NAME",
+    "NUMBER",
+    "STRING",
+    "NEWLINE",
+    "INDENT",
+    "DEDENT",
+    "LPAR",
+    "RPAR",
+    "LSQB",
+    "RSQB",
+    "COLON",
+    "COMMA",
+    "SEMI",
+    "PLUS",
+    "MINUS",
+    "STAR",
+    "SLASH",
+    "VBAR",
+    "AMPER",
+    "LESS",
+    "GREATER",
+    "EQUAL",
+    "DOT",
+    "PERCENT",
+    "LBRACE",
+    "RBRACE",
+    "EQEQUAL",
+    "NOTEQUAL",
+    "LESSEQUAL",
+    "GREATEREQUAL",
+    "TILDE",
+    "CIRCUMFLEX",
+    "LEFTSHIFT",
+    "RIGHTSHIFT",
+    "DOUBLESTAR",
+    "PLUSEQUAL",
+    "MINEQUAL",
+    "STAREQUAL",
+    "SLASHEQUAL",
+    "PERCENTEQUAL",
+    "AMPEREQUAL",
+    "VBAREQUAL",
+    "CIRCUMFLEXEQUAL",
+    "LEFTSHIFTEQUAL",
+    "RIGHTSHIFTEQUAL",
+    "DOUBLESTAREQUAL",
+    "DOUBLESLASH",
+    "DOUBLESLASHEQUAL",
+    "AT",
+    "ATEQUAL",
+    "RARROW",
+    "ELLIPSIS",
+    /* This table must match the #defines in token.h! */
+    "OP",
+    "AWAIT",
+    "ASYNC",
+    "TYPE_IGNORE",
+    "TYPE_COMMENT",
+    "<ERRORTOKEN>",
+    "<N_TOKENS>"
+};
+
+/* Spaces in this constant are treated as "zero or more spaces or tabs" when
+   tokenizing. */
+static const char* type_comment_prefix = "# type: ";
+
+
+/* Create and initialize a new tok_state structure */
+
+static struct tok_state *
+tok_new(void)
+{
+    struct tok_state *tok = (struct tok_state *)PyMem_MALLOC(
+                                            sizeof(struct tok_state));
+    if (tok == NULL)
+        return NULL;
+    tok->buf = tok->cur = tok->end = tok->inp = tok->start = NULL;
+    tok->done = E_OK;
+    tok->fp = NULL;
+    tok->input = NULL;
+    tok->tabsize = TABSIZE;
+    tok->indent = 0;
+    tok->indstack[0] = 0;
+
+    tok->atbol = 1;
+    tok->pendin = 0;
+    tok->prompt = tok->nextprompt = NULL;
+    tok->lineno = 0;
+    tok->level = 0;
+    tok->altwarning = 1;
+    tok->alterror = 1;
+    tok->alttabsize = 1;
+    tok->altindstack[0] = 0;
+    tok->decoding_state = STATE_INIT;
+    tok->decoding_erred = 0;
+    tok->read_coding_spec = 0;
+    tok->enc = NULL;
+    tok->encoding = NULL;
+    tok->cont_line = 0;
+#ifndef PGEN
+    tok->filename = NULL;
+    tok->decoding_readline = NULL;
+    tok->decoding_buffer = NULL;
+#endif
+
+    tok->async_def = 0;
+    tok->async_def_indent = 0;
+    tok->async_def_nl = 0;
+
+    return tok;
+}
+
+static char *
+new_string(const char *s, Py_ssize_t len, struct tok_state *tok)
+{
+    char* result = (char *)PyMem_MALLOC(len + 1);
+    if (!result) {
+        tok->done = E_NOMEM;
+        return NULL;
+    }
+    memcpy(result, s, len);
+    result[len] = '\0';
+    return result;
+}
+
+#ifdef PGEN
+
+static char *
+decoding_fgets(char *s, int size, struct tok_state *tok)
+{
+    return fgets(s, size, tok->fp);
+}
+
+static int
+decoding_feof(struct tok_state *tok)
+{
+    return feof(tok->fp);
+}
+
+static char *
+decode_str(const char *str, int exec_input, struct tok_state *tok)
+{
+    return new_string(str, strlen(str), tok);
+}
+
+#else /* PGEN */
+
+static char *
+error_ret(struct tok_state *tok) /* XXX */
+{
+    tok->decoding_erred = 1;
+    if (tok->fp != NULL && tok->buf != NULL) /* see Ta35Tokenizer_Free */
+        PyMem_FREE(tok->buf);
+    tok->buf = tok->cur = tok->end = tok->inp = tok->start = NULL;
+    tok->done = E_DECODE;
+    return NULL;                /* as if it were EOF */
+}
+
+
+static char *
+get_normal_name(char *s)        /* for utf-8 and latin-1 */
+{
+    char buf[13];
+    int i;
+    for (i = 0; i < 12; i++) {
+        int c = s[i];
+        if (c == '\0')
+            break;
+        else if (c == '_')
+            buf[i] = '-';
+        else
+            buf[i] = tolower(c);
+    }
+    buf[i] = '\0';
+    if (strcmp(buf, "utf-8") == 0 ||
+        strncmp(buf, "utf-8-", 6) == 0)
+        return "utf-8";
+    else if (strcmp(buf, "latin-1") == 0 ||
+             strcmp(buf, "iso-8859-1") == 0 ||
+             strcmp(buf, "iso-latin-1") == 0 ||
+             strncmp(buf, "latin-1-", 8) == 0 ||
+             strncmp(buf, "iso-8859-1-", 11) == 0 ||
+             strncmp(buf, "iso-latin-1-", 12) == 0)
+        return "iso-8859-1";
+    else
+        return s;
+}
+
+/* Return the coding spec in S, or NULL if none is found.  */
+
+static int
+get_coding_spec(const char *s, char **spec, Py_ssize_t size, struct tok_state *tok)
+{
+    Py_ssize_t i;
+    *spec = NULL;
+    /* Coding spec must be in a comment, and that comment must be
+     * the only statement on the source code line. */
+    for (i = 0; i < size - 6; i++) {
+        if (s[i] == '#')
+            break;
+        if (s[i] != ' ' && s[i] != '\t' && s[i] != '\014')
+            return 1;
+    }
+    for (; i < size - 6; i++) { /* XXX inefficient search */
+        const char* t = s + i;
+        if (strncmp(t, "coding", 6) == 0) {
+            const char* begin = NULL;
+            t += 6;
+            if (t[0] != ':' && t[0] != '=')
+                continue;
+            do {
+                t++;
+            } while (t[0] == '\x20' || t[0] == '\t');
+
+            begin = t;
+            while (Py_ISALNUM(t[0]) ||
+                   t[0] == '-' || t[0] == '_' || t[0] == '.')
+                t++;
+
+            if (begin < t) {
+                char* r = new_string(begin, t - begin, tok);
+                char* q;
+                if (!r)
+                    return 0;
+                q = get_normal_name(r);
+                if (r != q) {
+                    PyMem_FREE(r);
+                    r = new_string(q, strlen(q), tok);
+                    if (!r)
+                        return 0;
+                }
+                *spec = r;
+            }
+        }
+    }
+    return 1;
+}
+
+/* Check whether the line contains a coding spec. If it does,
+   invoke the set_readline function for the new encoding.
+   This function receives the tok_state and the new encoding.
+   Return 1 on success, 0 on failure.  */
+
+static int
+check_coding_spec(const char* line, Py_ssize_t size, struct tok_state *tok,
+                  int set_readline(struct tok_state *, const char *))
+{
+    char *cs;
+    int r = 1;
+
+    if (tok->cont_line) {
+        /* It's a continuation line, so it can't be a coding spec. */
+        tok->read_coding_spec = 1;
+        return 1;
+    }
+    if (!get_coding_spec(line, &cs, size, tok))
+        return 0;
+    if (!cs) {
+        Py_ssize_t i;
+        for (i = 0; i < size; i++) {
+            if (line[i] == '#' || line[i] == '\n' || line[i] == '\r')
+                break;
+            if (line[i] != ' ' && line[i] != '\t' && line[i] != '\014') {
+                /* Stop checking coding spec after a line containing
+                 * anything except a comment. */
+                tok->read_coding_spec = 1;
+                break;
+            }
+        }
+        return 1;
+    }
+    tok->read_coding_spec = 1;
+    if (tok->encoding == NULL) {
+        assert(tok->decoding_state == STATE_RAW);
+        if (strcmp(cs, "utf-8") == 0) {
+            tok->encoding = cs;
+        } else {
+            r = set_readline(tok, cs);
+            if (r) {
+                tok->encoding = cs;
+                tok->decoding_state = STATE_NORMAL;
+            }
+            else {
+                PyErr_Format(PyExc_SyntaxError,
+                             "encoding problem: %s", cs);
+                PyMem_FREE(cs);
+            }
+        }
+    } else {                /* then, compare cs with BOM */
+        r = (strcmp(tok->encoding, cs) == 0);
+        if (!r)
+            PyErr_Format(PyExc_SyntaxError,
+                         "encoding problem: %s with BOM", cs);
+        PyMem_FREE(cs);
+    }
+    return r;
+}
+
+/* See whether the file starts with a BOM. If it does,
+   invoke the set_readline function with the new encoding.
+   Return 1 on success, 0 on failure.  */
+
+static int
+check_bom(int get_char(struct tok_state *),
+          void unget_char(int, struct tok_state *),
+          int set_readline(struct tok_state *, const char *),
+          struct tok_state *tok)
+{
+    int ch1, ch2, ch3;
+    ch1 = get_char(tok);
+    tok->decoding_state = STATE_RAW;
+    if (ch1 == EOF) {
+        return 1;
+    } else if (ch1 == 0xEF) {
+        ch2 = get_char(tok);
+        if (ch2 != 0xBB) {
+            unget_char(ch2, tok);
+            unget_char(ch1, tok);
+            return 1;
+        }
+        ch3 = get_char(tok);
+        if (ch3 != 0xBF) {
+            unget_char(ch3, tok);
+            unget_char(ch2, tok);
+            unget_char(ch1, tok);
+            return 1;
+        }
+#if 0
+    /* Disable support for UTF-16 BOMs until a decision
+       is made whether this needs to be supported.  */
+    } else if (ch1 == 0xFE) {
+        ch2 = get_char(tok);
+        if (ch2 != 0xFF) {
+            unget_char(ch2, tok);
+            unget_char(ch1, tok);
+            return 1;
+        }
+        if (!set_readline(tok, "utf-16-be"))
+            return 0;
+        tok->decoding_state = STATE_NORMAL;
+    } else if (ch1 == 0xFF) {
+        ch2 = get_char(tok);
+        if (ch2 != 0xFE) {
+            unget_char(ch2, tok);
+            unget_char(ch1, tok);
+            return 1;
+        }
+        if (!set_readline(tok, "utf-16-le"))
+            return 0;
+        tok->decoding_state = STATE_NORMAL;
+#endif
+    } else {
+        unget_char(ch1, tok);
+        return 1;
+    }
+    if (tok->encoding != NULL)
+        PyMem_FREE(tok->encoding);
+    tok->encoding = new_string("utf-8", 5, tok);
+    if (!tok->encoding)
+        return 0;
+    /* No need to set_readline: input is already utf-8 */
+    return 1;
+}
+
+/* Read a line of text from TOK into S, using the stream in TOK.
+   Return NULL on failure, else S.
+
+   On entry, tok->decoding_buffer will be one of:
+     1) NULL: need to call tok->decoding_readline to get a new line
+     2) PyUnicodeObject *: decoding_feof has called tok->decoding_readline and
+       stored the result in tok->decoding_buffer
+     3) PyByteArrayObject *: previous call to fp_readl did not have enough room
+       (in the s buffer) to copy entire contents of the line read
+       by tok->decoding_readline.  tok->decoding_buffer has the overflow.
+       In this case, fp_readl is called in a loop (with an expanded buffer)
+       until the buffer ends with a '\n' (or until the end of the file is
+       reached): see tok_nextc and its calls to decoding_fgets.
+*/
+
+static char *
+fp_readl(char *s, int size, struct tok_state *tok)
+{
+    PyObject* bufobj;
+    const char *buf;
+    Py_ssize_t buflen;
+
+    /* Ask for one less byte so we can terminate it */
+    assert(size > 0);
+    size--;
+
+    if (tok->decoding_buffer) {
+        bufobj = tok->decoding_buffer;
+        Py_INCREF(bufobj);
+    }
+    else
+    {
+        bufobj = PyObject_CallObject(tok->decoding_readline, NULL);
+        if (bufobj == NULL)
+            goto error;
+    }
+    if (PyUnicode_CheckExact(bufobj))
+    {
+        buf = _PyUnicode_AsStringAndSize(bufobj, &buflen);
+        if (buf == NULL) {
+            goto error;
+        }
+    }
+    else
+    {
+        buf = PyByteArray_AsString(bufobj);
+        if (buf == NULL) {
+            goto error;
+        }
+        buflen = PyByteArray_GET_SIZE(bufobj);
+    }
+
+    Py_XDECREF(tok->decoding_buffer);
+    if (buflen > size) {
+        /* Too many chars, the rest goes into tok->decoding_buffer */
+        tok->decoding_buffer = PyByteArray_FromStringAndSize(buf+size,
+                                                         buflen-size);
+        if (tok->decoding_buffer == NULL)
+            goto error;
+        buflen = size;
+    }
+    else
+        tok->decoding_buffer = NULL;
+
+    memcpy(s, buf, buflen);
+    s[buflen] = '\0';
+    if (buflen == 0) /* EOF */
+        s = NULL;
+    Py_DECREF(bufobj);
+    return s;
+
+error:
+    Py_XDECREF(bufobj);
+    return error_ret(tok);
+}
+
+/* Set the readline function for TOK to a StreamReader's
+   readline function. The StreamReader is named ENC.
+
+   This function is called from check_bom and check_coding_spec.
+
+   ENC is usually identical to the future value of tok->encoding,
+   except for the (currently unsupported) case of UTF-16.
+
+   Return 1 on success, 0 on failure. */
+
+static int
+fp_setreadl(struct tok_state *tok, const char* enc)
+{
+    PyObject *readline = NULL, *stream = NULL, *io = NULL;
+    _Py_IDENTIFIER(open);
+    _Py_IDENTIFIER(readline);
+    int fd;
+    long pos;
+
+    io = PyImport_ImportModuleNoBlock("io");
+    if (io == NULL)
+        goto cleanup;
+
+    fd = fileno(tok->fp);
+    /* Due to buffering the file offset for fd can be different from the file
+     * position of tok->fp.  If tok->fp was opened in text mode on Windows,
+     * its file position counts CRLF as one char and can't be directly mapped
+     * to the file offset for fd.  Instead we step back one byte and read to
+     * the end of line.*/
+    pos = ftell(tok->fp);
+    if (pos == -1 ||
+        lseek(fd, (off_t)(pos > 0 ? pos - 1 : pos), SEEK_SET) == (off_t)-1) {
+        PyErr_SetFromErrnoWithFilename(PyExc_OSError, NULL);
+        goto cleanup;
+    }
+
+    stream = _PyObject_CallMethodId(io, &PyId_open, "isisOOO",
+                    fd, "r", -1, enc, Py_None, Py_None, Py_False);
+    if (stream == NULL)
+        goto cleanup;
+
+    Py_XDECREF(tok->decoding_readline);
+    readline = _PyObject_GetAttrId(stream, &PyId_readline);
+    tok->decoding_readline = readline;
+    if (pos > 0) {
+        if (PyObject_CallObject(readline, NULL) == NULL) {
+            readline = NULL;
+            goto cleanup;
+        }
+    }
+
+  cleanup:
+    Py_XDECREF(stream);
+    Py_XDECREF(io);
+    return readline != NULL;
+}
+
+/* Fetch the next byte from TOK. */
+
+static int fp_getc(struct tok_state *tok) {
+    return getc(tok->fp);
+}
+
+/* Unfetch the last byte back into TOK.  */
+
+static void fp_ungetc(int c, struct tok_state *tok) {
+    ungetc(c, tok->fp);
+}
+
+/* Check whether the characters at s start a valid
+   UTF-8 sequence. Return the number of characters forming
+   the sequence if yes, 0 if not.  */
+static int valid_utf8(const unsigned char* s)
+{
+    int expected = 0;
+    int length;
+    if (*s < 0x80)
+        /* single-byte code */
+        return 1;
+    if (*s < 0xc0)
+        /* following byte */
+        return 0;
+    if (*s < 0xE0)
+        expected = 1;
+    else if (*s < 0xF0)
+        expected = 2;
+    else if (*s < 0xF8)
+        expected = 3;
+    else
+        return 0;
+    length = expected + 1;
+    for (; expected; expected--)
+        if (s[expected] < 0x80 || s[expected] >= 0xC0)
+            return 0;
+    return length;
+}
+
+/* Read a line of input from TOK. Determine encoding
+   if necessary.  */
+
+static char *
+decoding_fgets(char *s, int size, struct tok_state *tok)
+{
+    char *line = NULL;
+    int badchar = 0;
+    for (;;) {
+        if (tok->decoding_state == STATE_NORMAL) {
+            /* We already have a codec associated with
+               this input. */
+            line = fp_readl(s, size, tok);
+            break;
+        } else if (tok->decoding_state == STATE_RAW) {
+            /* We want a 'raw' read. */
+            line = Py_UniversalNewlineFgets(s, size,
+                                            tok->fp, NULL);
+            break;
+        } else {
+            /* We have not yet determined the encoding.
+               If an encoding is found, use the file-pointer
+               reader functions from now on. */
+            if (!check_bom(fp_getc, fp_ungetc, fp_setreadl, tok))
+                return error_ret(tok);
+            assert(tok->decoding_state != STATE_INIT);
+        }
+    }
+    if (line != NULL && tok->lineno < 2 && !tok->read_coding_spec) {
+        if (!check_coding_spec(line, strlen(line), tok, fp_setreadl)) {
+            return error_ret(tok);
+        }
+    }
+#ifndef PGEN
+    /* The default encoding is UTF-8, so make sure we don't have any
+       non-UTF-8 sequences in it. */
+    if (line && !tok->encoding) {
+        unsigned char *c;
+        int length;
+        for (c = (unsigned char *)line; *c; c += length)
+            if (!(length = valid_utf8(c))) {
+                badchar = *c;
+                break;
+            }
+    }
+    if (badchar) {
+        /* Need to add 1 to the line number, since this line
+           has not been counted, yet.  */
+        PyErr_Format(PyExc_SyntaxError,
+                "Non-UTF-8 code starting with '\\x%.2x' "
+                "in file %U on line %i, "
+                "but no encoding declared; "
+                "see http://python.org/dev/peps/pep-0263/ for details",
+                badchar, tok->filename, tok->lineno + 1);
+        return error_ret(tok);
+    }
+#endif
+    return line;
+}
+
+static int
+decoding_feof(struct tok_state *tok)
+{
+    if (tok->decoding_state != STATE_NORMAL) {
+        return feof(tok->fp);
+    } else {
+        PyObject* buf = tok->decoding_buffer;
+        if (buf == NULL) {
+            buf = PyObject_CallObject(tok->decoding_readline, NULL);
+            if (buf == NULL) {
+                error_ret(tok);
+                return 1;
+            } else {
+                tok->decoding_buffer = buf;
+            }
+        }
+        return PyObject_Length(buf) == 0;
+    }
+}
+
+/* Fetch a byte from TOK, using the string buffer. */
+
+static int
+buf_getc(struct tok_state *tok) {
+    return Py_CHARMASK(*tok->str++);
+}
+
+/* Unfetch a byte from TOK, using the string buffer. */
+
+static void
+buf_ungetc(int c, struct tok_state *tok) {
+    tok->str--;
+    assert(Py_CHARMASK(*tok->str) == c);        /* tok->cur may point to read-only segment */
+}
+
+/* Set the readline function for TOK to ENC. For the string-based
+   tokenizer, this means to just record the encoding. */
+
+static int
+buf_setreadl(struct tok_state *tok, const char* enc) {
+    tok->enc = enc;
+    return 1;
+}
+
+/* Return a UTF-8 encoding Python string object from the
+   C byte string STR, which is encoded with ENC. */
+
+static PyObject *
+translate_into_utf8(const char* str, const char* enc) {
+    PyObject *utf8;
+    PyObject* buf = PyUnicode_Decode(str, strlen(str), enc, NULL);
+    if (buf == NULL)
+        return NULL;
+    utf8 = PyUnicode_AsUTF8String(buf);
+    Py_DECREF(buf);
+    return utf8;
+}
+
+
+static char *
+translate_newlines(const char *s, int exec_input, struct tok_state *tok) {
+    int skip_next_lf = 0;
+    size_t needed_length = strlen(s) + 2, final_length;
+    char *buf, *current;
+    char c = '\0';
+    buf = PyMem_MALLOC(needed_length);
+    if (buf == NULL) {
+        tok->done = E_NOMEM;
+        return NULL;
+    }
+    for (current = buf; *s; s++, current++) {
+        c = *s;
+        if (skip_next_lf) {
+            skip_next_lf = 0;
+            if (c == '\n') {
+                c = *++s;
+                if (!c)
+                    break;
+            }
+        }
+        if (c == '\r') {
+            skip_next_lf = 1;
+            c = '\n';
+        }
+        *current = c;
+    }
+    /* If this is exec input, add a newline to the end of the string if
+       there isn't one already. */
+    if (exec_input && c != '\n') {
+        *current = '\n';
+        current++;
+    }
+    *current = '\0';
+    final_length = current - buf + 1;
+    if (final_length < needed_length && final_length)
+        /* should never fail */
+        buf = PyMem_REALLOC(buf, final_length);
+    return buf;
+}
+
+/* Decode a byte string STR for use as the buffer of TOK.
+   Look for encoding declarations inside STR, and record them
+   inside TOK.  */
+
+static const char *
+decode_str(const char *input, int single, struct tok_state *tok)
+{
+    PyObject* utf8 = NULL;
+    const char *str;
+    const char *s;
+    const char *newl[2] = {NULL, NULL};
+    int lineno = 0;
+    tok->input = str = translate_newlines(input, single, tok);
+    if (str == NULL)
+        return NULL;
+    tok->enc = NULL;
+    tok->str = str;
+    if (!check_bom(buf_getc, buf_ungetc, buf_setreadl, tok))
+        return error_ret(tok);
+    str = tok->str;             /* string after BOM if any */
+    assert(str);
+    if (tok->enc != NULL) {
+        utf8 = translate_into_utf8(str, tok->enc);
+        if (utf8 == NULL)
+            return error_ret(tok);
+        str = PyBytes_AsString(utf8);
+    }
+    for (s = str;; s++) {
+        if (*s == '\0') break;
+        else if (*s == '\n') {
+            assert(lineno < 2);
+            newl[lineno] = s;
+            lineno++;
+            if (lineno == 2) break;
+        }
+    }
+    tok->enc = NULL;
+    /* need to check line 1 and 2 separately since check_coding_spec
+       assumes a single line as input */
+    if (newl[0]) {
+        if (!check_coding_spec(str, newl[0] - str, tok, buf_setreadl))
+            return error_ret(tok);
+        if (tok->enc == NULL && !tok->read_coding_spec && newl[1]) {
+            if (!check_coding_spec(newl[0]+1, newl[1] - newl[0],
+                                   tok, buf_setreadl))
+                return error_ret(tok);
+        }
+    }
+    if (tok->enc != NULL) {
+        assert(utf8 == NULL);
+        utf8 = translate_into_utf8(str, tok->enc);
+        if (utf8 == NULL)
+            return error_ret(tok);
+        str = PyBytes_AS_STRING(utf8);
+    }
+    assert(tok->decoding_buffer == NULL);
+    tok->decoding_buffer = utf8; /* CAUTION */
+    return str;
+}
+
+#endif /* PGEN */
+
+/* Set up tokenizer for string */
+
+struct tok_state *
+Ta35Tokenizer_FromString(const char *str, int exec_input)
+{
+    struct tok_state *tok = tok_new();
+    if (tok == NULL)
+        return NULL;
+    str = decode_str(str, exec_input, tok);
+    if (str == NULL) {
+        Ta35Tokenizer_Free(tok);
+        return NULL;
+    }
+
+    /* XXX: constify members. */
+    tok->buf = tok->cur = tok->end = tok->inp = (char*)str;
+    return tok;
+}
+
+struct tok_state *
+Ta35Tokenizer_FromUTF8(const char *str, int exec_input)
+{
+    struct tok_state *tok = tok_new();
+    if (tok == NULL)
+        return NULL;
+#ifndef PGEN
+    tok->input = str = translate_newlines(str, exec_input, tok);
+#endif
+    if (str == NULL) {
+        Ta35Tokenizer_Free(tok);
+        return NULL;
+    }
+    tok->decoding_state = STATE_RAW;
+    tok->read_coding_spec = 1;
+    tok->enc = NULL;
+    tok->str = str;
+    tok->encoding = (char *)PyMem_MALLOC(6);
+    if (!tok->encoding) {
+        Ta35Tokenizer_Free(tok);
+        return NULL;
+    }
+    strcpy(tok->encoding, "utf-8");
+
+    /* XXX: constify members. */
+    tok->buf = tok->cur = tok->end = tok->inp = (char*)str;
+    return tok;
+}
+
+/* Set up tokenizer for file */
+
+struct tok_state *
+Ta35Tokenizer_FromFile(FILE *fp, const char* enc,
+                     const char *ps1, const char *ps2)
+{
+    struct tok_state *tok = tok_new();
+    if (tok == NULL)
+        return NULL;
+    if ((tok->buf = (char *)PyMem_MALLOC(BUFSIZ)) == NULL) {
+        Ta35Tokenizer_Free(tok);
+        return NULL;
+    }
+    tok->cur = tok->inp = tok->buf;
+    tok->end = tok->buf + BUFSIZ;
+    tok->fp = fp;
+    tok->prompt = ps1;
+    tok->nextprompt = ps2;
+    if (enc != NULL) {
+        /* Must copy encoding declaration since it
+           gets copied into the parse tree. */
+        tok->encoding = PyMem_MALLOC(strlen(enc)+1);
+        if (!tok->encoding) {
+            Ta35Tokenizer_Free(tok);
+            return NULL;
+        }
+        strcpy(tok->encoding, enc);
+        tok->decoding_state = STATE_NORMAL;
+    }
+    return tok;
+}
+
+
+/* Free a tok_state structure */
+
+void
+Ta35Tokenizer_Free(struct tok_state *tok)
+{
+    if (tok->encoding != NULL)
+        PyMem_FREE(tok->encoding);
+#ifndef PGEN
+    Py_XDECREF(tok->decoding_readline);
+    Py_XDECREF(tok->decoding_buffer);
+    Py_XDECREF(tok->filename);
+#endif
+    if (tok->fp != NULL && tok->buf != NULL)
+        PyMem_FREE(tok->buf);
+    if (tok->input)
+        PyMem_FREE((char *)tok->input);
+    PyMem_FREE(tok);
+}
+
+/* Get next char, updating state; error code goes into tok->done */
+
+static int
+tok_nextc(struct tok_state *tok)
+{
+    for (;;) {
+        if (tok->cur != tok->inp) {
+            return Py_CHARMASK(*tok->cur++); /* Fast path */
+        }
+        if (tok->done != E_OK)
+            return EOF;
+        if (tok->fp == NULL) {
+            char *end = strchr(tok->inp, '\n');
+            if (end != NULL)
+                end++;
+            else {
+                end = strchr(tok->inp, '\0');
+                if (end == tok->inp) {
+                    tok->done = E_EOF;
+                    return EOF;
+                }
+            }
+            if (tok->start == NULL)
+                tok->buf = tok->cur;
+            tok->line_start = tok->cur;
+            tok->lineno++;
+            tok->inp = end;
+            return Py_CHARMASK(*tok->cur++);
+        }
+        if (tok->prompt != NULL) {
+            char *newtok = PyOS_Readline(stdin, stdout, tok->prompt);
+#ifndef PGEN
+            if (newtok != NULL) {
+                char *translated = translate_newlines(newtok, 0, tok);
+                PyMem_FREE(newtok);
+                if (translated == NULL)
+                    return EOF;
+                newtok = translated;
+            }
+            if (tok->encoding && newtok && *newtok) {
+                /* Recode to UTF-8 */
+                Py_ssize_t buflen;
+                const char* buf;
+                PyObject *u = translate_into_utf8(newtok, tok->encoding);
+                PyMem_FREE(newtok);
+                if (!u) {
+                    tok->done = E_DECODE;
+                    return EOF;
+                }
+                buflen = PyBytes_GET_SIZE(u);
+                buf = PyBytes_AS_STRING(u);
+                newtok = PyMem_MALLOC(buflen+1);
+                strcpy(newtok, buf);
+                Py_DECREF(u);
+            }
+#endif
+            if (tok->nextprompt != NULL)
+                tok->prompt = tok->nextprompt;
+            if (newtok == NULL)
+                tok->done = E_INTR;
+            else if (*newtok == '\0') {
+                PyMem_FREE(newtok);
+                tok->done = E_EOF;
+            }
+            else if (tok->start != NULL) {
+                size_t start = tok->start - tok->buf;
+                size_t oldlen = tok->cur - tok->buf;
+                size_t newlen = oldlen + strlen(newtok);
+                char *buf = tok->buf;
+                buf = (char *)PyMem_REALLOC(buf, newlen+1);
+                tok->lineno++;
+                if (buf == NULL) {
+                    PyMem_FREE(tok->buf);
+                    tok->buf = NULL;
+                    PyMem_FREE(newtok);
+                    tok->done = E_NOMEM;
+                    return EOF;
+                }
+                tok->buf = buf;
+                tok->cur = tok->buf + oldlen;
+                tok->line_start = tok->cur;
+                strcpy(tok->buf + oldlen, newtok);
+                PyMem_FREE(newtok);
+                tok->inp = tok->buf + newlen;
+                tok->end = tok->inp + 1;
+                tok->start = tok->buf + start;
+            }
+            else {
+                tok->lineno++;
+                if (tok->buf != NULL)
+                    PyMem_FREE(tok->buf);
+                tok->buf = newtok;
+                tok->cur = tok->buf;
+                tok->line_start = tok->buf;
+                tok->inp = strchr(tok->buf, '\0');
+                tok->end = tok->inp + 1;
+            }
+        }
+        else {
+            int done = 0;
+            Py_ssize_t cur = 0;
+            char *pt;
+            if (tok->start == NULL) {
+                if (tok->buf == NULL) {
+                    tok->buf = (char *)
+                        PyMem_MALLOC(BUFSIZ);
+                    if (tok->buf == NULL) {
+                        tok->done = E_NOMEM;
+                        return EOF;
+                    }
+                    tok->end = tok->buf + BUFSIZ;
+                }
+                if (decoding_fgets(tok->buf, (int)(tok->end - tok->buf),
+                          tok) == NULL) {
+                    if (!tok->decoding_erred)
+                        tok->done = E_EOF;
+                    done = 1;
+                }
+                else {
+                    tok->done = E_OK;
+                    tok->inp = strchr(tok->buf, '\0');
+                    done = tok->inp[-1] == '\n';
+                }
+            }
+            else {
+                cur = tok->cur - tok->buf;
+                if (decoding_feof(tok)) {
+                    tok->done = E_EOF;
+                    done = 1;
+                }
+                else
+                    tok->done = E_OK;
+            }
+            tok->lineno++;
+            /* Read until '\n' or EOF */
+            while (!done) {
+                Py_ssize_t curstart = tok->start == NULL ? -1 :
+                          tok->start - tok->buf;
+                Py_ssize_t curvalid = tok->inp - tok->buf;
+                Py_ssize_t newsize = curvalid + BUFSIZ;
+                char *newbuf = tok->buf;
+                newbuf = (char *)PyMem_REALLOC(newbuf,
+                                               newsize);
+                if (newbuf == NULL) {
+                    tok->done = E_NOMEM;
+                    tok->cur = tok->inp;
+                    return EOF;
+                }
+                tok->buf = newbuf;
+                tok->cur = tok->buf + cur;
+                tok->line_start = tok->cur;
+                tok->inp = tok->buf + curvalid;
+                tok->end = tok->buf + newsize;
+                tok->start = curstart < 0 ? NULL :
+                         tok->buf + curstart;
+                if (decoding_fgets(tok->inp,
+                               (int)(tok->end - tok->inp),
+                               tok) == NULL) {
+                    /* Break out early on decoding
+                       errors, as tok->buf will be NULL
+                     */
+                    if (tok->decoding_erred)
+                        return EOF;
+                    /* Last line does not end in \n,
+                       fake one */
+                    strcpy(tok->inp, "\n");
+                }
+                tok->inp = strchr(tok->inp, '\0');
+                done = tok->inp[-1] == '\n';
+            }
+            if (tok->buf != NULL) {
+                tok->cur = tok->buf + cur;
+                tok->line_start = tok->cur;
+                /* replace "\r\n" with "\n" */
+                /* For Mac leave the \r, giving a syntax error */
+                pt = tok->inp - 2;
+                if (pt >= tok->buf && *pt == '\r') {
+                    *pt++ = '\n';
+                    *pt = '\0';
+                    tok->inp = pt;
+                }
+            }
+        }
+        if (tok->done != E_OK) {
+            if (tok->prompt != NULL)
+                PySys_WriteStderr("\n");
+            tok->cur = tok->inp;
+            return EOF;
+        }
+    }
+    /*NOTREACHED*/
+}
+
+
+/* Back-up one character */
+
+static void
+tok_backup(struct tok_state *tok, int c)
+{
+    if (c != EOF) {
+        if (--tok->cur < tok->buf)
+            Py_FatalError("tok_backup: beginning of buffer");
+        if (*tok->cur != c)
+            *tok->cur = c;
+    }
+}
+
+
+/* Return the token corresponding to a single character */
+
+int
+Ta35Token_OneChar(int c)
+{
+    switch (c) {
+    case '(':           return LPAR;
+    case ')':           return RPAR;
+    case '[':           return LSQB;
+    case ']':           return RSQB;
+    case ':':           return COLON;
+    case ',':           return COMMA;
+    case ';':           return SEMI;
+    case '+':           return PLUS;
+    case '-':           return MINUS;
+    case '*':           return STAR;
+    case '/':           return SLASH;
+    case '|':           return VBAR;
+    case '&':           return AMPER;
+    case '<':           return LESS;
+    case '>':           return GREATER;
+    case '=':           return EQUAL;
+    case '.':           return DOT;
+    case '%':           return PERCENT;
+    case '{':           return LBRACE;
+    case '}':           return RBRACE;
+    case '^':           return CIRCUMFLEX;
+    case '~':           return TILDE;
+    case '@':           return AT;
+    default:            return OP;
+    }
+}
+
+
+int
+Ta35Token_TwoChars(int c1, int c2)
+{
+    switch (c1) {
+    case '=':
+        switch (c2) {
+        case '=':               return EQEQUAL;
+        }
+        break;
+    case '!':
+        switch (c2) {
+        case '=':               return NOTEQUAL;
+        }
+        break;
+    case '<':
+        switch (c2) {
+        case '>':               return NOTEQUAL;
+        case '=':               return LESSEQUAL;
+        case '<':               return LEFTSHIFT;
+        }
+        break;
+    case '>':
+        switch (c2) {
+        case '=':               return GREATEREQUAL;
+        case '>':               return RIGHTSHIFT;
+        }
+        break;
+    case '+':
+        switch (c2) {
+        case '=':               return PLUSEQUAL;
+        }
+        break;
+    case '-':
+        switch (c2) {
+        case '=':               return MINEQUAL;
+        case '>':               return RARROW;
+        }
+        break;
+    case '*':
+        switch (c2) {
+        case '*':               return DOUBLESTAR;
+        case '=':               return STAREQUAL;
+        }
+        break;
+    case '/':
+        switch (c2) {
+        case '/':               return DOUBLESLASH;
+        case '=':               return SLASHEQUAL;
+        }
+        break;
+    case '|':
+        switch (c2) {
+        case '=':               return VBAREQUAL;
+        }
+        break;
+    case '%':
+        switch (c2) {
+        case '=':               return PERCENTEQUAL;
+        }
+        break;
+    case '&':
+        switch (c2) {
+        case '=':               return AMPEREQUAL;
+        }
+        break;
+    case '^':
+        switch (c2) {
+        case '=':               return CIRCUMFLEXEQUAL;
+        }
+        break;
+    case '@':
+        switch (c2) {
+        case '=':               return ATEQUAL;
+        }
+        break;
+    }
+    return OP;
+}
+
+int
+Ta35Token_ThreeChars(int c1, int c2, int c3)
+{
+    switch (c1) {
+    case '<':
+        switch (c2) {
+        case '<':
+            switch (c3) {
+            case '=':
+                return LEFTSHIFTEQUAL;
+            }
+            break;
+        }
+        break;
+    case '>':
+        switch (c2) {
+        case '>':
+            switch (c3) {
+            case '=':
+                return RIGHTSHIFTEQUAL;
+            }
+            break;
+        }
+        break;
+    case '*':
+        switch (c2) {
+        case '*':
+            switch (c3) {
+            case '=':
+                return DOUBLESTAREQUAL;
+            }
+            break;
+        }
+        break;
+    case '/':
+        switch (c2) {
+        case '/':
+            switch (c3) {
+            case '=':
+                return DOUBLESLASHEQUAL;
+            }
+            break;
+        }
+        break;
+    case '.':
+        switch (c2) {
+        case '.':
+            switch (c3) {
+            case '.':
+                return ELLIPSIS;
+            }
+            break;
+        }
+        break;
+    }
+    return OP;
+}
+
+static int
+indenterror(struct tok_state *tok)
+{
+    if (tok->alterror) {
+        tok->done = E_TABSPACE;
+        tok->cur = tok->inp;
+        return 1;
+    }
+    if (tok->altwarning) {
+#ifdef PGEN
+        PySys_WriteStderr("inconsistent use of tabs and spaces "
+                          "in indentation\n");
+#else
+        PySys_FormatStderr("%U: inconsistent use of tabs and spaces "
+                          "in indentation\n", tok->filename);
+#endif
+        tok->altwarning = 0;
+    }
+    return 0;
+}
+
+#ifdef PGEN
+#define verify_identifier(tok) 1
+#else
+/* Verify that the identifier follows PEP 3131.
+   All identifier strings are guaranteed to be "ready" unicode objects.
+ */
+static int
+verify_identifier(struct tok_state *tok)
+{
+    PyObject *s;
+    int result;
+    if (tok->decoding_erred)
+        return 0;
+    s = PyUnicode_DecodeUTF8(tok->start, tok->cur - tok->start, NULL);
+    if (s == NULL || PyUnicode_READY(s) == -1) {
+        if (PyErr_ExceptionMatches(PyExc_UnicodeDecodeError)) {
+            PyErr_Clear();
+            tok->done = E_IDENTIFIER;
+        } else {
+            tok->done = E_ERROR;
+        }
+        return 0;
+    }
+    result = PyUnicode_IsIdentifier(s);
+    Py_DECREF(s);
+    if (result == 0)
+        tok->done = E_IDENTIFIER;
+    return result;
+}
+#endif
+
+/* Get next token, after space stripping etc. */
+
+static int
+tok_get(struct tok_state *tok, char **p_start, char **p_end)
+{
+    int c;
+    int blankline, nonascii;
+
+    *p_start = *p_end = NULL;
+  nextline:
+    tok->start = NULL;
+    blankline = 0;
+
+    /* Get indentation level */
+    if (tok->atbol) {
+        int col = 0;
+        int altcol = 0;
+        tok->atbol = 0;
+        for (;;) {
+            c = tok_nextc(tok);
+            if (c == ' ')
+                col++, altcol++;
+            else if (c == '\t') {
+                col = (col/tok->tabsize + 1) * tok->tabsize;
+                altcol = (altcol/tok->alttabsize + 1)
+                    * tok->alttabsize;
+            }
+            else if (c == '\014') /* Control-L (formfeed) */
+                col = altcol = 0; /* For Emacs users */
+            else
+                break;
+        }
+        tok_backup(tok, c);
+        if (c == '#' || c == '\n') {
+            /* Lines with only whitespace and/or comments
+               shouldn't affect the indentation and are
+               not passed to the parser as NEWLINE tokens,
+               except *totally* empty lines in interactive
+               mode, which signal the end of a command group. */
+            if (col == 0 && c == '\n' && tok->prompt != NULL)
+                blankline = 0; /* Let it through */
+            else
+                blankline = 1; /* Ignore completely */
+            /* We can't jump back right here since we still
+               may need to skip to the end of a comment */
+        }
+        if (!blankline && tok->level == 0) {
+            if (col == tok->indstack[tok->indent]) {
+                /* No change */
+                if (altcol != tok->altindstack[tok->indent]) {
+                    if (indenterror(tok))
+                        return ERRORTOKEN;
+                }
+            }
+            else if (col > tok->indstack[tok->indent]) {
+                /* Indent -- always one */
+                if (tok->indent+1 >= MAXINDENT) {
+                    tok->done = E_TOODEEP;
+                    tok->cur = tok->inp;
+                    return ERRORTOKEN;
+                }
+                if (altcol <= tok->altindstack[tok->indent]) {
+                    if (indenterror(tok))
+                        return ERRORTOKEN;
+                }
+                tok->pendin++;
+                tok->indstack[++tok->indent] = col;
+                tok->altindstack[tok->indent] = altcol;
+            }
+            else /* col < tok->indstack[tok->indent] */ {
+                /* Dedent -- any number, must be consistent */
+                while (tok->indent > 0 &&
+                    col < tok->indstack[tok->indent]) {
+                    tok->pendin--;
+                    tok->indent--;
+                }
+                if (col != tok->indstack[tok->indent]) {
+                    tok->done = E_DEDENT;
+                    tok->cur = tok->inp;
+                    return ERRORTOKEN;
+                }
+                if (altcol != tok->altindstack[tok->indent]) {
+                    if (indenterror(tok))
+                        return ERRORTOKEN;
+                }
+            }
+        }
+    }
+
+    tok->start = tok->cur;
+
+    /* Return pending indents/dedents */
+    if (tok->pendin != 0) {
+        if (tok->pendin < 0) {
+            tok->pendin++;
+            return DEDENT;
+        }
+        else {
+            tok->pendin--;
+            return INDENT;
+        }
+    }
+
+    if (tok->async_def
+        && !blankline
+        && tok->level == 0
+        /* There was a NEWLINE after ASYNC DEF,
+           so we're past the signature. */
+        && tok->async_def_nl
+        /* Current indentation level is less than where
+           the async function was defined */
+        && tok->async_def_indent >= tok->indent)
+    {
+        tok->async_def = 0;
+        tok->async_def_indent = 0;
+        tok->async_def_nl = 0;
+    }
+
+ again:
+    tok->start = NULL;
+    /* Skip spaces */
+    do {
+        c = tok_nextc(tok);
+    } while (c == ' ' || c == '\t' || c == '\014');
+
+    /* Set start of current token */
+    tok->start = tok->cur - 1;
+
+    /* Skip comment, unless it's a type comment */
+    if (c == '#') {
+        const char *prefix, *p, *type_start;
+
+        while (c != EOF && c != '\n')
+            c = tok_nextc(tok);
+
+        p = tok->start;
+        prefix = type_comment_prefix;
+        while (*prefix && p < tok->cur) {
+            if (*prefix == ' ') {
+                while (*p == ' ' || *p == '\t')
+                    p++;
+            } else if (*prefix == *p) {
+                p++;
+            } else {
+                break;
+            }
+
+            prefix++;
+        }
+
+        /* This is a type comment if we matched all of type_comment_prefix. */
+        if (!*prefix) {
+            int is_type_ignore = 1;
+            tok_backup(tok, c);  /* don't eat the newline or EOF */
+
+            type_start = p;
+
+            is_type_ignore = tok->cur >= p + 6 && memcmp(p, "ignore", 6) == 0;
+            p += 6;
+            while (is_type_ignore && p < tok->cur) {
+              if (*p == '#')
+                  break;
+              is_type_ignore = is_type_ignore && (*p == ' ' || *p == '\t');
+              p++;
+            }
+
+            if (is_type_ignore) {
+                /* If this type ignore is the only thing on the line, consume the newline also. */
+                if (blankline) {
+                    tok_nextc(tok);
+                    tok->atbol = 1;
+                }
+                return TYPE_IGNORE;
+            } else {
+                *p_start = (char *) type_start;  /* after type_comment_prefix */
+                *p_end = tok->cur;
+                return TYPE_COMMENT;
+            }
+        }
+    }
+
+
+    /* Check for EOF and errors now */
+    if (c == EOF) {
+        return tok->done == E_EOF ? ENDMARKER : ERRORTOKEN;
+    }
+
+    /* Identifier (most frequent token!) */
+    nonascii = 0;
+    if (is_potential_identifier_start(c)) {
+        /* Process b"", r"", u"", br"" and rb"" */
+        int saw_b = 0, saw_r = 0, saw_u = 0;
+        while (1) {
+            if (!(saw_b || saw_u) && (c == 'b' || c == 'B'))
+                saw_b = 1;
+            /* Since this is a backwards compatibility support literal we don't
+               want to support it in arbitrary order like byte literals. */
+            else if (!(saw_b || saw_u || saw_r) && (c == 'u' || c == 'U'))
+                saw_u = 1;
+            /* ur"" and ru"" are not supported */
+            else if (!(saw_r || saw_u) && (c == 'r' || c == 'R'))
+                saw_r = 1;
+            else
+                break;
+            c = tok_nextc(tok);
+            if (c == '"' || c == '\'')
+                goto letter_quote;
+        }
+        while (is_potential_identifier_char(c)) {
+            if (c >= 128)
+                nonascii = 1;
+            c = tok_nextc(tok);
+        }
+        tok_backup(tok, c);
+        if (nonascii && !verify_identifier(tok))
+            return ERRORTOKEN;
+        *p_start = tok->start;
+        *p_end = tok->cur;
+
+        /* async/await parsing block. */
+        if (tok->cur - tok->start == 5) {
+            /* Current token length is 5. */
+            if (tok->async_def) {
+                /* We're inside an 'async def' function. */
+                if (memcmp(tok->start, "async", 5) == 0)
+                    return ASYNC;
+                if (memcmp(tok->start, "await", 5) == 0)
+                    return AWAIT;
+            }
+            else if (memcmp(tok->start, "async", 5) == 0) {
+                /* The current token is 'async'.
+                   Look ahead one token.*/
+
+                struct tok_state ahead_tok;
+                char *ahead_tok_start = NULL, *ahead_tok_end = NULL;
+                int ahead_tok_kind;
+
+                memcpy(&ahead_tok, tok, sizeof(ahead_tok));
+                ahead_tok_kind = tok_get(&ahead_tok, &ahead_tok_start,
+                                         &ahead_tok_end);
+
+                if (ahead_tok_kind == NAME
+                    && ahead_tok.cur - ahead_tok.start == 3
+                    && memcmp(ahead_tok.start, "def", 3) == 0)
+                {
+                    /* The next token is going to be 'def', so instead of
+                       returning 'async' NAME token, we return ASYNC. */
+                    tok->async_def_indent = tok->indent;
+                    tok->async_def = 1;
+                    return ASYNC;
+                }
+            }
+        }
+
+        return NAME;
+    }
+
+    /* Newline */
+    if (c == '\n') {
+        tok->atbol = 1;
+        if (blankline || tok->level > 0)
+            goto nextline;
+        *p_start = tok->start;
+        *p_end = tok->cur - 1; /* Leave '\n' out of the string */
+        tok->cont_line = 0;
+        if (tok->async_def) {
+            /* We're somewhere inside an 'async def' function, and
+               we've encountered a NEWLINE after its signature. */
+            tok->async_def_nl = 1;
+        }
+        return NEWLINE;
+    }
+
+    /* Period or number starting with period? */
+    if (c == '.') {
+        c = tok_nextc(tok);
+        if (isdigit(c)) {
+            goto fraction;
+        } else if (c == '.') {
+            c = tok_nextc(tok);
+            if (c == '.') {
+                *p_start = tok->start;
+                *p_end = tok->cur;
+                return ELLIPSIS;
+            } else {
+                tok_backup(tok, c);
+            }
+            tok_backup(tok, '.');
+        } else {
+            tok_backup(tok, c);
+        }
+        *p_start = tok->start;
+        *p_end = tok->cur;
+        return DOT;
+    }
+
+    /* Number */
+    if (isdigit(c)) {
+        if (c == '0') {
+            /* Hex, octal or binary -- maybe. */
+            c = tok_nextc(tok);
+            if (c == '.')
+                goto fraction;
+            if (c == 'j' || c == 'J')
+                goto imaginary;
+            if (c == 'x' || c == 'X') {
+
+                /* Hex */
+                c = tok_nextc(tok);
+                if (!isxdigit(c)) {
+                    tok->done = E_TOKEN;
+                    tok_backup(tok, c);
+                    return ERRORTOKEN;
+                }
+                do {
+                    c = tok_nextc(tok);
+                } while (isxdigit(c));
+            }
+            else if (c == 'o' || c == 'O') {
+                /* Octal */
+                c = tok_nextc(tok);
+                if (c < '0' || c >= '8') {
+                    tok->done = E_TOKEN;
+                    tok_backup(tok, c);
+                    return ERRORTOKEN;
+                }
+                do {
+                    c = tok_nextc(tok);
+                } while ('0' <= c && c < '8');
+            }
+            else if (c == 'b' || c == 'B') {
+                /* Binary */
+                c = tok_nextc(tok);
+                if (c != '0' && c != '1') {
+                    tok->done = E_TOKEN;
+                    tok_backup(tok, c);
+                    return ERRORTOKEN;
+                }
+                do {
+                    c = tok_nextc(tok);
+                } while (c == '0' || c == '1');
+            }
+            else {
+                int nonzero = 0;
+                /* maybe old-style octal; c is first char of it */
+                /* in any case, allow '0' as a literal */
+                while (c == '0')
+                    c = tok_nextc(tok);
+                while (isdigit(c)) {
+                    nonzero = 1;
+                    c = tok_nextc(tok);
+                }
+                if (c == '.')
+                    goto fraction;
+                else if (c == 'e' || c == 'E')
+                    goto exponent;
+                else if (c == 'j' || c == 'J')
+                    goto imaginary;
+                else if (nonzero) {
+                    tok->done = E_TOKEN;
+                    tok_backup(tok, c);
+                    return ERRORTOKEN;
+                }
+            }
+        }
+        else {
+            /* Decimal */
+            do {
+                c = tok_nextc(tok);
+            } while (isdigit(c));
+            {
+                /* Accept floating point numbers. */
+                if (c == '.') {
+        fraction:
+                    /* Fraction */
+                    do {
+                        c = tok_nextc(tok);
+                    } while (isdigit(c));
+                }
+                if (c == 'e' || c == 'E') {
+                    int e;
+                  exponent:
+                    e = c;
+                    /* Exponent part */
+                    c = tok_nextc(tok);
+                    if (c == '+' || c == '-') {
+                        c = tok_nextc(tok);
+                        if (!isdigit(c)) {
+                            tok->done = E_TOKEN;
+                            tok_backup(tok, c);
+                            return ERRORTOKEN;
+                        }
+                    } else if (!isdigit(c)) {
+                        tok_backup(tok, c);
+                        tok_backup(tok, e);
+                        *p_start = tok->start;
+                        *p_end = tok->cur;
+                        return NUMBER;
+                    }
+                    do {
+                        c = tok_nextc(tok);
+                    } while (isdigit(c));
+                }
+                if (c == 'j' || c == 'J')
+                    /* Imaginary part */
+        imaginary:
+                    c = tok_nextc(tok);
+            }
+        }
+        tok_backup(tok, c);
+        *p_start = tok->start;
+        *p_end = tok->cur;
+        return NUMBER;
+    }
+
+  letter_quote:
+    /* String */
+    if (c == '\'' || c == '"') {
+        int quote = c;
+        int quote_size = 1;             /* 1 or 3 */
+        int end_quote_size = 0;
+
+        /* Find the quote size and start of string */
+        c = tok_nextc(tok);
+        if (c == quote) {
+            c = tok_nextc(tok);
+            if (c == quote)
+                quote_size = 3;
+            else
+                end_quote_size = 1;     /* empty string found */
+        }
+        if (c != quote)
+            tok_backup(tok, c);
+
+        /* Get rest of string */
+        while (end_quote_size != quote_size) {
+            c = tok_nextc(tok);
+            if (c == EOF) {
+                if (quote_size == 3)
+                    tok->done = E_EOFS;
+                else
+                    tok->done = E_EOLS;
+                tok->cur = tok->inp;
+                return ERRORTOKEN;
+            }
+            if (quote_size == 1 && c == '\n') {
+                tok->done = E_EOLS;
+                tok->cur = tok->inp;
+                return ERRORTOKEN;
+            }
+            if (c == quote)
+                end_quote_size += 1;
+            else {
+                end_quote_size = 0;
+                if (c == '\\')
+                c = tok_nextc(tok);  /* skip escaped char */
+            }
+        }
+
+        *p_start = tok->start;
+        *p_end = tok->cur;
+        return STRING;
+    }
+
+    /* Line continuation */
+    if (c == '\\') {
+        c = tok_nextc(tok);
+        if (c != '\n') {
+            tok->done = E_LINECONT;
+            tok->cur = tok->inp;
+            return ERRORTOKEN;
+        }
+        tok->cont_line = 1;
+        goto again; /* Read next line */
+    }
+
+    /* Check for two-character token */
+    {
+        int c2 = tok_nextc(tok);
+        int token = Ta35Token_TwoChars(c, c2);
+        if (token != OP) {
+            int c3 = tok_nextc(tok);
+            int token3 = Ta35Token_ThreeChars(c, c2, c3);
+            if (token3 != OP) {
+                token = token3;
+            } else {
+                tok_backup(tok, c3);
+            }
+            *p_start = tok->start;
+            *p_end = tok->cur;
+            return token;
+        }
+        tok_backup(tok, c2);
+    }
+
+    /* Keep track of parentheses nesting level */
+    switch (c) {
+    case '(':
+    case '[':
+    case '{':
+        tok->level++;
+        break;
+    case ')':
+    case ']':
+    case '}':
+        tok->level--;
+        break;
+    }
+
+    /* Punctuation character */
+    *p_start = tok->start;
+    *p_end = tok->cur;
+    return Ta35Token_OneChar(c);
+}
+
+int
+Ta35Tokenizer_Get(struct tok_state *tok, char **p_start, char **p_end)
+{
+    int result = tok_get(tok, p_start, p_end);
+    if (tok->decoding_erred) {
+        result = ERRORTOKEN;
+        tok->done = E_DECODE;
+    }
+    return result;
+}
+
+/* Get the encoding of a Python file. Check for the coding cookie and check if
+   the file starts with a BOM.
+
+   Ta35Tokenizer_FindEncodingFilename() returns NULL when it can't find the
+   encoding in the first or second line of the file (in which case the encoding
+   should be assumed to be UTF-8).
+
+   The char* returned is malloc'ed via PyMem_MALLOC() and thus must be freed
+   by the caller. */
+
+char *
+Ta35Tokenizer_FindEncodingFilename(int fd, PyObject *filename)
+{
+    struct tok_state *tok;
+    FILE *fp;
+    char *p_start =NULL , *p_end =NULL , *encoding = NULL;
+
+#ifndef PGEN
+#if PY_MINOR_VERSION >= 4
+    fd = _Py_dup(fd);
+#endif
+#else
+    fd = dup(fd);
+#endif
+    if (fd < 0) {
+        return NULL;
+    }
+
+    fp = fdopen(fd, "r");
+    if (fp == NULL) {
+        return NULL;
+    }
+    tok = Ta35Tokenizer_FromFile(fp, NULL, NULL, NULL);
+    if (tok == NULL) {
+        fclose(fp);
+        return NULL;
+    }
+#ifndef PGEN
+    if (filename != NULL) {
+        Py_INCREF(filename);
+        tok->filename = filename;
+    }
+    else {
+        tok->filename = PyUnicode_FromString("<string>");
+        if (tok->filename == NULL) {
+            fclose(fp);
+            Ta35Tokenizer_Free(tok);
+            return encoding;
+        }
+    }
+#endif
+    while (tok->lineno < 2 && tok->done == E_OK) {
+        Ta35Tokenizer_Get(tok, &p_start, &p_end);
+    }
+    fclose(fp);
+    if (tok->encoding) {
+        encoding = (char *)PyMem_MALLOC(strlen(tok->encoding) + 1);
+        if (encoding)
+        strcpy(encoding, tok->encoding);
+    }
+    Ta35Tokenizer_Free(tok);
+    return encoding;
+}
+
+char *
+Ta35Tokenizer_FindEncoding(int fd)
+{
+    return Ta35Tokenizer_FindEncodingFilename(fd, NULL);
+}
+
+#ifdef Py_DEBUG
+
+void
+tok_dump(int type, char *start, char *end)
+{
+    printf("%s", _Ta35Parser_TokenNames[type]);
+    if (type == NAME || type == NUMBER || type == STRING || type == OP)
+        printf("(%.*s)", (int)(end - start), start);
+}
+
+#endif
diff --git a/ast35/Parser/tokenizer.h b/ast35/Parser/tokenizer.h
new file mode 100644
index 0000000..1f8251a
--- /dev/null
+++ b/ast35/Parser/tokenizer.h
@@ -0,0 +1,89 @@
+#ifndef Ta35_TOKENIZER_H
+#define Ta35_TOKENIZER_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "object.h"
+
+/* Tokenizer interface */
+
+#include "token.h"      /* For token types */
+
+#define MAXINDENT 100   /* Max indentation level */
+
+enum decoding_state {
+    STATE_INIT,
+    STATE_RAW,
+    STATE_NORMAL        /* have a codec associated with input */
+};
+
+/* Tokenizer state */
+struct tok_state {
+    /* Input state; buf <= cur <= inp <= end */
+    /* NB an entire line is held in the buffer */
+    char *buf;          /* Input buffer, or NULL; malloc'ed if fp != NULL */
+    char *cur;          /* Next character in buffer */
+    char *inp;          /* End of data in buffer */
+    char *end;          /* End of input buffer if buf != NULL */
+    char *start;        /* Start of current token if not NULL */
+    int done;           /* E_OK normally, E_EOF at EOF, otherwise error code */
+    /* NB If done != E_OK, cur must be == inp!!! */
+    FILE *fp;           /* Rest of input; NULL if tokenizing a string */
+    int tabsize;        /* Tab spacing */
+    int indent;         /* Current indentation index */
+    int indstack[MAXINDENT];            /* Stack of indents */
+    int atbol;          /* Nonzero if at begin of new line */
+    int pendin;         /* Pending indents (if > 0) or dedents (if < 0) */
+    const char *prompt, *nextprompt;          /* For interactive prompting */
+    int lineno;         /* Current line number */
+    int level;          /* () [] {} Parentheses nesting level */
+            /* Used to allow free continuations inside them */
+    /* Stuff for checking on different tab sizes */
+#ifndef PGEN
+    /* pgen doesn't have access to Python codecs, it cannot decode the input
+       filename. The bytes filename might be kept, but it is only used by
+       indenterror() and it is not really needed: pgen only compiles one file
+       (Grammar/Grammar). */
+    PyObject *filename;
+#endif
+    int altwarning;     /* Issue warning if alternate tabs don't match */
+    int alterror;       /* Issue error if alternate tabs don't match */
+    int alttabsize;     /* Alternate tab spacing */
+    int altindstack[MAXINDENT];         /* Stack of alternate indents */
+    /* Stuff for PEP 0263 */
+    enum decoding_state decoding_state;
+    int decoding_erred;         /* whether erred in decoding  */
+    int read_coding_spec;       /* whether 'coding:...' has been read  */
+    char *encoding;         /* Source encoding. */
+    int cont_line;          /* whether we are in a continuation line. */
+    const char* line_start;     /* pointer to start of current line */
+#ifndef PGEN
+    PyObject *decoding_readline; /* open(...).readline */
+    PyObject *decoding_buffer;
+#endif
+    const char* enc;        /* Encoding for the current str. */
+    const char* str;
+    const char* input; /* Tokenizer's newline translated copy of the string. */
+
+    /* async/await related fields; can be removed in 3.7 when async and await
+       become normal keywords. */
+    int async_def;        /* =1 if tokens are inside an 'async def' body. */
+    int async_def_indent; /* Indentation level of the outermost 'async def'. */
+    int async_def_nl;     /* =1 if the outermost 'async def' had at least one
+                             NEWLINE token after it. */
+};
+
+extern struct tok_state *Ta35Tokenizer_FromString(const char *, int);
+extern struct tok_state *Ta35Tokenizer_FromUTF8(const char *, int);
+extern struct tok_state *Ta35Tokenizer_FromFile(FILE *, const char*,
+                                              const char *, const char *);
+extern void Ta35Tokenizer_Free(struct tok_state *);
+extern int Ta35Tokenizer_Get(struct tok_state *, char **, char **);
+extern char * PyTokenizer_RestoreEncoding(struct tok_state* tok,
+                                          int len, int *offset);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* !Ta35_TOKENIZER_H */
diff --git a/ast35/Python/Python-ast.c b/ast35/Python/Python-ast.c
new file mode 100644
index 0000000..eb866be
--- /dev/null
+++ b/ast35/Python/Python-ast.c
@@ -0,0 +1,7815 @@
+/* File automatically generated by Parser/asdl_c.py. */
+
+#include <stddef.h>
+
+#include "Python.h"
+#include "Python-ast.h"
+
+static PyTypeObject AST_type;
+static PyTypeObject *mod_type;
+static PyObject* ast2obj_mod(void*);
+static PyTypeObject *Module_type;
+_Py_IDENTIFIER(body);
+_Py_IDENTIFIER(type_ignores);
+static char *Module_fields[]={
+    "body",
+    "type_ignores",
+};
+static PyTypeObject *Interactive_type;
+static char *Interactive_fields[]={
+    "body",
+};
+static PyTypeObject *Expression_type;
+static char *Expression_fields[]={
+    "body",
+};
+static PyTypeObject *FunctionType_type;
+_Py_IDENTIFIER(argtypes);
+_Py_IDENTIFIER(returns);
+static char *FunctionType_fields[]={
+    "argtypes",
+    "returns",
+};
+static PyTypeObject *Suite_type;
+static char *Suite_fields[]={
+    "body",
+};
+static PyTypeObject *stmt_type;
+_Py_IDENTIFIER(lineno);
+_Py_IDENTIFIER(col_offset);
+static char *stmt_attributes[] = {
+    "lineno",
+    "col_offset",
+};
+static PyObject* ast2obj_stmt(void*);
+static PyTypeObject *FunctionDef_type;
+_Py_IDENTIFIER(name);
+_Py_IDENTIFIER(args);
+_Py_IDENTIFIER(decorator_list);
+_Py_IDENTIFIER(type_comment);
+static char *FunctionDef_fields[]={
+    "name",
+    "args",
+    "body",
+    "decorator_list",
+    "returns",
+    "type_comment",
+};
+static PyTypeObject *AsyncFunctionDef_type;
+static char *AsyncFunctionDef_fields[]={
+    "name",
+    "args",
+    "body",
+    "decorator_list",
+    "returns",
+    "type_comment",
+};
+static PyTypeObject *ClassDef_type;
+_Py_IDENTIFIER(bases);
+_Py_IDENTIFIER(keywords);
+static char *ClassDef_fields[]={
+    "name",
+    "bases",
+    "keywords",
+    "body",
+    "decorator_list",
+};
+static PyTypeObject *Return_type;
+_Py_IDENTIFIER(value);
+static char *Return_fields[]={
+    "value",
+};
+static PyTypeObject *Delete_type;
+_Py_IDENTIFIER(targets);
+static char *Delete_fields[]={
+    "targets",
+};
+static PyTypeObject *Assign_type;
+static char *Assign_fields[]={
+    "targets",
+    "value",
+    "type_comment",
+};
+static PyTypeObject *AugAssign_type;
+_Py_IDENTIFIER(target);
+_Py_IDENTIFIER(op);
+static char *AugAssign_fields[]={
+    "target",
+    "op",
+    "value",
+};
+static PyTypeObject *For_type;
+_Py_IDENTIFIER(iter);
+_Py_IDENTIFIER(orelse);
+static char *For_fields[]={
+    "target",
+    "iter",
+    "body",
+    "orelse",
+    "type_comment",
+};
+static PyTypeObject *AsyncFor_type;
+static char *AsyncFor_fields[]={
+    "target",
+    "iter",
+    "body",
+    "orelse",
+};
+static PyTypeObject *While_type;
+_Py_IDENTIFIER(test);
+static char *While_fields[]={
+    "test",
+    "body",
+    "orelse",
+};
+static PyTypeObject *If_type;
+static char *If_fields[]={
+    "test",
+    "body",
+    "orelse",
+};
+static PyTypeObject *With_type;
+_Py_IDENTIFIER(items);
+static char *With_fields[]={
+    "items",
+    "body",
+    "type_comment",
+};
+static PyTypeObject *AsyncWith_type;
+static char *AsyncWith_fields[]={
+    "items",
+    "body",
+};
+static PyTypeObject *Raise_type;
+_Py_IDENTIFIER(exc);
+_Py_IDENTIFIER(cause);
+static char *Raise_fields[]={
+    "exc",
+    "cause",
+};
+static PyTypeObject *Try_type;
+_Py_IDENTIFIER(handlers);
+_Py_IDENTIFIER(finalbody);
+static char *Try_fields[]={
+    "body",
+    "handlers",
+    "orelse",
+    "finalbody",
+};
+static PyTypeObject *Assert_type;
+_Py_IDENTIFIER(msg);
+static char *Assert_fields[]={
+    "test",
+    "msg",
+};
+static PyTypeObject *Import_type;
+_Py_IDENTIFIER(names);
+static char *Import_fields[]={
+    "names",
+};
+static PyTypeObject *ImportFrom_type;
+_Py_IDENTIFIER(module);
+_Py_IDENTIFIER(level);
+static char *ImportFrom_fields[]={
+    "module",
+    "names",
+    "level",
+};
+static PyTypeObject *Global_type;
+static char *Global_fields[]={
+    "names",
+};
+static PyTypeObject *Nonlocal_type;
+static char *Nonlocal_fields[]={
+    "names",
+};
+static PyTypeObject *Expr_type;
+static char *Expr_fields[]={
+    "value",
+};
+static PyTypeObject *Pass_type;
+static PyTypeObject *Break_type;
+static PyTypeObject *Continue_type;
+static PyTypeObject *expr_type;
+static char *expr_attributes[] = {
+    "lineno",
+    "col_offset",
+};
+static PyObject* ast2obj_expr(void*);
+static PyTypeObject *BoolOp_type;
+_Py_IDENTIFIER(values);
+static char *BoolOp_fields[]={
+    "op",
+    "values",
+};
+static PyTypeObject *BinOp_type;
+_Py_IDENTIFIER(left);
+_Py_IDENTIFIER(right);
+static char *BinOp_fields[]={
+    "left",
+    "op",
+    "right",
+};
+static PyTypeObject *UnaryOp_type;
+_Py_IDENTIFIER(operand);
+static char *UnaryOp_fields[]={
+    "op",
+    "operand",
+};
+static PyTypeObject *Lambda_type;
+static char *Lambda_fields[]={
+    "args",
+    "body",
+};
+static PyTypeObject *IfExp_type;
+static char *IfExp_fields[]={
+    "test",
+    "body",
+    "orelse",
+};
+static PyTypeObject *Dict_type;
+_Py_IDENTIFIER(keys);
+static char *Dict_fields[]={
+    "keys",
+    "values",
+};
+static PyTypeObject *Set_type;
+_Py_IDENTIFIER(elts);
+static char *Set_fields[]={
+    "elts",
+};
+static PyTypeObject *ListComp_type;
+_Py_IDENTIFIER(elt);
+_Py_IDENTIFIER(generators);
+static char *ListComp_fields[]={
+    "elt",
+    "generators",
+};
+static PyTypeObject *SetComp_type;
+static char *SetComp_fields[]={
+    "elt",
+    "generators",
+};
+static PyTypeObject *DictComp_type;
+_Py_IDENTIFIER(key);
+static char *DictComp_fields[]={
+    "key",
+    "value",
+    "generators",
+};
+static PyTypeObject *GeneratorExp_type;
+static char *GeneratorExp_fields[]={
+    "elt",
+    "generators",
+};
+static PyTypeObject *Await_type;
+static char *Await_fields[]={
+    "value",
+};
+static PyTypeObject *Yield_type;
+static char *Yield_fields[]={
+    "value",
+};
+static PyTypeObject *YieldFrom_type;
+static char *YieldFrom_fields[]={
+    "value",
+};
+static PyTypeObject *Compare_type;
+_Py_IDENTIFIER(ops);
+_Py_IDENTIFIER(comparators);
+static char *Compare_fields[]={
+    "left",
+    "ops",
+    "comparators",
+};
+static PyTypeObject *Call_type;
+_Py_IDENTIFIER(func);
+static char *Call_fields[]={
+    "func",
+    "args",
+    "keywords",
+};
+static PyTypeObject *Num_type;
+_Py_IDENTIFIER(n);
+static char *Num_fields[]={
+    "n",
+};
+static PyTypeObject *Str_type;
+_Py_IDENTIFIER(s);
+static char *Str_fields[]={
+    "s",
+};
+static PyTypeObject *Bytes_type;
+static char *Bytes_fields[]={
+    "s",
+};
+static PyTypeObject *NameConstant_type;
+static char *NameConstant_fields[]={
+    "value",
+};
+static PyTypeObject *Ellipsis_type;
+static PyTypeObject *Attribute_type;
+_Py_IDENTIFIER(attr);
+_Py_IDENTIFIER(ctx);
+static char *Attribute_fields[]={
+    "value",
+    "attr",
+    "ctx",
+};
+static PyTypeObject *Subscript_type;
+_Py_IDENTIFIER(slice);
+static char *Subscript_fields[]={
+    "value",
+    "slice",
+    "ctx",
+};
+static PyTypeObject *Starred_type;
+static char *Starred_fields[]={
+    "value",
+    "ctx",
+};
+static PyTypeObject *Name_type;
+_Py_IDENTIFIER(id);
+static char *Name_fields[]={
+    "id",
+    "ctx",
+};
+static PyTypeObject *List_type;
+static char *List_fields[]={
+    "elts",
+    "ctx",
+};
+static PyTypeObject *Tuple_type;
+static char *Tuple_fields[]={
+    "elts",
+    "ctx",
+};
+static PyTypeObject *expr_context_type;
+static PyObject *Load_singleton, *Store_singleton, *Del_singleton,
+*AugLoad_singleton, *AugStore_singleton, *Param_singleton;
+static PyObject* ast2obj_expr_context(expr_context_ty);
+static PyTypeObject *Load_type;
+static PyTypeObject *Store_type;
+static PyTypeObject *Del_type;
+static PyTypeObject *AugLoad_type;
+static PyTypeObject *AugStore_type;
+static PyTypeObject *Param_type;
+static PyTypeObject *slice_type;
+static PyObject* ast2obj_slice(void*);
+static PyTypeObject *Slice_type;
+_Py_IDENTIFIER(lower);
+_Py_IDENTIFIER(upper);
+_Py_IDENTIFIER(step);
+static char *Slice_fields[]={
+    "lower",
+    "upper",
+    "step",
+};
+static PyTypeObject *ExtSlice_type;
+_Py_IDENTIFIER(dims);
+static char *ExtSlice_fields[]={
+    "dims",
+};
+static PyTypeObject *Index_type;
+static char *Index_fields[]={
+    "value",
+};
+static PyTypeObject *boolop_type;
+static PyObject *And_singleton, *Or_singleton;
+static PyObject* ast2obj_boolop(boolop_ty);
+static PyTypeObject *And_type;
+static PyTypeObject *Or_type;
+static PyTypeObject *operator_type;
+static PyObject *Add_singleton, *Sub_singleton, *Mult_singleton,
+*MatMult_singleton, *Div_singleton, *Mod_singleton, *Pow_singleton,
+*LShift_singleton, *RShift_singleton, *BitOr_singleton, *BitXor_singleton,
+*BitAnd_singleton, *FloorDiv_singleton;
+static PyObject* ast2obj_operator(operator_ty);
+static PyTypeObject *Add_type;
+static PyTypeObject *Sub_type;
+static PyTypeObject *Mult_type;
+static PyTypeObject *MatMult_type;
+static PyTypeObject *Div_type;
+static PyTypeObject *Mod_type;
+static PyTypeObject *Pow_type;
+static PyTypeObject *LShift_type;
+static PyTypeObject *RShift_type;
+static PyTypeObject *BitOr_type;
+static PyTypeObject *BitXor_type;
+static PyTypeObject *BitAnd_type;
+static PyTypeObject *FloorDiv_type;
+static PyTypeObject *unaryop_type;
+static PyObject *Invert_singleton, *Not_singleton, *UAdd_singleton,
+*USub_singleton;
+static PyObject* ast2obj_unaryop(unaryop_ty);
+static PyTypeObject *Invert_type;
+static PyTypeObject *Not_type;
+static PyTypeObject *UAdd_type;
+static PyTypeObject *USub_type;
+static PyTypeObject *cmpop_type;
+static PyObject *Eq_singleton, *NotEq_singleton, *Lt_singleton, *LtE_singleton,
+*Gt_singleton, *GtE_singleton, *Is_singleton, *IsNot_singleton, *In_singleton,
+*NotIn_singleton;
+static PyObject* ast2obj_cmpop(cmpop_ty);
+static PyTypeObject *Eq_type;
+static PyTypeObject *NotEq_type;
+static PyTypeObject *Lt_type;
+static PyTypeObject *LtE_type;
+static PyTypeObject *Gt_type;
+static PyTypeObject *GtE_type;
+static PyTypeObject *Is_type;
+static PyTypeObject *IsNot_type;
+static PyTypeObject *In_type;
+static PyTypeObject *NotIn_type;
+static PyTypeObject *comprehension_type;
+static PyObject* ast2obj_comprehension(void*);
+_Py_IDENTIFIER(ifs);
+static char *comprehension_fields[]={
+    "target",
+    "iter",
+    "ifs",
+};
+static PyTypeObject *excepthandler_type;
+static char *excepthandler_attributes[] = {
+    "lineno",
+    "col_offset",
+};
+static PyObject* ast2obj_excepthandler(void*);
+static PyTypeObject *ExceptHandler_type;
+_Py_IDENTIFIER(type);
+static char *ExceptHandler_fields[]={
+    "type",
+    "name",
+    "body",
+};
+static PyTypeObject *arguments_type;
+static PyObject* ast2obj_arguments(void*);
+_Py_IDENTIFIER(vararg);
+_Py_IDENTIFIER(kwonlyargs);
+_Py_IDENTIFIER(kw_defaults);
+_Py_IDENTIFIER(kwarg);
+_Py_IDENTIFIER(defaults);
+static char *arguments_fields[]={
+    "args",
+    "vararg",
+    "kwonlyargs",
+    "kw_defaults",
+    "kwarg",
+    "defaults",
+};
+static PyTypeObject *arg_type;
+static PyObject* ast2obj_arg(void*);
+static char *arg_attributes[] = {
+    "lineno",
+    "col_offset",
+};
+_Py_IDENTIFIER(arg);
+_Py_IDENTIFIER(annotation);
+static char *arg_fields[]={
+    "arg",
+    "annotation",
+};
+static PyTypeObject *keyword_type;
+static PyObject* ast2obj_keyword(void*);
+static char *keyword_fields[]={
+    "arg",
+    "value",
+};
+static PyTypeObject *alias_type;
+static PyObject* ast2obj_alias(void*);
+_Py_IDENTIFIER(asname);
+static char *alias_fields[]={
+    "name",
+    "asname",
+};
+static PyTypeObject *withitem_type;
+static PyObject* ast2obj_withitem(void*);
+_Py_IDENTIFIER(context_expr);
+_Py_IDENTIFIER(optional_vars);
+static char *withitem_fields[]={
+    "context_expr",
+    "optional_vars",
+};
+static PyTypeObject *type_ignore_type;
+static PyObject* ast2obj_type_ignore(void*);
+static PyTypeObject *TypeIgnore_type;
+static char *TypeIgnore_fields[]={
+    "lineno",
+};
+
+
+typedef struct {
+    PyObject_HEAD
+    PyObject *dict;
+} AST_object;
+
+static void
+ast_dealloc(AST_object *self)
+{
+    Py_CLEAR(self->dict);
+    Py_TYPE(self)->tp_free(self);
+}
+
+static int
+ast_traverse(AST_object *self, visitproc visit, void *arg)
+{
+    Py_VISIT(self->dict);
+    return 0;
+}
+
+static void
+ast_clear(AST_object *self)
+{
+    Py_CLEAR(self->dict);
+}
+
+static int
+ast_type_init(PyObject *self, PyObject *args, PyObject *kw)
+{
+    _Py_IDENTIFIER(_fields);
+    Py_ssize_t i, numfields = 0;
+    int res = -1;
+    PyObject *key, *value, *fields;
+    fields = _PyObject_GetAttrId((PyObject*)Py_TYPE(self), &PyId__fields);
+    if (!fields)
+        PyErr_Clear();
+    if (fields) {
+        numfields = PySequence_Size(fields);
+        if (numfields == -1)
+            goto cleanup;
+    }
+    res = 0; /* if no error occurs, this stays 0 to the end */
+    if (PyTuple_GET_SIZE(args) > 0) {
+        if (numfields != PyTuple_GET_SIZE(args)) {
+            PyErr_Format(PyExc_TypeError, "%.400s constructor takes %s"
+                         "%zd positional argument%s",
+                         Py_TYPE(self)->tp_name,
+                         numfields == 0 ? "" : "either 0 or ",
+                         numfields, numfields == 1 ? "" : "s");
+            res = -1;
+            goto cleanup;
+        }
+        for (i = 0; i < PyTuple_GET_SIZE(args); i++) {
+            /* cannot be reached when fields is NULL */
+            PyObject *name = PySequence_GetItem(fields, i);
+            if (!name) {
+                res = -1;
+                goto cleanup;
+            }
+            res = PyObject_SetAttr(self, name, PyTuple_GET_ITEM(args, i));
+            Py_DECREF(name);
+            if (res < 0)
+                goto cleanup;
+        }
+    }
+    if (kw) {
+        i = 0;  /* needed by PyDict_Next */
+        while (PyDict_Next(kw, &i, &key, &value)) {
+            res = PyObject_SetAttr(self, key, value);
+            if (res < 0)
+                goto cleanup;
+        }
+    }
+  cleanup:
+    Py_XDECREF(fields);
+    return res;
+}
+
+/* Pickling support */
+static PyObject *
+ast_type_reduce(PyObject *self, PyObject *unused)
+{
+    PyObject *res;
+    _Py_IDENTIFIER(__dict__);
+    PyObject *dict = _PyObject_GetAttrId(self, &PyId___dict__);
+    if (dict == NULL) {
+        if (PyErr_ExceptionMatches(PyExc_AttributeError))
+            PyErr_Clear();
+        else
+            return NULL;
+    }
+    if (dict) {
+        res = Py_BuildValue("O()O", Py_TYPE(self), dict);
+        Py_DECREF(dict);
+        return res;
+    }
+    return Py_BuildValue("O()", Py_TYPE(self));
+}
+
+static PyMethodDef ast_type_methods[] = {
+    {"__reduce__", ast_type_reduce, METH_NOARGS, NULL},
+    {NULL}
+};
+
+static PyGetSetDef ast_type_getsets[] = {
+    {"__dict__", PyObject_GenericGetDict, PyObject_GenericSetDict},
+    {NULL}
+};
+
+static PyTypeObject AST_type = {
+    PyVarObject_HEAD_INIT(&PyType_Type, 0)
+    "_ast35.AST",
+    sizeof(AST_object),
+    0,
+    (destructor)ast_dealloc, /* tp_dealloc */
+    0,                       /* tp_print */
+    0,                       /* tp_getattr */
+    0,                       /* tp_setattr */
+    0,                       /* tp_reserved */
+    0,                       /* tp_repr */
+    0,                       /* tp_as_number */
+    0,                       /* tp_as_sequence */
+    0,                       /* tp_as_mapping */
+    0,                       /* tp_hash */
+    0,                       /* tp_call */
+    0,                       /* tp_str */
+    PyObject_GenericGetAttr, /* tp_getattro */
+    PyObject_GenericSetAttr, /* tp_setattro */
+    0,                       /* tp_as_buffer */
+    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /* tp_flags */
+    0,                       /* tp_doc */
+    (traverseproc)ast_traverse, /* tp_traverse */
+    (inquiry)ast_clear,      /* tp_clear */
+    0,                       /* tp_richcompare */
+    0,                       /* tp_weaklistoffset */
+    0,                       /* tp_iter */
+    0,                       /* tp_iternext */
+    ast_type_methods,        /* tp_methods */
+    0,                       /* tp_members */
+    ast_type_getsets,        /* tp_getset */
+    0,                       /* tp_base */
+    0,                       /* tp_dict */
+    0,                       /* tp_descr_get */
+    0,                       /* tp_descr_set */
+    offsetof(AST_object, dict),/* tp_dictoffset */
+    (initproc)ast_type_init, /* tp_init */
+    PyType_GenericAlloc,     /* tp_alloc */
+    PyType_GenericNew,       /* tp_new */
+    PyObject_GC_Del,         /* tp_free */
+};
+
+
+static PyTypeObject* make_type(char *type, PyTypeObject* base, char**fields, int num_fields)
+{
+    PyObject *fnames, *result;
+    int i;
+    fnames = PyTuple_New(num_fields);
+    if (!fnames) return NULL;
+    for (i = 0; i < num_fields; i++) {
+        PyObject *field = PyUnicode_FromString(fields[i]);
+        if (!field) {
+            Py_DECREF(fnames);
+            return NULL;
+        }
+        PyTuple_SET_ITEM(fnames, i, field);
+    }
+    result = PyObject_CallFunction((PyObject*)&PyType_Type, "s(O){sOss}",
+                    type, base, "_fields", fnames, "__module__", "_ast35");
+    Py_DECREF(fnames);
+    return (PyTypeObject*)result;
+}
+
+static int add_attributes(PyTypeObject* type, char**attrs, int num_fields)
+{
+    int i, result;
+    _Py_IDENTIFIER(_attributes);
+    PyObject *s, *l = PyTuple_New(num_fields);
+    if (!l)
+        return 0;
+    for (i = 0; i < num_fields; i++) {
+        s = PyUnicode_FromString(attrs[i]);
+        if (!s) {
+            Py_DECREF(l);
+            return 0;
+        }
+        PyTuple_SET_ITEM(l, i, s);
+    }
+    result = _PyObject_SetAttrId((PyObject*)type, &PyId__attributes, l) >= 0;
+    Py_DECREF(l);
+    return result;
+}
+
+/* Conversion AST -> Python */
+
+static PyObject* ast2obj_list(asdl_seq *seq, PyObject* (*func)(void*))
+{
+    Py_ssize_t i, n = asdl_seq_LEN(seq);
+    PyObject *result = PyList_New(n);
+    PyObject *value;
+    if (!result)
+        return NULL;
+    for (i = 0; i < n; i++) {
+        value = func(asdl_seq_GET(seq, i));
+        if (!value) {
+            Py_DECREF(result);
+            return NULL;
+        }
+        PyList_SET_ITEM(result, i, value);
+    }
+    return result;
+}
+
+static PyObject* ast2obj_object(void *o)
+{
+    if (!o)
+        o = Py_None;
+    Py_INCREF((PyObject*)o);
+    return (PyObject*)o;
+}
+#define ast2obj_singleton ast2obj_object
+#define ast2obj_identifier ast2obj_object
+#define ast2obj_string ast2obj_object
+#define ast2obj_bytes ast2obj_object
+
+static PyObject* ast2obj_int(long b)
+{
+    return PyLong_FromLong(b);
+}
+
+/* Conversion Python -> AST */
+
+static int obj2ast_singleton(PyObject *obj, PyObject** out, PyArena* arena)
+{
+    if (obj != Py_None && obj != Py_True && obj != Py_False) {
+        PyErr_SetString(PyExc_ValueError,
+                        "AST singleton must be True, False, or None");
+        return 1;
+    }
+    *out = obj;
+    return 0;
+}
+
+static int obj2ast_object(PyObject* obj, PyObject** out, PyArena* arena)
+{
+    if (obj == Py_None)
+        obj = NULL;
+    if (obj) {
+        if (PyArena_AddPyObject(arena, obj) < 0) {
+            *out = NULL;
+            return -1;
+        }
+        Py_INCREF(obj);
+    }
+    *out = obj;
+    return 0;
+}
+
+static int obj2ast_identifier(PyObject* obj, PyObject** out, PyArena* arena)
+{
+    if (!PyUnicode_CheckExact(obj) && obj != Py_None) {
+        PyErr_SetString(PyExc_TypeError, "AST identifier must be of type str");
+        return 1;
+    }
+    return obj2ast_object(obj, out, arena);
+}
+
+static int obj2ast_string(PyObject* obj, PyObject** out, PyArena* arena)
+{
+    if (!PyUnicode_CheckExact(obj) && !PyBytes_CheckExact(obj)) {
+        PyErr_SetString(PyExc_TypeError, "AST string must be of type str");
+        return 1;
+    }
+    return obj2ast_object(obj, out, arena);
+}
+
+static int obj2ast_bytes(PyObject* obj, PyObject** out, PyArena* arena)
+{
+    if (!PyBytes_CheckExact(obj)) {
+        PyErr_SetString(PyExc_TypeError, "AST bytes must be of type bytes");
+        return 1;
+    }
+    return obj2ast_object(obj, out, arena);
+}
+
+static int obj2ast_int(PyObject* obj, int* out, PyArena* arena)
+{
+    int i;
+    if (!PyLong_Check(obj)) {
+        PyErr_Format(PyExc_ValueError, "invalid integer value: %R", obj);
+        return 1;
+    }
+
+    i = (int)PyLong_AsLong(obj);
+    if (i == -1 && PyErr_Occurred())
+        return 1;
+    *out = i;
+    return 0;
+}
+
+static int add_ast_fields(void)
+{
+    PyObject *empty_tuple, *d;
+    if (PyType_Ready(&AST_type) < 0)
+        return -1;
+    d = AST_type.tp_dict;
+    empty_tuple = PyTuple_New(0);
+    if (!empty_tuple ||
+        PyDict_SetItemString(d, "_fields", empty_tuple) < 0 ||
+        PyDict_SetItemString(d, "_attributes", empty_tuple) < 0) {
+        Py_XDECREF(empty_tuple);
+        return -1;
+    }
+    Py_DECREF(empty_tuple);
+    return 0;
+}
+
+static int exists_not_none(PyObject *obj, _Py_Identifier *id)
+{
+    int isnone;
+    PyObject *attr = _PyObject_GetAttrId(obj, id);
+    if (!attr) {
+        PyErr_Clear();
+        return 0;
+    }
+    isnone = attr == Py_None;
+    Py_DECREF(attr);
+    return !isnone;
+}
+
+
+static int init_types(void)
+{
+    static int initialized;
+    if (initialized) return 1;
+    if (add_ast_fields() < 0) return 0;
+    mod_type = make_type("mod", &AST_type, NULL, 0);
+    if (!mod_type) return 0;
+    if (!add_attributes(mod_type, NULL, 0)) return 0;
+    Module_type = make_type("Module", mod_type, Module_fields, 2);
+    if (!Module_type) return 0;
+    Interactive_type = make_type("Interactive", mod_type, Interactive_fields,
+                                 1);
+    if (!Interactive_type) return 0;
+    Expression_type = make_type("Expression", mod_type, Expression_fields, 1);
+    if (!Expression_type) return 0;
+    FunctionType_type = make_type("FunctionType", mod_type,
+                                  FunctionType_fields, 2);
+    if (!FunctionType_type) return 0;
+    Suite_type = make_type("Suite", mod_type, Suite_fields, 1);
+    if (!Suite_type) return 0;
+    stmt_type = make_type("stmt", &AST_type, NULL, 0);
+    if (!stmt_type) return 0;
+    if (!add_attributes(stmt_type, stmt_attributes, 2)) return 0;
+    FunctionDef_type = make_type("FunctionDef", stmt_type, FunctionDef_fields,
+                                 6);
+    if (!FunctionDef_type) return 0;
+    AsyncFunctionDef_type = make_type("AsyncFunctionDef", stmt_type,
+                                      AsyncFunctionDef_fields, 6);
+    if (!AsyncFunctionDef_type) return 0;
+    ClassDef_type = make_type("ClassDef", stmt_type, ClassDef_fields, 5);
+    if (!ClassDef_type) return 0;
+    Return_type = make_type("Return", stmt_type, Return_fields, 1);
+    if (!Return_type) return 0;
+    Delete_type = make_type("Delete", stmt_type, Delete_fields, 1);
+    if (!Delete_type) return 0;
+    Assign_type = make_type("Assign", stmt_type, Assign_fields, 3);
+    if (!Assign_type) return 0;
+    AugAssign_type = make_type("AugAssign", stmt_type, AugAssign_fields, 3);
+    if (!AugAssign_type) return 0;
+    For_type = make_type("For", stmt_type, For_fields, 5);
+    if (!For_type) return 0;
+    AsyncFor_type = make_type("AsyncFor", stmt_type, AsyncFor_fields, 4);
+    if (!AsyncFor_type) return 0;
+    While_type = make_type("While", stmt_type, While_fields, 3);
+    if (!While_type) return 0;
+    If_type = make_type("If", stmt_type, If_fields, 3);
+    if (!If_type) return 0;
+    With_type = make_type("With", stmt_type, With_fields, 3);
+    if (!With_type) return 0;
+    AsyncWith_type = make_type("AsyncWith", stmt_type, AsyncWith_fields, 2);
+    if (!AsyncWith_type) return 0;
+    Raise_type = make_type("Raise", stmt_type, Raise_fields, 2);
+    if (!Raise_type) return 0;
+    Try_type = make_type("Try", stmt_type, Try_fields, 4);
+    if (!Try_type) return 0;
+    Assert_type = make_type("Assert", stmt_type, Assert_fields, 2);
+    if (!Assert_type) return 0;
+    Import_type = make_type("Import", stmt_type, Import_fields, 1);
+    if (!Import_type) return 0;
+    ImportFrom_type = make_type("ImportFrom", stmt_type, ImportFrom_fields, 3);
+    if (!ImportFrom_type) return 0;
+    Global_type = make_type("Global", stmt_type, Global_fields, 1);
+    if (!Global_type) return 0;
+    Nonlocal_type = make_type("Nonlocal", stmt_type, Nonlocal_fields, 1);
+    if (!Nonlocal_type) return 0;
+    Expr_type = make_type("Expr", stmt_type, Expr_fields, 1);
+    if (!Expr_type) return 0;
+    Pass_type = make_type("Pass", stmt_type, NULL, 0);
+    if (!Pass_type) return 0;
+    Break_type = make_type("Break", stmt_type, NULL, 0);
+    if (!Break_type) return 0;
+    Continue_type = make_type("Continue", stmt_type, NULL, 0);
+    if (!Continue_type) return 0;
+    expr_type = make_type("expr", &AST_type, NULL, 0);
+    if (!expr_type) return 0;
+    if (!add_attributes(expr_type, expr_attributes, 2)) return 0;
+    BoolOp_type = make_type("BoolOp", expr_type, BoolOp_fields, 2);
+    if (!BoolOp_type) return 0;
+    BinOp_type = make_type("BinOp", expr_type, BinOp_fields, 3);
+    if (!BinOp_type) return 0;
+    UnaryOp_type = make_type("UnaryOp", expr_type, UnaryOp_fields, 2);
+    if (!UnaryOp_type) return 0;
+    Lambda_type = make_type("Lambda", expr_type, Lambda_fields, 2);
+    if (!Lambda_type) return 0;
+    IfExp_type = make_type("IfExp", expr_type, IfExp_fields, 3);
+    if (!IfExp_type) return 0;
+    Dict_type = make_type("Dict", expr_type, Dict_fields, 2);
+    if (!Dict_type) return 0;
+    Set_type = make_type("Set", expr_type, Set_fields, 1);
+    if (!Set_type) return 0;
+    ListComp_type = make_type("ListComp", expr_type, ListComp_fields, 2);
+    if (!ListComp_type) return 0;
+    SetComp_type = make_type("SetComp", expr_type, SetComp_fields, 2);
+    if (!SetComp_type) return 0;
+    DictComp_type = make_type("DictComp", expr_type, DictComp_fields, 3);
+    if (!DictComp_type) return 0;
+    GeneratorExp_type = make_type("GeneratorExp", expr_type,
+                                  GeneratorExp_fields, 2);
+    if (!GeneratorExp_type) return 0;
+    Await_type = make_type("Await", expr_type, Await_fields, 1);
+    if (!Await_type) return 0;
+    Yield_type = make_type("Yield", expr_type, Yield_fields, 1);
+    if (!Yield_type) return 0;
+    YieldFrom_type = make_type("YieldFrom", expr_type, YieldFrom_fields, 1);
+    if (!YieldFrom_type) return 0;
+    Compare_type = make_type("Compare", expr_type, Compare_fields, 3);
+    if (!Compare_type) return 0;
+    Call_type = make_type("Call", expr_type, Call_fields, 3);
+    if (!Call_type) return 0;
+    Num_type = make_type("Num", expr_type, Num_fields, 1);
+    if (!Num_type) return 0;
+    Str_type = make_type("Str", expr_type, Str_fields, 1);
+    if (!Str_type) return 0;
+    Bytes_type = make_type("Bytes", expr_type, Bytes_fields, 1);
+    if (!Bytes_type) return 0;
+    NameConstant_type = make_type("NameConstant", expr_type,
+                                  NameConstant_fields, 1);
+    if (!NameConstant_type) return 0;
+    Ellipsis_type = make_type("Ellipsis", expr_type, NULL, 0);
+    if (!Ellipsis_type) return 0;
+    Attribute_type = make_type("Attribute", expr_type, Attribute_fields, 3);
+    if (!Attribute_type) return 0;
+    Subscript_type = make_type("Subscript", expr_type, Subscript_fields, 3);
+    if (!Subscript_type) return 0;
+    Starred_type = make_type("Starred", expr_type, Starred_fields, 2);
+    if (!Starred_type) return 0;
+    Name_type = make_type("Name", expr_type, Name_fields, 2);
+    if (!Name_type) return 0;
+    List_type = make_type("List", expr_type, List_fields, 2);
+    if (!List_type) return 0;
+    Tuple_type = make_type("Tuple", expr_type, Tuple_fields, 2);
+    if (!Tuple_type) return 0;
+    expr_context_type = make_type("expr_context", &AST_type, NULL, 0);
+    if (!expr_context_type) return 0;
+    if (!add_attributes(expr_context_type, NULL, 0)) return 0;
+    Load_type = make_type("Load", expr_context_type, NULL, 0);
+    if (!Load_type) return 0;
+    Load_singleton = PyType_GenericNew(Load_type, NULL, NULL);
+    if (!Load_singleton) return 0;
+    Store_type = make_type("Store", expr_context_type, NULL, 0);
+    if (!Store_type) return 0;
+    Store_singleton = PyType_GenericNew(Store_type, NULL, NULL);
+    if (!Store_singleton) return 0;
+    Del_type = make_type("Del", expr_context_type, NULL, 0);
+    if (!Del_type) return 0;
+    Del_singleton = PyType_GenericNew(Del_type, NULL, NULL);
+    if (!Del_singleton) return 0;
+    AugLoad_type = make_type("AugLoad", expr_context_type, NULL, 0);
+    if (!AugLoad_type) return 0;
+    AugLoad_singleton = PyType_GenericNew(AugLoad_type, NULL, NULL);
+    if (!AugLoad_singleton) return 0;
+    AugStore_type = make_type("AugStore", expr_context_type, NULL, 0);
+    if (!AugStore_type) return 0;
+    AugStore_singleton = PyType_GenericNew(AugStore_type, NULL, NULL);
+    if (!AugStore_singleton) return 0;
+    Param_type = make_type("Param", expr_context_type, NULL, 0);
+    if (!Param_type) return 0;
+    Param_singleton = PyType_GenericNew(Param_type, NULL, NULL);
+    if (!Param_singleton) return 0;
+    slice_type = make_type("slice", &AST_type, NULL, 0);
+    if (!slice_type) return 0;
+    if (!add_attributes(slice_type, NULL, 0)) return 0;
+    Slice_type = make_type("Slice", slice_type, Slice_fields, 3);
+    if (!Slice_type) return 0;
+    ExtSlice_type = make_type("ExtSlice", slice_type, ExtSlice_fields, 1);
+    if (!ExtSlice_type) return 0;
+    Index_type = make_type("Index", slice_type, Index_fields, 1);
+    if (!Index_type) return 0;
+    boolop_type = make_type("boolop", &AST_type, NULL, 0);
+    if (!boolop_type) return 0;
+    if (!add_attributes(boolop_type, NULL, 0)) return 0;
+    And_type = make_type("And", boolop_type, NULL, 0);
+    if (!And_type) return 0;
+    And_singleton = PyType_GenericNew(And_type, NULL, NULL);
+    if (!And_singleton) return 0;
+    Or_type = make_type("Or", boolop_type, NULL, 0);
+    if (!Or_type) return 0;
+    Or_singleton = PyType_GenericNew(Or_type, NULL, NULL);
+    if (!Or_singleton) return 0;
+    operator_type = make_type("operator", &AST_type, NULL, 0);
+    if (!operator_type) return 0;
+    if (!add_attributes(operator_type, NULL, 0)) return 0;
+    Add_type = make_type("Add", operator_type, NULL, 0);
+    if (!Add_type) return 0;
+    Add_singleton = PyType_GenericNew(Add_type, NULL, NULL);
+    if (!Add_singleton) return 0;
+    Sub_type = make_type("Sub", operator_type, NULL, 0);
+    if (!Sub_type) return 0;
+    Sub_singleton = PyType_GenericNew(Sub_type, NULL, NULL);
+    if (!Sub_singleton) return 0;
+    Mult_type = make_type("Mult", operator_type, NULL, 0);
+    if (!Mult_type) return 0;
+    Mult_singleton = PyType_GenericNew(Mult_type, NULL, NULL);
+    if (!Mult_singleton) return 0;
+    MatMult_type = make_type("MatMult", operator_type, NULL, 0);
+    if (!MatMult_type) return 0;
+    MatMult_singleton = PyType_GenericNew(MatMult_type, NULL, NULL);
+    if (!MatMult_singleton) return 0;
+    Div_type = make_type("Div", operator_type, NULL, 0);
+    if (!Div_type) return 0;
+    Div_singleton = PyType_GenericNew(Div_type, NULL, NULL);
+    if (!Div_singleton) return 0;
+    Mod_type = make_type("Mod", operator_type, NULL, 0);
+    if (!Mod_type) return 0;
+    Mod_singleton = PyType_GenericNew(Mod_type, NULL, NULL);
+    if (!Mod_singleton) return 0;
+    Pow_type = make_type("Pow", operator_type, NULL, 0);
+    if (!Pow_type) return 0;
+    Pow_singleton = PyType_GenericNew(Pow_type, NULL, NULL);
+    if (!Pow_singleton) return 0;
+    LShift_type = make_type("LShift", operator_type, NULL, 0);
+    if (!LShift_type) return 0;
+    LShift_singleton = PyType_GenericNew(LShift_type, NULL, NULL);
+    if (!LShift_singleton) return 0;
+    RShift_type = make_type("RShift", operator_type, NULL, 0);
+    if (!RShift_type) return 0;
+    RShift_singleton = PyType_GenericNew(RShift_type, NULL, NULL);
+    if (!RShift_singleton) return 0;
+    BitOr_type = make_type("BitOr", operator_type, NULL, 0);
+    if (!BitOr_type) return 0;
+    BitOr_singleton = PyType_GenericNew(BitOr_type, NULL, NULL);
+    if (!BitOr_singleton) return 0;
+    BitXor_type = make_type("BitXor", operator_type, NULL, 0);
+    if (!BitXor_type) return 0;
+    BitXor_singleton = PyType_GenericNew(BitXor_type, NULL, NULL);
+    if (!BitXor_singleton) return 0;
+    BitAnd_type = make_type("BitAnd", operator_type, NULL, 0);
+    if (!BitAnd_type) return 0;
+    BitAnd_singleton = PyType_GenericNew(BitAnd_type, NULL, NULL);
+    if (!BitAnd_singleton) return 0;
+    FloorDiv_type = make_type("FloorDiv", operator_type, NULL, 0);
+    if (!FloorDiv_type) return 0;
+    FloorDiv_singleton = PyType_GenericNew(FloorDiv_type, NULL, NULL);
+    if (!FloorDiv_singleton) return 0;
+    unaryop_type = make_type("unaryop", &AST_type, NULL, 0);
+    if (!unaryop_type) return 0;
+    if (!add_attributes(unaryop_type, NULL, 0)) return 0;
+    Invert_type = make_type("Invert", unaryop_type, NULL, 0);
+    if (!Invert_type) return 0;
+    Invert_singleton = PyType_GenericNew(Invert_type, NULL, NULL);
+    if (!Invert_singleton) return 0;
+    Not_type = make_type("Not", unaryop_type, NULL, 0);
+    if (!Not_type) return 0;
+    Not_singleton = PyType_GenericNew(Not_type, NULL, NULL);
+    if (!Not_singleton) return 0;
+    UAdd_type = make_type("UAdd", unaryop_type, NULL, 0);
+    if (!UAdd_type) return 0;
+    UAdd_singleton = PyType_GenericNew(UAdd_type, NULL, NULL);
+    if (!UAdd_singleton) return 0;
+    USub_type = make_type("USub", unaryop_type, NULL, 0);
+    if (!USub_type) return 0;
+    USub_singleton = PyType_GenericNew(USub_type, NULL, NULL);
+    if (!USub_singleton) return 0;
+    cmpop_type = make_type("cmpop", &AST_type, NULL, 0);
+    if (!cmpop_type) return 0;
+    if (!add_attributes(cmpop_type, NULL, 0)) return 0;
+    Eq_type = make_type("Eq", cmpop_type, NULL, 0);
+    if (!Eq_type) return 0;
+    Eq_singleton = PyType_GenericNew(Eq_type, NULL, NULL);
+    if (!Eq_singleton) return 0;
+    NotEq_type = make_type("NotEq", cmpop_type, NULL, 0);
+    if (!NotEq_type) return 0;
+    NotEq_singleton = PyType_GenericNew(NotEq_type, NULL, NULL);
+    if (!NotEq_singleton) return 0;
+    Lt_type = make_type("Lt", cmpop_type, NULL, 0);
+    if (!Lt_type) return 0;
+    Lt_singleton = PyType_GenericNew(Lt_type, NULL, NULL);
+    if (!Lt_singleton) return 0;
+    LtE_type = make_type("LtE", cmpop_type, NULL, 0);
+    if (!LtE_type) return 0;
+    LtE_singleton = PyType_GenericNew(LtE_type, NULL, NULL);
+    if (!LtE_singleton) return 0;
+    Gt_type = make_type("Gt", cmpop_type, NULL, 0);
+    if (!Gt_type) return 0;
+    Gt_singleton = PyType_GenericNew(Gt_type, NULL, NULL);
+    if (!Gt_singleton) return 0;
+    GtE_type = make_type("GtE", cmpop_type, NULL, 0);
+    if (!GtE_type) return 0;
+    GtE_singleton = PyType_GenericNew(GtE_type, NULL, NULL);
+    if (!GtE_singleton) return 0;
+    Is_type = make_type("Is", cmpop_type, NULL, 0);
+    if (!Is_type) return 0;
+    Is_singleton = PyType_GenericNew(Is_type, NULL, NULL);
+    if (!Is_singleton) return 0;
+    IsNot_type = make_type("IsNot", cmpop_type, NULL, 0);
+    if (!IsNot_type) return 0;
+    IsNot_singleton = PyType_GenericNew(IsNot_type, NULL, NULL);
+    if (!IsNot_singleton) return 0;
+    In_type = make_type("In", cmpop_type, NULL, 0);
+    if (!In_type) return 0;
+    In_singleton = PyType_GenericNew(In_type, NULL, NULL);
+    if (!In_singleton) return 0;
+    NotIn_type = make_type("NotIn", cmpop_type, NULL, 0);
+    if (!NotIn_type) return 0;
+    NotIn_singleton = PyType_GenericNew(NotIn_type, NULL, NULL);
+    if (!NotIn_singleton) return 0;
+    comprehension_type = make_type("comprehension", &AST_type,
+                                   comprehension_fields, 3);
+    if (!comprehension_type) return 0;
+    if (!add_attributes(comprehension_type, NULL, 0)) return 0;
+    excepthandler_type = make_type("excepthandler", &AST_type, NULL, 0);
+    if (!excepthandler_type) return 0;
+    if (!add_attributes(excepthandler_type, excepthandler_attributes, 2))
+        return 0;
+    ExceptHandler_type = make_type("ExceptHandler", excepthandler_type,
+                                   ExceptHandler_fields, 3);
+    if (!ExceptHandler_type) return 0;
+    arguments_type = make_type("arguments", &AST_type, arguments_fields, 6);
+    if (!arguments_type) return 0;
+    if (!add_attributes(arguments_type, NULL, 0)) return 0;
+    arg_type = make_type("arg", &AST_type, arg_fields, 2);
+    if (!arg_type) return 0;
+    if (!add_attributes(arg_type, arg_attributes, 2)) return 0;
+    keyword_type = make_type("keyword", &AST_type, keyword_fields, 2);
+    if (!keyword_type) return 0;
+    if (!add_attributes(keyword_type, NULL, 0)) return 0;
+    alias_type = make_type("alias", &AST_type, alias_fields, 2);
+    if (!alias_type) return 0;
+    if (!add_attributes(alias_type, NULL, 0)) return 0;
+    withitem_type = make_type("withitem", &AST_type, withitem_fields, 2);
+    if (!withitem_type) return 0;
+    if (!add_attributes(withitem_type, NULL, 0)) return 0;
+    type_ignore_type = make_type("type_ignore", &AST_type, NULL, 0);
+    if (!type_ignore_type) return 0;
+    if (!add_attributes(type_ignore_type, NULL, 0)) return 0;
+    TypeIgnore_type = make_type("TypeIgnore", type_ignore_type,
+                                TypeIgnore_fields, 1);
+    if (!TypeIgnore_type) return 0;
+    initialized = 1;
+    return 1;
+}
+
+static int obj2ast_mod(PyObject* obj, mod_ty* out, PyArena* arena);
+static int obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena);
+static int obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena);
+static int obj2ast_expr_context(PyObject* obj, expr_context_ty* out, PyArena*
+                                arena);
+static int obj2ast_slice(PyObject* obj, slice_ty* out, PyArena* arena);
+static int obj2ast_boolop(PyObject* obj, boolop_ty* out, PyArena* arena);
+static int obj2ast_operator(PyObject* obj, operator_ty* out, PyArena* arena);
+static int obj2ast_unaryop(PyObject* obj, unaryop_ty* out, PyArena* arena);
+static int obj2ast_cmpop(PyObject* obj, cmpop_ty* out, PyArena* arena);
+static int obj2ast_comprehension(PyObject* obj, comprehension_ty* out, PyArena*
+                                 arena);
+static int obj2ast_excepthandler(PyObject* obj, excepthandler_ty* out, PyArena*
+                                 arena);
+static int obj2ast_arguments(PyObject* obj, arguments_ty* out, PyArena* arena);
+static int obj2ast_arg(PyObject* obj, arg_ty* out, PyArena* arena);
+static int obj2ast_keyword(PyObject* obj, keyword_ty* out, PyArena* arena);
+static int obj2ast_alias(PyObject* obj, alias_ty* out, PyArena* arena);
+static int obj2ast_withitem(PyObject* obj, withitem_ty* out, PyArena* arena);
+static int obj2ast_type_ignore(PyObject* obj, type_ignore_ty* out, PyArena*
+                               arena);
+
+mod_ty
+Module(asdl_seq * body, asdl_seq * type_ignores, PyArena *arena)
+{
+    mod_ty p;
+    p = (mod_ty)PyArena_Malloc(arena, sizeof(*p));
+    if (!p)
+        return NULL;
+    p->kind = Module_kind;
+    p->v.Module.body = body;
+    p->v.Module.type_ignores = type_ignores;
+    return p;
+}
+
+mod_ty
+Interactive(asdl_seq * body, PyArena *arena)
+{
+    mod_ty p;
+    p = (mod_ty)PyArena_Malloc(arena, sizeof(*p));
+    if (!p)
+        return NULL;
+    p->kind = Interactive_kind;
+    p->v.Interactive.body = body;
+    return p;
+}
+
+mod_ty
+Expression(expr_ty body, PyArena *arena)
+{
+    mod_ty p;
+    if (!body) {
+        PyErr_SetString(PyExc_ValueError,
+                        "field body is required for Expression");
+        return NULL;
+    }
+    p = (mod_ty)PyArena_Malloc(arena, sizeof(*p));
+    if (!p)
+        return NULL;
+    p->kind = Expression_kind;
+    p->v.Expression.body = body;
+    return p;
+}
+
+mod_ty
+FunctionType(asdl_seq * argtypes, expr_ty returns, PyArena *arena)
+{
+    mod_ty p;
+    if (!returns) {
+        PyErr_SetString(PyExc_ValueError,
+                        "field returns is required for FunctionType");
+        return NULL;
+    }
+    p = (mod_ty)PyArena_Malloc(arena, sizeof(*p));
+    if (!p)
+        return NULL;
+    p->kind = FunctionType_kind;
+    p->v.FunctionType.argtypes = argtypes;
+    p->v.FunctionType.returns = returns;
+    return p;
+}
+
+mod_ty
+Suite(asdl_seq * body, PyArena *arena)
+{
+    mod_ty p;
+    p = (mod_ty)PyArena_Malloc(arena, sizeof(*p));
+    if (!p)
+        return NULL;
+    p->kind = Suite_kind;
+    p->v.Suite.body = body;
+    return p;
+}
+
+stmt_ty
+FunctionDef(identifier name, arguments_ty args, asdl_seq * body, asdl_seq *
+            decorator_list, expr_ty returns, string type_comment, int lineno,
+            int col_offset, PyArena *arena)
+{
+    stmt_ty p;
+    if (!name) {
+        PyErr_SetString(PyExc_ValueError,
+                        "field name is required for FunctionDef");
+        return NULL;
+    }
+    if (!args) {
+        PyErr_SetString(PyExc_ValueError,
+                        "field args is required for FunctionDef");
+        return NULL;
+    }
+    p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p));
+    if (!p)
+        return NULL;
+    p->kind = FunctionDef_kind;
+    p->v.FunctionDef.name = name;
+    p->v.FunctionDef.args = args;
+    p->v.FunctionDef.body = body;
+    p->v.FunctionDef.decorator_list = decorator_list;
+    p->v.FunctionDef.returns = returns;
+    p->v.FunctionDef.type_comment = type_comment;
+    p->lineno = lineno;
+    p->col_offset = col_offset;
+    return p;
+}
+
+stmt_ty
+AsyncFunctionDef(identifier name, arguments_ty args, asdl_seq * body, asdl_seq
+                 * decorator_list, expr_ty returns, string type_comment, int
+                 lineno, int col_offset, PyArena *arena)
+{
+    stmt_ty p;
+    if (!name) {
+        PyErr_SetString(PyExc_ValueError,
+                        "field name is required for AsyncFunctionDef");
+        return NULL;
+    }
+    if (!args) {
+        PyErr_SetString(PyExc_ValueError,
+                        "field args is required for AsyncFunctionDef");
+        return NULL;
+    }
+    p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p));
+    if (!p)
+        return NULL;
+    p->kind = AsyncFunctionDef_kind;
+    p->v.AsyncFunctionDef.name = name;
+    p->v.AsyncFunctionDef.args = args;
+    p->v.AsyncFunctionDef.body = body;
+    p->v.AsyncFunctionDef.decorator_list = decorator_list;
+    p->v.AsyncFunctionDef.returns = returns;
+    p->v.AsyncFunctionDef.type_comment = type_comment;
+    p->lineno = lineno;
+    p->col_offset = col_offset;
+    return p;
+}
+
+stmt_ty
+ClassDef(identifier name, asdl_seq * bases, asdl_seq * keywords, asdl_seq *
+         body, asdl_seq * decorator_list, int lineno, int col_offset, PyArena
+         *arena)
+{
+    stmt_ty p;
+    if (!name) {
+        PyErr_SetString(PyExc_ValueError,
+                        "field name is required for ClassDef");
+        return NULL;
+    }
+    p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p));
+    if (!p)
+        return NULL;
+    p->kind = ClassDef_kind;
+    p->v.ClassDef.name = name;
+    p->v.ClassDef.bases = bases;
+    p->v.ClassDef.keywords = keywords;
+    p->v.ClassDef.body = body;
+    p->v.ClassDef.decorator_list = decorator_list;
+    p->lineno = lineno;
+    p->col_offset = col_offset;
+    return p;
+}
+
+stmt_ty
+Return(expr_ty value, int lineno, int col_offset, PyArena *arena)
+{
+    stmt_ty p;
+    p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p));
+    if (!p)
+        return NULL;
+    p->kind = Return_kind;
+    p->v.Return.value = value;
+    p->lineno = lineno;
+    p->col_offset = col_offset;
+    return p;
+}
+
+stmt_ty
+Delete(asdl_seq * targets, int lineno, int col_offset, PyArena *arena)
+{
+    stmt_ty p;
+    p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p));
+    if (!p)
+        return NULL;
+    p->kind = Delete_kind;
+    p->v.Delete.targets = targets;
+    p->lineno = lineno;
+    p->col_offset = col_offset;
+    return p;
+}
+
+stmt_ty
+Assign(asdl_seq * targets, expr_ty value, string type_comment, int lineno, int
+       col_offset, PyArena *arena)
+{
+    stmt_ty p;
+    if (!value) {
+        PyErr_SetString(PyExc_ValueError,
+                        "field value is required for Assign");
+        return NULL;
+    }
+    p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p));
+    if (!p)
+        return NULL;
+    p->kind = Assign_kind;
+    p->v.Assign.targets = targets;
+    p->v.Assign.value = value;
+    p->v.Assign.type_comment = type_comment;
+    p->lineno = lineno;
+    p->col_offset = col_offset;
+    return p;
+}
+
+stmt_ty
+AugAssign(expr_ty target, operator_ty op, expr_ty value, int lineno, int
+          col_offset, PyArena *arena)
+{
+    stmt_ty p;
+    if (!target) {
+        PyErr_SetString(PyExc_ValueError,
+                        "field target is required for AugAssign");
+        return NULL;
+    }
+    if (!op) {
+        PyErr_SetString(PyExc_ValueError,
+                        "field op is required for AugAssign");
+        return NULL;
+    }
+    if (!value) {
+        PyErr_SetString(PyExc_ValueError,
+                        "field value is required for AugAssign");
+        return NULL;
+    }
+    p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p));
+    if (!p)
+        return NULL;
+    p->kind = AugAssign_kind;
+    p->v.AugAssign.target = target;
+    p->v.AugAssign.op = op;
+    p->v.AugAssign.value = value;
+    p->lineno = lineno;
+    p->col_offset = col_offset;
+    return p;
+}
+
+stmt_ty
+For(expr_ty target, expr_ty iter, asdl_seq * body, asdl_seq * orelse, string
+    type_comment, int lineno, int col_offset, PyArena *arena)
+{
+    stmt_ty p;
+    if (!target) {
+        PyErr_SetString(PyExc_ValueError,
+                        "field target is required for For");
+        return NULL;
+    }
+    if (!iter) {
+        PyErr_SetString(PyExc_ValueError,
+                        "field iter is required for For");
+        return NULL;
+    }
+    p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p));
+    if (!p)
+        return NULL;
+    p->kind = For_kind;
+    p->v.For.target = target;
+    p->v.For.iter = iter;
+    p->v.For.body = body;
+    p->v.For.orelse = orelse;
+    p->v.For.type_comment = type_comment;
+    p->lineno = lineno;
+    p->col_offset = col_offset;
+    return p;
+}
+
+stmt_ty
+AsyncFor(expr_ty target, expr_ty iter, asdl_seq * body, asdl_seq * orelse, int
+         lineno, int col_offset, PyArena *arena)
+{
+    stmt_ty p;
+    if (!target) {
+        PyErr_SetString(PyExc_ValueError,
+                        "field target is required for AsyncFor");
+        return NULL;
+    }
+    if (!iter) {
+        PyErr_SetString(PyExc_ValueError,
+                        "field iter is required for AsyncFor");
+        return NULL;
+    }
+    p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p));
+    if (!p)
+        return NULL;
+    p->kind = AsyncFor_kind;
+    p->v.AsyncFor.target = target;
+    p->v.AsyncFor.iter = iter;
+    p->v.AsyncFor.body = body;
+    p->v.AsyncFor.orelse = orelse;
+    p->lineno = lineno;
+    p->col_offset = col_offset;
+    return p;
+}
+
+stmt_ty
+While(expr_ty test, asdl_seq * body, asdl_seq * orelse, int lineno, int
+      col_offset, PyArena *arena)
+{
+    stmt_ty p;
+    if (!test) {
+        PyErr_SetString(PyExc_ValueError,
+                        "field test is required for While");
+        return NULL;
+    }
+    p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p));
+    if (!p)
+        return NULL;
+    p->kind = While_kind;
+    p->v.While.test = test;
+    p->v.While.body = body;
+    p->v.While.orelse = orelse;
+    p->lineno = lineno;
+    p->col_offset = col_offset;
+    return p;
+}
+
+stmt_ty
+If(expr_ty test, asdl_seq * body, asdl_seq * orelse, int lineno, int
+   col_offset, PyArena *arena)
+{
+    stmt_ty p;
+    if (!test) {
+        PyErr_SetString(PyExc_ValueError,
+                        "field test is required for If");
+        return NULL;
+    }
+    p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p));
+    if (!p)
+        return NULL;
+    p->kind = If_kind;
+    p->v.If.test = test;
+    p->v.If.body = body;
+    p->v.If.orelse = orelse;
+    p->lineno = lineno;
+    p->col_offset = col_offset;
+    return p;
+}
+
+stmt_ty
+With(asdl_seq * items, asdl_seq * body, string type_comment, int lineno, int
+     col_offset, PyArena *arena)
+{
+    stmt_ty p;
+    p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p));
+    if (!p)
+        return NULL;
+    p->kind = With_kind;
+    p->v.With.items = items;
+    p->v.With.body = body;
+    p->v.With.type_comment = type_comment;
+    p->lineno = lineno;
+    p->col_offset = col_offset;
+    return p;
+}
+
+stmt_ty
+AsyncWith(asdl_seq * items, asdl_seq * body, int lineno, int col_offset,
+          PyArena *arena)
+{
+    stmt_ty p;
+    p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p));
+    if (!p)
+        return NULL;
+    p->kind = AsyncWith_kind;
+    p->v.AsyncWith.items = items;
+    p->v.AsyncWith.body = body;
+    p->lineno = lineno;
+    p->col_offset = col_offset;
+    return p;
+}
+
+stmt_ty
+Raise(expr_ty exc, expr_ty cause, int lineno, int col_offset, PyArena *arena)
+{
+    stmt_ty p;
+    p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p));
+    if (!p)
+        return NULL;
+    p->kind = Raise_kind;
+    p->v.Raise.exc = exc;
+    p->v.Raise.cause = cause;
+    p->lineno = lineno;
+    p->col_offset = col_offset;
+    return p;
+}
+
+stmt_ty
+Try(asdl_seq * body, asdl_seq * handlers, asdl_seq * orelse, asdl_seq *
+    finalbody, int lineno, int col_offset, PyArena *arena)
+{
+    stmt_ty p;
+    p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p));
+    if (!p)
+        return NULL;
+    p->kind = Try_kind;
+    p->v.Try.body = body;
+    p->v.Try.handlers = handlers;
+    p->v.Try.orelse = orelse;
+    p->v.Try.finalbody = finalbody;
+    p->lineno = lineno;
+    p->col_offset = col_offset;
+    return p;
+}
+
+stmt_ty
+Assert(expr_ty test, expr_ty msg, int lineno, int col_offset, PyArena *arena)
+{
+    stmt_ty p;
+    if (!test) {
+        PyErr_SetString(PyExc_ValueError,
+                        "field test is required for Assert");
+        return NULL;
+    }
+    p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p));
+    if (!p)
+        return NULL;
+    p->kind = Assert_kind;
+    p->v.Assert.test = test;
+    p->v.Assert.msg = msg;
+    p->lineno = lineno;
+    p->col_offset = col_offset;
+    return p;
+}
+
+stmt_ty
+Import(asdl_seq * names, int lineno, int col_offset, PyArena *arena)
+{
+    stmt_ty p;
+    p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p));
+    if (!p)
+        return NULL;
+    p->kind = Import_kind;
+    p->v.Import.names = names;
+    p->lineno = lineno;
+    p->col_offset = col_offset;
+    return p;
+}
+
+stmt_ty
+ImportFrom(identifier module, asdl_seq * names, int level, int lineno, int
+           col_offset, PyArena *arena)
+{
+    stmt_ty p;
+    p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p));
+    if (!p)
+        return NULL;
+    p->kind = ImportFrom_kind;
+    p->v.ImportFrom.module = module;
+    p->v.ImportFrom.names = names;
+    p->v.ImportFrom.level = level;
+    p->lineno = lineno;
+    p->col_offset = col_offset;
+    return p;
+}
+
+stmt_ty
+Global(asdl_seq * names, int lineno, int col_offset, PyArena *arena)
+{
+    stmt_ty p;
+    p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p));
+    if (!p)
+        return NULL;
+    p->kind = Global_kind;
+    p->v.Global.names = names;
+    p->lineno = lineno;
+    p->col_offset = col_offset;
+    return p;
+}
+
+stmt_ty
+Nonlocal(asdl_seq * names, int lineno, int col_offset, PyArena *arena)
+{
+    stmt_ty p;
+    p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p));
+    if (!p)
+        return NULL;
+    p->kind = Nonlocal_kind;
+    p->v.Nonlocal.names = names;
+    p->lineno = lineno;
+    p->col_offset = col_offset;
+    return p;
+}
+
+stmt_ty
+Expr(expr_ty value, int lineno, int col_offset, PyArena *arena)
+{
+    stmt_ty p;
+    if (!value) {
+        PyErr_SetString(PyExc_ValueError,
+                        "field value is required for Expr");
+        return NULL;
+    }
+    p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p));
+    if (!p)
+        return NULL;
+    p->kind = Expr_kind;
+    p->v.Expr.value = value;
+    p->lineno = lineno;
+    p->col_offset = col_offset;
+    return p;
+}
+
+stmt_ty
+Pass(int lineno, int col_offset, PyArena *arena)
+{
+    stmt_ty p;
+    p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p));
+    if (!p)
+        return NULL;
+    p->kind = Pass_kind;
+    p->lineno = lineno;
+    p->col_offset = col_offset;
+    return p;
+}
+
+stmt_ty
+Break(int lineno, int col_offset, PyArena *arena)
+{
+    stmt_ty p;
+    p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p));
+    if (!p)
+        return NULL;
+    p->kind = Break_kind;
+    p->lineno = lineno;
+    p->col_offset = col_offset;
+    return p;
+}
+
+stmt_ty
+Continue(int lineno, int col_offset, PyArena *arena)
+{
+    stmt_ty p;
+    p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p));
+    if (!p)
+        return NULL;
+    p->kind = Continue_kind;
+    p->lineno = lineno;
+    p->col_offset = col_offset;
+    return p;
+}
+
+expr_ty
+BoolOp(boolop_ty op, asdl_seq * values, int lineno, int col_offset, PyArena
+       *arena)
+{
+    expr_ty p;
+    if (!op) {
+        PyErr_SetString(PyExc_ValueError,
+                        "field op is required for BoolOp");
+        return NULL;
+    }
+    p = (expr_ty)PyArena_Malloc(arena, sizeof(*p));
+    if (!p)
+        return NULL;
+    p->kind = BoolOp_kind;
+    p->v.BoolOp.op = op;
+    p->v.BoolOp.values = values;
+    p->lineno = lineno;
+    p->col_offset = col_offset;
+    return p;
+}
+
+expr_ty
+BinOp(expr_ty left, operator_ty op, expr_ty right, int lineno, int col_offset,
+      PyArena *arena)
+{
+    expr_ty p;
+    if (!left) {
+        PyErr_SetString(PyExc_ValueError,
+                        "field left is required for BinOp");
+        return NULL;
+    }
+    if (!op) {
+        PyErr_SetString(PyExc_ValueError,
+                        "field op is required for BinOp");
+        return NULL;
+    }
+    if (!right) {
+        PyErr_SetString(PyExc_ValueError,
+                        "field right is required for BinOp");
+        return NULL;
+    }
+    p = (expr_ty)PyArena_Malloc(arena, sizeof(*p));
+    if (!p)
+        return NULL;
+    p->kind = BinOp_kind;
+    p->v.BinOp.left = left;
+    p->v.BinOp.op = op;
+    p->v.BinOp.right = right;
+    p->lineno = lineno;
+    p->col_offset = col_offset;
+    return p;
+}
+
+expr_ty
+UnaryOp(unaryop_ty op, expr_ty operand, int lineno, int col_offset, PyArena
+        *arena)
+{
+    expr_ty p;
+    if (!op) {
+        PyErr_SetString(PyExc_ValueError,
+                        "field op is required for UnaryOp");
+        return NULL;
+    }
+    if (!operand) {
+        PyErr_SetString(PyExc_ValueError,
+                        "field operand is required for UnaryOp");
+        return NULL;
+    }
+    p = (expr_ty)PyArena_Malloc(arena, sizeof(*p));
+    if (!p)
+        return NULL;
+    p->kind = UnaryOp_kind;
+    p->v.UnaryOp.op = op;
+    p->v.UnaryOp.operand = operand;
+    p->lineno = lineno;
+    p->col_offset = col_offset;
+    return p;
+}
+
+expr_ty
+Lambda(arguments_ty args, expr_ty body, int lineno, int col_offset, PyArena
+       *arena)
+{
+    expr_ty p;
+    if (!args) {
+        PyErr_SetString(PyExc_ValueError,
+                        "field args is required for Lambda");
+        return NULL;
+    }
+    if (!body) {
+        PyErr_SetString(PyExc_ValueError,
+                        "field body is required for Lambda");
+        return NULL;
+    }
+    p = (expr_ty)PyArena_Malloc(arena, sizeof(*p));
+    if (!p)
+        return NULL;
+    p->kind = Lambda_kind;
+    p->v.Lambda.args = args;
+    p->v.Lambda.body = body;
+    p->lineno = lineno;
+    p->col_offset = col_offset;
+    return p;
+}
+
+expr_ty
+IfExp(expr_ty test, expr_ty body, expr_ty orelse, int lineno, int col_offset,
+      PyArena *arena)
+{
+    expr_ty p;
+    if (!test) {
+        PyErr_SetString(PyExc_ValueError,
+                        "field test is required for IfExp");
+        return NULL;
+    }
+    if (!body) {
+        PyErr_SetString(PyExc_ValueError,
+                        "field body is required for IfExp");
+        return NULL;
+    }
+    if (!orelse) {
+        PyErr_SetString(PyExc_ValueError,
+                        "field orelse is required for IfExp");
+        return NULL;
+    }
+    p = (expr_ty)PyArena_Malloc(arena, sizeof(*p));
+    if (!p)
+        return NULL;
+    p->kind = IfExp_kind;
+    p->v.IfExp.test = test;
+    p->v.IfExp.body = body;
+    p->v.IfExp.orelse = orelse;
+    p->lineno = lineno;
+    p->col_offset = col_offset;
+    return p;
+}
+
+expr_ty
+Dict(asdl_seq * keys, asdl_seq * values, int lineno, int col_offset, PyArena
+     *arena)
+{
+    expr_ty p;
+    p = (expr_ty)PyArena_Malloc(arena, sizeof(*p));
+    if (!p)
+        return NULL;
+    p->kind = Dict_kind;
+    p->v.Dict.keys = keys;
+    p->v.Dict.values = values;
+    p->lineno = lineno;
+    p->col_offset = col_offset;
+    return p;
+}
+
+expr_ty
+Set(asdl_seq * elts, int lineno, int col_offset, PyArena *arena)
+{
+    expr_ty p;
+    p = (expr_ty)PyArena_Malloc(arena, sizeof(*p));
+    if (!p)
+        return NULL;
+    p->kind = Set_kind;
+    p->v.Set.elts = elts;
+    p->lineno = lineno;
+    p->col_offset = col_offset;
+    return p;
+}
+
+expr_ty
+ListComp(expr_ty elt, asdl_seq * generators, int lineno, int col_offset,
+         PyArena *arena)
+{
+    expr_ty p;
+    if (!elt) {
+        PyErr_SetString(PyExc_ValueError,
+                        "field elt is required for ListComp");
+        return NULL;
+    }
+    p = (expr_ty)PyArena_Malloc(arena, sizeof(*p));
+    if (!p)
+        return NULL;
+    p->kind = ListComp_kind;
+    p->v.ListComp.elt = elt;
+    p->v.ListComp.generators = generators;
+    p->lineno = lineno;
+    p->col_offset = col_offset;
+    return p;
+}
+
+expr_ty
+SetComp(expr_ty elt, asdl_seq * generators, int lineno, int col_offset, PyArena
+        *arena)
+{
+    expr_ty p;
+    if (!elt) {
+        PyErr_SetString(PyExc_ValueError,
+                        "field elt is required for SetComp");
+        return NULL;
+    }
+    p = (expr_ty)PyArena_Malloc(arena, sizeof(*p));
+    if (!p)
+        return NULL;
+    p->kind = SetComp_kind;
+    p->v.SetComp.elt = elt;
+    p->v.SetComp.generators = generators;
+    p->lineno = lineno;
+    p->col_offset = col_offset;
+    return p;
+}
+
+expr_ty
+DictComp(expr_ty key, expr_ty value, asdl_seq * generators, int lineno, int
+         col_offset, PyArena *arena)
+{
+    expr_ty p;
+    if (!key) {
+        PyErr_SetString(PyExc_ValueError,
+                        "field key is required for DictComp");
+        return NULL;
+    }
+    if (!value) {
+        PyErr_SetString(PyExc_ValueError,
+                        "field value is required for DictComp");
+        return NULL;
+    }
+    p = (expr_ty)PyArena_Malloc(arena, sizeof(*p));
+    if (!p)
+        return NULL;
+    p->kind = DictComp_kind;
+    p->v.DictComp.key = key;
+    p->v.DictComp.value = value;
+    p->v.DictComp.generators = generators;
+    p->lineno = lineno;
+    p->col_offset = col_offset;
+    return p;
+}
+
+expr_ty
+GeneratorExp(expr_ty elt, asdl_seq * generators, int lineno, int col_offset,
+             PyArena *arena)
+{
+    expr_ty p;
+    if (!elt) {
+        PyErr_SetString(PyExc_ValueError,
+                        "field elt is required for GeneratorExp");
+        return NULL;
+    }
+    p = (expr_ty)PyArena_Malloc(arena, sizeof(*p));
+    if (!p)
+        return NULL;
+    p->kind = GeneratorExp_kind;
+    p->v.GeneratorExp.elt = elt;
+    p->v.GeneratorExp.generators = generators;
+    p->lineno = lineno;
+    p->col_offset = col_offset;
+    return p;
+}
+
+expr_ty
+Await(expr_ty value, int lineno, int col_offset, PyArena *arena)
+{
+    expr_ty p;
+    if (!value) {
+        PyErr_SetString(PyExc_ValueError,
+                        "field value is required for Await");
+        return NULL;
+    }
+    p = (expr_ty)PyArena_Malloc(arena, sizeof(*p));
+    if (!p)
+        return NULL;
+    p->kind = Await_kind;
+    p->v.Await.value = value;
+    p->lineno = lineno;
+    p->col_offset = col_offset;
+    return p;
+}
+
+expr_ty
+Yield(expr_ty value, int lineno, int col_offset, PyArena *arena)
+{
+    expr_ty p;
+    p = (expr_ty)PyArena_Malloc(arena, sizeof(*p));
+    if (!p)
+        return NULL;
+    p->kind = Yield_kind;
+    p->v.Yield.value = value;
+    p->lineno = lineno;
+    p->col_offset = col_offset;
+    return p;
+}
+
+expr_ty
+YieldFrom(expr_ty value, int lineno, int col_offset, PyArena *arena)
+{
+    expr_ty p;
+    if (!value) {
+        PyErr_SetString(PyExc_ValueError,
+                        "field value is required for YieldFrom");
+        return NULL;
+    }
+    p = (expr_ty)PyArena_Malloc(arena, sizeof(*p));
+    if (!p)
+        return NULL;
+    p->kind = YieldFrom_kind;
+    p->v.YieldFrom.value = value;
+    p->lineno = lineno;
+    p->col_offset = col_offset;
+    return p;
+}
+
+expr_ty
+Compare(expr_ty left, asdl_int_seq * ops, asdl_seq * comparators, int lineno,
+        int col_offset, PyArena *arena)
+{
+    expr_ty p;
+    if (!left) {
+        PyErr_SetString(PyExc_ValueError,
+                        "field left is required for Compare");
+        return NULL;
+    }
+    p = (expr_ty)PyArena_Malloc(arena, sizeof(*p));
+    if (!p)
+        return NULL;
+    p->kind = Compare_kind;
+    p->v.Compare.left = left;
+    p->v.Compare.ops = ops;
+    p->v.Compare.comparators = comparators;
+    p->lineno = lineno;
+    p->col_offset = col_offset;
+    return p;
+}
+
+expr_ty
+Call(expr_ty func, asdl_seq * args, asdl_seq * keywords, int lineno, int
+     col_offset, PyArena *arena)
+{
+    expr_ty p;
+    if (!func) {
+        PyErr_SetString(PyExc_ValueError,
+                        "field func is required for Call");
+        return NULL;
+    }
+    p = (expr_ty)PyArena_Malloc(arena, sizeof(*p));
+    if (!p)
+        return NULL;
+    p->kind = Call_kind;
+    p->v.Call.func = func;
+    p->v.Call.args = args;
+    p->v.Call.keywords = keywords;
+    p->lineno = lineno;
+    p->col_offset = col_offset;
+    return p;
+}
+
+expr_ty
+Num(object n, int lineno, int col_offset, PyArena *arena)
+{
+    expr_ty p;
+    if (!n) {
+        PyErr_SetString(PyExc_ValueError,
+                        "field n is required for Num");
+        return NULL;
+    }
+    p = (expr_ty)PyArena_Malloc(arena, sizeof(*p));
+    if (!p)
+        return NULL;
+    p->kind = Num_kind;
+    p->v.Num.n = n;
+    p->lineno = lineno;
+    p->col_offset = col_offset;
+    return p;
+}
+
+expr_ty
+Str(string s, int lineno, int col_offset, PyArena *arena)
+{
+    expr_ty p;
+    if (!s) {
+        PyErr_SetString(PyExc_ValueError,
+                        "field s is required for Str");
+        return NULL;
+    }
+    p = (expr_ty)PyArena_Malloc(arena, sizeof(*p));
+    if (!p)
+        return NULL;
+    p->kind = Str_kind;
+    p->v.Str.s = s;
+    p->lineno = lineno;
+    p->col_offset = col_offset;
+    return p;
+}
+
+expr_ty
+Bytes(bytes s, int lineno, int col_offset, PyArena *arena)
+{
+    expr_ty p;
+    if (!s) {
+        PyErr_SetString(PyExc_ValueError,
+                        "field s is required for Bytes");
+        return NULL;
+    }
+    p = (expr_ty)PyArena_Malloc(arena, sizeof(*p));
+    if (!p)
+        return NULL;
+    p->kind = Bytes_kind;
+    p->v.Bytes.s = s;
+    p->lineno = lineno;
+    p->col_offset = col_offset;
+    return p;
+}
+
+expr_ty
+NameConstant(singleton value, int lineno, int col_offset, PyArena *arena)
+{
+    expr_ty p;
+    if (!value) {
+        PyErr_SetString(PyExc_ValueError,
+                        "field value is required for NameConstant");
+        return NULL;
+    }
+    p = (expr_ty)PyArena_Malloc(arena, sizeof(*p));
+    if (!p)
+        return NULL;
+    p->kind = NameConstant_kind;
+    p->v.NameConstant.value = value;
+    p->lineno = lineno;
+    p->col_offset = col_offset;
+    return p;
+}
+
+expr_ty
+Ellipsis(int lineno, int col_offset, PyArena *arena)
+{
+    expr_ty p;
+    p = (expr_ty)PyArena_Malloc(arena, sizeof(*p));
+    if (!p)
+        return NULL;
+    p->kind = Ellipsis_kind;
+    p->lineno = lineno;
+    p->col_offset = col_offset;
+    return p;
+}
+
+expr_ty
+Attribute(expr_ty value, identifier attr, expr_context_ty ctx, int lineno, int
+          col_offset, PyArena *arena)
+{
+    expr_ty p;
+    if (!value) {
+        PyErr_SetString(PyExc_ValueError,
+                        "field value is required for Attribute");
+        return NULL;
+    }
+    if (!attr) {
+        PyErr_SetString(PyExc_ValueError,
+                        "field attr is required for Attribute");
+        return NULL;
+    }
+    if (!ctx) {
+        PyErr_SetString(PyExc_ValueError,
+                        "field ctx is required for Attribute");
+        return NULL;
+    }
+    p = (expr_ty)PyArena_Malloc(arena, sizeof(*p));
+    if (!p)
+        return NULL;
+    p->kind = Attribute_kind;
+    p->v.Attribute.value = value;
+    p->v.Attribute.attr = attr;
+    p->v.Attribute.ctx = ctx;
+    p->lineno = lineno;
+    p->col_offset = col_offset;
+    return p;
+}
+
+expr_ty
+Subscript(expr_ty value, slice_ty slice, expr_context_ty ctx, int lineno, int
+          col_offset, PyArena *arena)
+{
+    expr_ty p;
+    if (!value) {
+        PyErr_SetString(PyExc_ValueError,
+                        "field value is required for Subscript");
+        return NULL;
+    }
+    if (!slice) {
+        PyErr_SetString(PyExc_ValueError,
+                        "field slice is required for Subscript");
+        return NULL;
+    }
+    if (!ctx) {
+        PyErr_SetString(PyExc_ValueError,
+                        "field ctx is required for Subscript");
+        return NULL;
+    }
+    p = (expr_ty)PyArena_Malloc(arena, sizeof(*p));
+    if (!p)
+        return NULL;
+    p->kind = Subscript_kind;
+    p->v.Subscript.value = value;
+    p->v.Subscript.slice = slice;
+    p->v.Subscript.ctx = ctx;
+    p->lineno = lineno;
+    p->col_offset = col_offset;
+    return p;
+}
+
+expr_ty
+Starred(expr_ty value, expr_context_ty ctx, int lineno, int col_offset, PyArena
+        *arena)
+{
+    expr_ty p;
+    if (!value) {
+        PyErr_SetString(PyExc_ValueError,
+                        "field value is required for Starred");
+        return NULL;
+    }
+    if (!ctx) {
+        PyErr_SetString(PyExc_ValueError,
+                        "field ctx is required for Starred");
+        return NULL;
+    }
+    p = (expr_ty)PyArena_Malloc(arena, sizeof(*p));
+    if (!p)
+        return NULL;
+    p->kind = Starred_kind;
+    p->v.Starred.value = value;
+    p->v.Starred.ctx = ctx;
+    p->lineno = lineno;
+    p->col_offset = col_offset;
+    return p;
+}
+
+expr_ty
+Name(identifier id, expr_context_ty ctx, int lineno, int col_offset, PyArena
+     *arena)
+{
+    expr_ty p;
+    if (!id) {
+        PyErr_SetString(PyExc_ValueError,
+                        "field id is required for Name");
+        return NULL;
+    }
+    if (!ctx) {
+        PyErr_SetString(PyExc_ValueError,
+                        "field ctx is required for Name");
+        return NULL;
+    }
+    p = (expr_ty)PyArena_Malloc(arena, sizeof(*p));
+    if (!p)
+        return NULL;
+    p->kind = Name_kind;
+    p->v.Name.id = id;
+    p->v.Name.ctx = ctx;
+    p->lineno = lineno;
+    p->col_offset = col_offset;
+    return p;
+}
+
+expr_ty
+List(asdl_seq * elts, expr_context_ty ctx, int lineno, int col_offset, PyArena
+     *arena)
+{
+    expr_ty p;
+    if (!ctx) {
+        PyErr_SetString(PyExc_ValueError,
+                        "field ctx is required for List");
+        return NULL;
+    }
+    p = (expr_ty)PyArena_Malloc(arena, sizeof(*p));
+    if (!p)
+        return NULL;
+    p->kind = List_kind;
+    p->v.List.elts = elts;
+    p->v.List.ctx = ctx;
+    p->lineno = lineno;
+    p->col_offset = col_offset;
+    return p;
+}
+
+expr_ty
+Tuple(asdl_seq * elts, expr_context_ty ctx, int lineno, int col_offset, PyArena
+      *arena)
+{
+    expr_ty p;
+    if (!ctx) {
+        PyErr_SetString(PyExc_ValueError,
+                        "field ctx is required for Tuple");
+        return NULL;
+    }
+    p = (expr_ty)PyArena_Malloc(arena, sizeof(*p));
+    if (!p)
+        return NULL;
+    p->kind = Tuple_kind;
+    p->v.Tuple.elts = elts;
+    p->v.Tuple.ctx = ctx;
+    p->lineno = lineno;
+    p->col_offset = col_offset;
+    return p;
+}
+
+slice_ty
+Slice(expr_ty lower, expr_ty upper, expr_ty step, PyArena *arena)
+{
+    slice_ty p;
+    p = (slice_ty)PyArena_Malloc(arena, sizeof(*p));
+    if (!p)
+        return NULL;
+    p->kind = Slice_kind;
+    p->v.Slice.lower = lower;
+    p->v.Slice.upper = upper;
+    p->v.Slice.step = step;
+    return p;
+}
+
+slice_ty
+ExtSlice(asdl_seq * dims, PyArena *arena)
+{
+    slice_ty p;
+    p = (slice_ty)PyArena_Malloc(arena, sizeof(*p));
+    if (!p)
+        return NULL;
+    p->kind = ExtSlice_kind;
+    p->v.ExtSlice.dims = dims;
+    return p;
+}
+
+slice_ty
+Index(expr_ty value, PyArena *arena)
+{
+    slice_ty p;
+    if (!value) {
+        PyErr_SetString(PyExc_ValueError,
+                        "field value is required for Index");
+        return NULL;
+    }
+    p = (slice_ty)PyArena_Malloc(arena, sizeof(*p));
+    if (!p)
+        return NULL;
+    p->kind = Index_kind;
+    p->v.Index.value = value;
+    return p;
+}
+
+comprehension_ty
+comprehension(expr_ty target, expr_ty iter, asdl_seq * ifs, PyArena *arena)
+{
+    comprehension_ty p;
+    if (!target) {
+        PyErr_SetString(PyExc_ValueError,
+                        "field target is required for comprehension");
+        return NULL;
+    }
+    if (!iter) {
+        PyErr_SetString(PyExc_ValueError,
+                        "field iter is required for comprehension");
+        return NULL;
+    }
+    p = (comprehension_ty)PyArena_Malloc(arena, sizeof(*p));
+    if (!p)
+        return NULL;
+    p->target = target;
+    p->iter = iter;
+    p->ifs = ifs;
+    return p;
+}
+
+excepthandler_ty
+ExceptHandler(expr_ty type, identifier name, asdl_seq * body, int lineno, int
+              col_offset, PyArena *arena)
+{
+    excepthandler_ty p;
+    p = (excepthandler_ty)PyArena_Malloc(arena, sizeof(*p));
+    if (!p)
+        return NULL;
+    p->kind = ExceptHandler_kind;
+    p->v.ExceptHandler.type = type;
+    p->v.ExceptHandler.name = name;
+    p->v.ExceptHandler.body = body;
+    p->lineno = lineno;
+    p->col_offset = col_offset;
+    return p;
+}
+
+arguments_ty
+arguments(asdl_seq * args, arg_ty vararg, asdl_seq * kwonlyargs, asdl_seq *
+          kw_defaults, arg_ty kwarg, asdl_seq * defaults, PyArena *arena)
+{
+    arguments_ty p;
+    p = (arguments_ty)PyArena_Malloc(arena, sizeof(*p));
+    if (!p)
+        return NULL;
+    p->args = args;
+    p->vararg = vararg;
+    p->kwonlyargs = kwonlyargs;
+    p->kw_defaults = kw_defaults;
+    p->kwarg = kwarg;
+    p->defaults = defaults;
+    return p;
+}
+
+arg_ty
+arg(identifier arg, expr_ty annotation, int lineno, int col_offset, PyArena
+    *arena)
+{
+    arg_ty p;
+    if (!arg) {
+        PyErr_SetString(PyExc_ValueError,
+                        "field arg is required for arg");
+        return NULL;
+    }
+    p = (arg_ty)PyArena_Malloc(arena, sizeof(*p));
+    if (!p)
+        return NULL;
+    p->arg = arg;
+    p->annotation = annotation;
+    p->lineno = lineno;
+    p->col_offset = col_offset;
+    return p;
+}
+
+keyword_ty
+keyword(identifier arg, expr_ty value, PyArena *arena)
+{
+    keyword_ty p;
+    if (!value) {
+        PyErr_SetString(PyExc_ValueError,
+                        "field value is required for keyword");
+        return NULL;
+    }
+    p = (keyword_ty)PyArena_Malloc(arena, sizeof(*p));
+    if (!p)
+        return NULL;
+    p->arg = arg;
+    p->value = value;
+    return p;
+}
+
+alias_ty
+alias(identifier name, identifier asname, PyArena *arena)
+{
+    alias_ty p;
+    if (!name) {
+        PyErr_SetString(PyExc_ValueError,
+                        "field name is required for alias");
+        return NULL;
+    }
+    p = (alias_ty)PyArena_Malloc(arena, sizeof(*p));
+    if (!p)
+        return NULL;
+    p->name = name;
+    p->asname = asname;
+    return p;
+}
+
+withitem_ty
+withitem(expr_ty context_expr, expr_ty optional_vars, PyArena *arena)
+{
+    withitem_ty p;
+    if (!context_expr) {
+        PyErr_SetString(PyExc_ValueError,
+                        "field context_expr is required for withitem");
+        return NULL;
+    }
+    p = (withitem_ty)PyArena_Malloc(arena, sizeof(*p));
+    if (!p)
+        return NULL;
+    p->context_expr = context_expr;
+    p->optional_vars = optional_vars;
+    return p;
+}
+
+type_ignore_ty
+TypeIgnore(int lineno, PyArena *arena)
+{
+    type_ignore_ty p;
+    p = (type_ignore_ty)PyArena_Malloc(arena, sizeof(*p));
+    if (!p)
+        return NULL;
+    p->kind = TypeIgnore_kind;
+    p->v.TypeIgnore.lineno = lineno;
+    return p;
+}
+
+
+PyObject*
+ast2obj_mod(void* _o)
+{
+    mod_ty o = (mod_ty)_o;
+    PyObject *result = NULL, *value = NULL;
+    if (!o) {
+        Py_INCREF(Py_None);
+        return Py_None;
+    }
+
+    switch (o->kind) {
+    case Module_kind:
+        result = PyType_GenericNew(Module_type, NULL, NULL);
+        if (!result) goto failed;
+        value = ast2obj_list(o->v.Module.body, ast2obj_stmt);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_body, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        value = ast2obj_list(o->v.Module.type_ignores, ast2obj_type_ignore);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_type_ignores, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        break;
+    case Interactive_kind:
+        result = PyType_GenericNew(Interactive_type, NULL, NULL);
+        if (!result) goto failed;
+        value = ast2obj_list(o->v.Interactive.body, ast2obj_stmt);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_body, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        break;
+    case Expression_kind:
+        result = PyType_GenericNew(Expression_type, NULL, NULL);
+        if (!result) goto failed;
+        value = ast2obj_expr(o->v.Expression.body);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_body, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        break;
+    case FunctionType_kind:
+        result = PyType_GenericNew(FunctionType_type, NULL, NULL);
+        if (!result) goto failed;
+        value = ast2obj_list(o->v.FunctionType.argtypes, ast2obj_expr);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_argtypes, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        value = ast2obj_expr(o->v.FunctionType.returns);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_returns, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        break;
+    case Suite_kind:
+        result = PyType_GenericNew(Suite_type, NULL, NULL);
+        if (!result) goto failed;
+        value = ast2obj_list(o->v.Suite.body, ast2obj_stmt);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_body, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        break;
+    }
+    return result;
+failed:
+    Py_XDECREF(value);
+    Py_XDECREF(result);
+    return NULL;
+}
+
+PyObject*
+ast2obj_stmt(void* _o)
+{
+    stmt_ty o = (stmt_ty)_o;
+    PyObject *result = NULL, *value = NULL;
+    if (!o) {
+        Py_INCREF(Py_None);
+        return Py_None;
+    }
+
+    switch (o->kind) {
+    case FunctionDef_kind:
+        result = PyType_GenericNew(FunctionDef_type, NULL, NULL);
+        if (!result) goto failed;
+        value = ast2obj_identifier(o->v.FunctionDef.name);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_name, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        value = ast2obj_arguments(o->v.FunctionDef.args);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_args, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        value = ast2obj_list(o->v.FunctionDef.body, ast2obj_stmt);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_body, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        value = ast2obj_list(o->v.FunctionDef.decorator_list, ast2obj_expr);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_decorator_list, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        value = ast2obj_expr(o->v.FunctionDef.returns);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_returns, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        value = ast2obj_string(o->v.FunctionDef.type_comment);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_type_comment, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        break;
+    case AsyncFunctionDef_kind:
+        result = PyType_GenericNew(AsyncFunctionDef_type, NULL, NULL);
+        if (!result) goto failed;
+        value = ast2obj_identifier(o->v.AsyncFunctionDef.name);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_name, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        value = ast2obj_arguments(o->v.AsyncFunctionDef.args);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_args, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        value = ast2obj_list(o->v.AsyncFunctionDef.body, ast2obj_stmt);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_body, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        value = ast2obj_list(o->v.AsyncFunctionDef.decorator_list,
+                             ast2obj_expr);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_decorator_list, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        value = ast2obj_expr(o->v.AsyncFunctionDef.returns);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_returns, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        value = ast2obj_string(o->v.AsyncFunctionDef.type_comment);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_type_comment, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        break;
+    case ClassDef_kind:
+        result = PyType_GenericNew(ClassDef_type, NULL, NULL);
+        if (!result) goto failed;
+        value = ast2obj_identifier(o->v.ClassDef.name);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_name, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        value = ast2obj_list(o->v.ClassDef.bases, ast2obj_expr);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_bases, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        value = ast2obj_list(o->v.ClassDef.keywords, ast2obj_keyword);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_keywords, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        value = ast2obj_list(o->v.ClassDef.body, ast2obj_stmt);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_body, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        value = ast2obj_list(o->v.ClassDef.decorator_list, ast2obj_expr);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_decorator_list, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        break;
+    case Return_kind:
+        result = PyType_GenericNew(Return_type, NULL, NULL);
+        if (!result) goto failed;
+        value = ast2obj_expr(o->v.Return.value);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_value, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        break;
+    case Delete_kind:
+        result = PyType_GenericNew(Delete_type, NULL, NULL);
+        if (!result) goto failed;
+        value = ast2obj_list(o->v.Delete.targets, ast2obj_expr);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_targets, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        break;
+    case Assign_kind:
+        result = PyType_GenericNew(Assign_type, NULL, NULL);
+        if (!result) goto failed;
+        value = ast2obj_list(o->v.Assign.targets, ast2obj_expr);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_targets, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        value = ast2obj_expr(o->v.Assign.value);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_value, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        value = ast2obj_string(o->v.Assign.type_comment);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_type_comment, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        break;
+    case AugAssign_kind:
+        result = PyType_GenericNew(AugAssign_type, NULL, NULL);
+        if (!result) goto failed;
+        value = ast2obj_expr(o->v.AugAssign.target);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_target, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        value = ast2obj_operator(o->v.AugAssign.op);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_op, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        value = ast2obj_expr(o->v.AugAssign.value);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_value, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        break;
+    case For_kind:
+        result = PyType_GenericNew(For_type, NULL, NULL);
+        if (!result) goto failed;
+        value = ast2obj_expr(o->v.For.target);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_target, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        value = ast2obj_expr(o->v.For.iter);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_iter, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        value = ast2obj_list(o->v.For.body, ast2obj_stmt);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_body, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        value = ast2obj_list(o->v.For.orelse, ast2obj_stmt);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_orelse, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        value = ast2obj_string(o->v.For.type_comment);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_type_comment, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        break;
+    case AsyncFor_kind:
+        result = PyType_GenericNew(AsyncFor_type, NULL, NULL);
+        if (!result) goto failed;
+        value = ast2obj_expr(o->v.AsyncFor.target);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_target, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        value = ast2obj_expr(o->v.AsyncFor.iter);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_iter, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        value = ast2obj_list(o->v.AsyncFor.body, ast2obj_stmt);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_body, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        value = ast2obj_list(o->v.AsyncFor.orelse, ast2obj_stmt);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_orelse, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        break;
+    case While_kind:
+        result = PyType_GenericNew(While_type, NULL, NULL);
+        if (!result) goto failed;
+        value = ast2obj_expr(o->v.While.test);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_test, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        value = ast2obj_list(o->v.While.body, ast2obj_stmt);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_body, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        value = ast2obj_list(o->v.While.orelse, ast2obj_stmt);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_orelse, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        break;
+    case If_kind:
+        result = PyType_GenericNew(If_type, NULL, NULL);
+        if (!result) goto failed;
+        value = ast2obj_expr(o->v.If.test);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_test, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        value = ast2obj_list(o->v.If.body, ast2obj_stmt);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_body, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        value = ast2obj_list(o->v.If.orelse, ast2obj_stmt);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_orelse, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        break;
+    case With_kind:
+        result = PyType_GenericNew(With_type, NULL, NULL);
+        if (!result) goto failed;
+        value = ast2obj_list(o->v.With.items, ast2obj_withitem);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_items, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        value = ast2obj_list(o->v.With.body, ast2obj_stmt);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_body, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        value = ast2obj_string(o->v.With.type_comment);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_type_comment, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        break;
+    case AsyncWith_kind:
+        result = PyType_GenericNew(AsyncWith_type, NULL, NULL);
+        if (!result) goto failed;
+        value = ast2obj_list(o->v.AsyncWith.items, ast2obj_withitem);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_items, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        value = ast2obj_list(o->v.AsyncWith.body, ast2obj_stmt);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_body, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        break;
+    case Raise_kind:
+        result = PyType_GenericNew(Raise_type, NULL, NULL);
+        if (!result) goto failed;
+        value = ast2obj_expr(o->v.Raise.exc);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_exc, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        value = ast2obj_expr(o->v.Raise.cause);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_cause, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        break;
+    case Try_kind:
+        result = PyType_GenericNew(Try_type, NULL, NULL);
+        if (!result) goto failed;
+        value = ast2obj_list(o->v.Try.body, ast2obj_stmt);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_body, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        value = ast2obj_list(o->v.Try.handlers, ast2obj_excepthandler);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_handlers, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        value = ast2obj_list(o->v.Try.orelse, ast2obj_stmt);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_orelse, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        value = ast2obj_list(o->v.Try.finalbody, ast2obj_stmt);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_finalbody, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        break;
+    case Assert_kind:
+        result = PyType_GenericNew(Assert_type, NULL, NULL);
+        if (!result) goto failed;
+        value = ast2obj_expr(o->v.Assert.test);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_test, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        value = ast2obj_expr(o->v.Assert.msg);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_msg, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        break;
+    case Import_kind:
+        result = PyType_GenericNew(Import_type, NULL, NULL);
+        if (!result) goto failed;
+        value = ast2obj_list(o->v.Import.names, ast2obj_alias);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_names, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        break;
+    case ImportFrom_kind:
+        result = PyType_GenericNew(ImportFrom_type, NULL, NULL);
+        if (!result) goto failed;
+        value = ast2obj_identifier(o->v.ImportFrom.module);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_module, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        value = ast2obj_list(o->v.ImportFrom.names, ast2obj_alias);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_names, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        value = ast2obj_int(o->v.ImportFrom.level);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_level, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        break;
+    case Global_kind:
+        result = PyType_GenericNew(Global_type, NULL, NULL);
+        if (!result) goto failed;
+        value = ast2obj_list(o->v.Global.names, ast2obj_identifier);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_names, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        break;
+    case Nonlocal_kind:
+        result = PyType_GenericNew(Nonlocal_type, NULL, NULL);
+        if (!result) goto failed;
+        value = ast2obj_list(o->v.Nonlocal.names, ast2obj_identifier);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_names, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        break;
+    case Expr_kind:
+        result = PyType_GenericNew(Expr_type, NULL, NULL);
+        if (!result) goto failed;
+        value = ast2obj_expr(o->v.Expr.value);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_value, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        break;
+    case Pass_kind:
+        result = PyType_GenericNew(Pass_type, NULL, NULL);
+        if (!result) goto failed;
+        break;
+    case Break_kind:
+        result = PyType_GenericNew(Break_type, NULL, NULL);
+        if (!result) goto failed;
+        break;
+    case Continue_kind:
+        result = PyType_GenericNew(Continue_type, NULL, NULL);
+        if (!result) goto failed;
+        break;
+    }
+    value = ast2obj_int(o->lineno);
+    if (!value) goto failed;
+    if (_PyObject_SetAttrId(result, &PyId_lineno, value) < 0)
+        goto failed;
+    Py_DECREF(value);
+    value = ast2obj_int(o->col_offset);
+    if (!value) goto failed;
+    if (_PyObject_SetAttrId(result, &PyId_col_offset, value) < 0)
+        goto failed;
+    Py_DECREF(value);
+    return result;
+failed:
+    Py_XDECREF(value);
+    Py_XDECREF(result);
+    return NULL;
+}
+
+PyObject*
+ast2obj_expr(void* _o)
+{
+    expr_ty o = (expr_ty)_o;
+    PyObject *result = NULL, *value = NULL;
+    if (!o) {
+        Py_INCREF(Py_None);
+        return Py_None;
+    }
+
+    switch (o->kind) {
+    case BoolOp_kind:
+        result = PyType_GenericNew(BoolOp_type, NULL, NULL);
+        if (!result) goto failed;
+        value = ast2obj_boolop(o->v.BoolOp.op);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_op, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        value = ast2obj_list(o->v.BoolOp.values, ast2obj_expr);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_values, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        break;
+    case BinOp_kind:
+        result = PyType_GenericNew(BinOp_type, NULL, NULL);
+        if (!result) goto failed;
+        value = ast2obj_expr(o->v.BinOp.left);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_left, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        value = ast2obj_operator(o->v.BinOp.op);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_op, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        value = ast2obj_expr(o->v.BinOp.right);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_right, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        break;
+    case UnaryOp_kind:
+        result = PyType_GenericNew(UnaryOp_type, NULL, NULL);
+        if (!result) goto failed;
+        value = ast2obj_unaryop(o->v.UnaryOp.op);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_op, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        value = ast2obj_expr(o->v.UnaryOp.operand);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_operand, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        break;
+    case Lambda_kind:
+        result = PyType_GenericNew(Lambda_type, NULL, NULL);
+        if (!result) goto failed;
+        value = ast2obj_arguments(o->v.Lambda.args);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_args, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        value = ast2obj_expr(o->v.Lambda.body);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_body, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        break;
+    case IfExp_kind:
+        result = PyType_GenericNew(IfExp_type, NULL, NULL);
+        if (!result) goto failed;
+        value = ast2obj_expr(o->v.IfExp.test);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_test, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        value = ast2obj_expr(o->v.IfExp.body);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_body, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        value = ast2obj_expr(o->v.IfExp.orelse);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_orelse, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        break;
+    case Dict_kind:
+        result = PyType_GenericNew(Dict_type, NULL, NULL);
+        if (!result) goto failed;
+        value = ast2obj_list(o->v.Dict.keys, ast2obj_expr);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_keys, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        value = ast2obj_list(o->v.Dict.values, ast2obj_expr);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_values, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        break;
+    case Set_kind:
+        result = PyType_GenericNew(Set_type, NULL, NULL);
+        if (!result) goto failed;
+        value = ast2obj_list(o->v.Set.elts, ast2obj_expr);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_elts, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        break;
+    case ListComp_kind:
+        result = PyType_GenericNew(ListComp_type, NULL, NULL);
+        if (!result) goto failed;
+        value = ast2obj_expr(o->v.ListComp.elt);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_elt, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        value = ast2obj_list(o->v.ListComp.generators, ast2obj_comprehension);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_generators, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        break;
+    case SetComp_kind:
+        result = PyType_GenericNew(SetComp_type, NULL, NULL);
+        if (!result) goto failed;
+        value = ast2obj_expr(o->v.SetComp.elt);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_elt, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        value = ast2obj_list(o->v.SetComp.generators, ast2obj_comprehension);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_generators, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        break;
+    case DictComp_kind:
+        result = PyType_GenericNew(DictComp_type, NULL, NULL);
+        if (!result) goto failed;
+        value = ast2obj_expr(o->v.DictComp.key);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_key, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        value = ast2obj_expr(o->v.DictComp.value);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_value, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        value = ast2obj_list(o->v.DictComp.generators, ast2obj_comprehension);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_generators, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        break;
+    case GeneratorExp_kind:
+        result = PyType_GenericNew(GeneratorExp_type, NULL, NULL);
+        if (!result) goto failed;
+        value = ast2obj_expr(o->v.GeneratorExp.elt);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_elt, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        value = ast2obj_list(o->v.GeneratorExp.generators,
+                             ast2obj_comprehension);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_generators, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        break;
+    case Await_kind:
+        result = PyType_GenericNew(Await_type, NULL, NULL);
+        if (!result) goto failed;
+        value = ast2obj_expr(o->v.Await.value);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_value, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        break;
+    case Yield_kind:
+        result = PyType_GenericNew(Yield_type, NULL, NULL);
+        if (!result) goto failed;
+        value = ast2obj_expr(o->v.Yield.value);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_value, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        break;
+    case YieldFrom_kind:
+        result = PyType_GenericNew(YieldFrom_type, NULL, NULL);
+        if (!result) goto failed;
+        value = ast2obj_expr(o->v.YieldFrom.value);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_value, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        break;
+    case Compare_kind:
+        result = PyType_GenericNew(Compare_type, NULL, NULL);
+        if (!result) goto failed;
+        value = ast2obj_expr(o->v.Compare.left);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_left, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        {
+            Py_ssize_t i, n = asdl_seq_LEN(o->v.Compare.ops);
+            value = PyList_New(n);
+            if (!value) goto failed;
+            for(i = 0; i < n; i++)
+                PyList_SET_ITEM(value, i, ast2obj_cmpop((cmpop_ty)asdl_seq_GET(o->v.Compare.ops, i)));
+        }
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_ops, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        value = ast2obj_list(o->v.Compare.comparators, ast2obj_expr);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_comparators, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        break;
+    case Call_kind:
+        result = PyType_GenericNew(Call_type, NULL, NULL);
+        if (!result) goto failed;
+        value = ast2obj_expr(o->v.Call.func);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_func, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        value = ast2obj_list(o->v.Call.args, ast2obj_expr);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_args, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        value = ast2obj_list(o->v.Call.keywords, ast2obj_keyword);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_keywords, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        break;
+    case Num_kind:
+        result = PyType_GenericNew(Num_type, NULL, NULL);
+        if (!result) goto failed;
+        value = ast2obj_object(o->v.Num.n);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_n, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        break;
+    case Str_kind:
+        result = PyType_GenericNew(Str_type, NULL, NULL);
+        if (!result) goto failed;
+        value = ast2obj_string(o->v.Str.s);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_s, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        break;
+    case Bytes_kind:
+        result = PyType_GenericNew(Bytes_type, NULL, NULL);
+        if (!result) goto failed;
+        value = ast2obj_bytes(o->v.Bytes.s);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_s, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        break;
+    case NameConstant_kind:
+        result = PyType_GenericNew(NameConstant_type, NULL, NULL);
+        if (!result) goto failed;
+        value = ast2obj_singleton(o->v.NameConstant.value);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_value, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        break;
+    case Ellipsis_kind:
+        result = PyType_GenericNew(Ellipsis_type, NULL, NULL);
+        if (!result) goto failed;
+        break;
+    case Attribute_kind:
+        result = PyType_GenericNew(Attribute_type, NULL, NULL);
+        if (!result) goto failed;
+        value = ast2obj_expr(o->v.Attribute.value);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_value, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        value = ast2obj_identifier(o->v.Attribute.attr);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_attr, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        value = ast2obj_expr_context(o->v.Attribute.ctx);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_ctx, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        break;
+    case Subscript_kind:
+        result = PyType_GenericNew(Subscript_type, NULL, NULL);
+        if (!result) goto failed;
+        value = ast2obj_expr(o->v.Subscript.value);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_value, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        value = ast2obj_slice(o->v.Subscript.slice);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_slice, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        value = ast2obj_expr_context(o->v.Subscript.ctx);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_ctx, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        break;
+    case Starred_kind:
+        result = PyType_GenericNew(Starred_type, NULL, NULL);
+        if (!result) goto failed;
+        value = ast2obj_expr(o->v.Starred.value);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_value, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        value = ast2obj_expr_context(o->v.Starred.ctx);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_ctx, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        break;
+    case Name_kind:
+        result = PyType_GenericNew(Name_type, NULL, NULL);
+        if (!result) goto failed;
+        value = ast2obj_identifier(o->v.Name.id);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_id, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        value = ast2obj_expr_context(o->v.Name.ctx);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_ctx, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        break;
+    case List_kind:
+        result = PyType_GenericNew(List_type, NULL, NULL);
+        if (!result) goto failed;
+        value = ast2obj_list(o->v.List.elts, ast2obj_expr);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_elts, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        value = ast2obj_expr_context(o->v.List.ctx);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_ctx, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        break;
+    case Tuple_kind:
+        result = PyType_GenericNew(Tuple_type, NULL, NULL);
+        if (!result) goto failed;
+        value = ast2obj_list(o->v.Tuple.elts, ast2obj_expr);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_elts, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        value = ast2obj_expr_context(o->v.Tuple.ctx);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_ctx, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        break;
+    }
+    value = ast2obj_int(o->lineno);
+    if (!value) goto failed;
+    if (_PyObject_SetAttrId(result, &PyId_lineno, value) < 0)
+        goto failed;
+    Py_DECREF(value);
+    value = ast2obj_int(o->col_offset);
+    if (!value) goto failed;
+    if (_PyObject_SetAttrId(result, &PyId_col_offset, value) < 0)
+        goto failed;
+    Py_DECREF(value);
+    return result;
+failed:
+    Py_XDECREF(value);
+    Py_XDECREF(result);
+    return NULL;
+}
+
+PyObject* ast2obj_expr_context(expr_context_ty o)
+{
+    switch(o) {
+        case Load:
+            Py_INCREF(Load_singleton);
+            return Load_singleton;
+        case Store:
+            Py_INCREF(Store_singleton);
+            return Store_singleton;
+        case Del:
+            Py_INCREF(Del_singleton);
+            return Del_singleton;
+        case AugLoad:
+            Py_INCREF(AugLoad_singleton);
+            return AugLoad_singleton;
+        case AugStore:
+            Py_INCREF(AugStore_singleton);
+            return AugStore_singleton;
+        case Param:
+            Py_INCREF(Param_singleton);
+            return Param_singleton;
+        default:
+            /* should never happen, but just in case ... */
+            PyErr_Format(PyExc_SystemError, "unknown expr_context found");
+            return NULL;
+    }
+}
+PyObject*
+ast2obj_slice(void* _o)
+{
+    slice_ty o = (slice_ty)_o;
+    PyObject *result = NULL, *value = NULL;
+    if (!o) {
+        Py_INCREF(Py_None);
+        return Py_None;
+    }
+
+    switch (o->kind) {
+    case Slice_kind:
+        result = PyType_GenericNew(Slice_type, NULL, NULL);
+        if (!result) goto failed;
+        value = ast2obj_expr(o->v.Slice.lower);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_lower, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        value = ast2obj_expr(o->v.Slice.upper);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_upper, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        value = ast2obj_expr(o->v.Slice.step);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_step, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        break;
+    case ExtSlice_kind:
+        result = PyType_GenericNew(ExtSlice_type, NULL, NULL);
+        if (!result) goto failed;
+        value = ast2obj_list(o->v.ExtSlice.dims, ast2obj_slice);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_dims, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        break;
+    case Index_kind:
+        result = PyType_GenericNew(Index_type, NULL, NULL);
+        if (!result) goto failed;
+        value = ast2obj_expr(o->v.Index.value);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_value, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        break;
+    }
+    return result;
+failed:
+    Py_XDECREF(value);
+    Py_XDECREF(result);
+    return NULL;
+}
+
+PyObject* ast2obj_boolop(boolop_ty o)
+{
+    switch(o) {
+        case And:
+            Py_INCREF(And_singleton);
+            return And_singleton;
+        case Or:
+            Py_INCREF(Or_singleton);
+            return Or_singleton;
+        default:
+            /* should never happen, but just in case ... */
+            PyErr_Format(PyExc_SystemError, "unknown boolop found");
+            return NULL;
+    }
+}
+PyObject* ast2obj_operator(operator_ty o)
+{
+    switch(o) {
+        case Add:
+            Py_INCREF(Add_singleton);
+            return Add_singleton;
+        case Sub:
+            Py_INCREF(Sub_singleton);
+            return Sub_singleton;
+        case Mult:
+            Py_INCREF(Mult_singleton);
+            return Mult_singleton;
+        case MatMult:
+            Py_INCREF(MatMult_singleton);
+            return MatMult_singleton;
+        case Div:
+            Py_INCREF(Div_singleton);
+            return Div_singleton;
+        case Mod:
+            Py_INCREF(Mod_singleton);
+            return Mod_singleton;
+        case Pow:
+            Py_INCREF(Pow_singleton);
+            return Pow_singleton;
+        case LShift:
+            Py_INCREF(LShift_singleton);
+            return LShift_singleton;
+        case RShift:
+            Py_INCREF(RShift_singleton);
+            return RShift_singleton;
+        case BitOr:
+            Py_INCREF(BitOr_singleton);
+            return BitOr_singleton;
+        case BitXor:
+            Py_INCREF(BitXor_singleton);
+            return BitXor_singleton;
+        case BitAnd:
+            Py_INCREF(BitAnd_singleton);
+            return BitAnd_singleton;
+        case FloorDiv:
+            Py_INCREF(FloorDiv_singleton);
+            return FloorDiv_singleton;
+        default:
+            /* should never happen, but just in case ... */
+            PyErr_Format(PyExc_SystemError, "unknown operator found");
+            return NULL;
+    }
+}
+PyObject* ast2obj_unaryop(unaryop_ty o)
+{
+    switch(o) {
+        case Invert:
+            Py_INCREF(Invert_singleton);
+            return Invert_singleton;
+        case Not:
+            Py_INCREF(Not_singleton);
+            return Not_singleton;
+        case UAdd:
+            Py_INCREF(UAdd_singleton);
+            return UAdd_singleton;
+        case USub:
+            Py_INCREF(USub_singleton);
+            return USub_singleton;
+        default:
+            /* should never happen, but just in case ... */
+            PyErr_Format(PyExc_SystemError, "unknown unaryop found");
+            return NULL;
+    }
+}
+PyObject* ast2obj_cmpop(cmpop_ty o)
+{
+    switch(o) {
+        case Eq:
+            Py_INCREF(Eq_singleton);
+            return Eq_singleton;
+        case NotEq:
+            Py_INCREF(NotEq_singleton);
+            return NotEq_singleton;
+        case Lt:
+            Py_INCREF(Lt_singleton);
+            return Lt_singleton;
+        case LtE:
+            Py_INCREF(LtE_singleton);
+            return LtE_singleton;
+        case Gt:
+            Py_INCREF(Gt_singleton);
+            return Gt_singleton;
+        case GtE:
+            Py_INCREF(GtE_singleton);
+            return GtE_singleton;
+        case Is:
+            Py_INCREF(Is_singleton);
+            return Is_singleton;
+        case IsNot:
+            Py_INCREF(IsNot_singleton);
+            return IsNot_singleton;
+        case In:
+            Py_INCREF(In_singleton);
+            return In_singleton;
+        case NotIn:
+            Py_INCREF(NotIn_singleton);
+            return NotIn_singleton;
+        default:
+            /* should never happen, but just in case ... */
+            PyErr_Format(PyExc_SystemError, "unknown cmpop found");
+            return NULL;
+    }
+}
+PyObject*
+ast2obj_comprehension(void* _o)
+{
+    comprehension_ty o = (comprehension_ty)_o;
+    PyObject *result = NULL, *value = NULL;
+    if (!o) {
+        Py_INCREF(Py_None);
+        return Py_None;
+    }
+
+    result = PyType_GenericNew(comprehension_type, NULL, NULL);
+    if (!result) return NULL;
+    value = ast2obj_expr(o->target);
+    if (!value) goto failed;
+    if (_PyObject_SetAttrId(result, &PyId_target, value) == -1)
+        goto failed;
+    Py_DECREF(value);
+    value = ast2obj_expr(o->iter);
+    if (!value) goto failed;
+    if (_PyObject_SetAttrId(result, &PyId_iter, value) == -1)
+        goto failed;
+    Py_DECREF(value);
+    value = ast2obj_list(o->ifs, ast2obj_expr);
+    if (!value) goto failed;
+    if (_PyObject_SetAttrId(result, &PyId_ifs, value) == -1)
+        goto failed;
+    Py_DECREF(value);
+    return result;
+failed:
+    Py_XDECREF(value);
+    Py_XDECREF(result);
+    return NULL;
+}
+
+PyObject*
+ast2obj_excepthandler(void* _o)
+{
+    excepthandler_ty o = (excepthandler_ty)_o;
+    PyObject *result = NULL, *value = NULL;
+    if (!o) {
+        Py_INCREF(Py_None);
+        return Py_None;
+    }
+
+    switch (o->kind) {
+    case ExceptHandler_kind:
+        result = PyType_GenericNew(ExceptHandler_type, NULL, NULL);
+        if (!result) goto failed;
+        value = ast2obj_expr(o->v.ExceptHandler.type);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_type, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        value = ast2obj_identifier(o->v.ExceptHandler.name);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_name, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        value = ast2obj_list(o->v.ExceptHandler.body, ast2obj_stmt);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_body, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        break;
+    }
+    value = ast2obj_int(o->lineno);
+    if (!value) goto failed;
+    if (_PyObject_SetAttrId(result, &PyId_lineno, value) < 0)
+        goto failed;
+    Py_DECREF(value);
+    value = ast2obj_int(o->col_offset);
+    if (!value) goto failed;
+    if (_PyObject_SetAttrId(result, &PyId_col_offset, value) < 0)
+        goto failed;
+    Py_DECREF(value);
+    return result;
+failed:
+    Py_XDECREF(value);
+    Py_XDECREF(result);
+    return NULL;
+}
+
+PyObject*
+ast2obj_arguments(void* _o)
+{
+    arguments_ty o = (arguments_ty)_o;
+    PyObject *result = NULL, *value = NULL;
+    if (!o) {
+        Py_INCREF(Py_None);
+        return Py_None;
+    }
+
+    result = PyType_GenericNew(arguments_type, NULL, NULL);
+    if (!result) return NULL;
+    value = ast2obj_list(o->args, ast2obj_arg);
+    if (!value) goto failed;
+    if (_PyObject_SetAttrId(result, &PyId_args, value) == -1)
+        goto failed;
+    Py_DECREF(value);
+    value = ast2obj_arg(o->vararg);
+    if (!value) goto failed;
+    if (_PyObject_SetAttrId(result, &PyId_vararg, value) == -1)
+        goto failed;
+    Py_DECREF(value);
+    value = ast2obj_list(o->kwonlyargs, ast2obj_arg);
+    if (!value) goto failed;
+    if (_PyObject_SetAttrId(result, &PyId_kwonlyargs, value) == -1)
+        goto failed;
+    Py_DECREF(value);
+    value = ast2obj_list(o->kw_defaults, ast2obj_expr);
+    if (!value) goto failed;
+    if (_PyObject_SetAttrId(result, &PyId_kw_defaults, value) == -1)
+        goto failed;
+    Py_DECREF(value);
+    value = ast2obj_arg(o->kwarg);
+    if (!value) goto failed;
+    if (_PyObject_SetAttrId(result, &PyId_kwarg, value) == -1)
+        goto failed;
+    Py_DECREF(value);
+    value = ast2obj_list(o->defaults, ast2obj_expr);
+    if (!value) goto failed;
+    if (_PyObject_SetAttrId(result, &PyId_defaults, value) == -1)
+        goto failed;
+    Py_DECREF(value);
+    return result;
+failed:
+    Py_XDECREF(value);
+    Py_XDECREF(result);
+    return NULL;
+}
+
+PyObject*
+ast2obj_arg(void* _o)
+{
+    arg_ty o = (arg_ty)_o;
+    PyObject *result = NULL, *value = NULL;
+    if (!o) {
+        Py_INCREF(Py_None);
+        return Py_None;
+    }
+
+    result = PyType_GenericNew(arg_type, NULL, NULL);
+    if (!result) return NULL;
+    value = ast2obj_identifier(o->arg);
+    if (!value) goto failed;
+    if (_PyObject_SetAttrId(result, &PyId_arg, value) == -1)
+        goto failed;
+    Py_DECREF(value);
+    value = ast2obj_expr(o->annotation);
+    if (!value) goto failed;
+    if (_PyObject_SetAttrId(result, &PyId_annotation, value) == -1)
+        goto failed;
+    Py_DECREF(value);
+    value = ast2obj_int(o->lineno);
+    if (!value) goto failed;
+    if (_PyObject_SetAttrId(result, &PyId_lineno, value) < 0)
+        goto failed;
+    Py_DECREF(value);
+    value = ast2obj_int(o->col_offset);
+    if (!value) goto failed;
+    if (_PyObject_SetAttrId(result, &PyId_col_offset, value) < 0)
+        goto failed;
+    Py_DECREF(value);
+    return result;
+failed:
+    Py_XDECREF(value);
+    Py_XDECREF(result);
+    return NULL;
+}
+
+PyObject*
+ast2obj_keyword(void* _o)
+{
+    keyword_ty o = (keyword_ty)_o;
+    PyObject *result = NULL, *value = NULL;
+    if (!o) {
+        Py_INCREF(Py_None);
+        return Py_None;
+    }
+
+    result = PyType_GenericNew(keyword_type, NULL, NULL);
+    if (!result) return NULL;
+    value = ast2obj_identifier(o->arg);
+    if (!value) goto failed;
+    if (_PyObject_SetAttrId(result, &PyId_arg, value) == -1)
+        goto failed;
+    Py_DECREF(value);
+    value = ast2obj_expr(o->value);
+    if (!value) goto failed;
+    if (_PyObject_SetAttrId(result, &PyId_value, value) == -1)
+        goto failed;
+    Py_DECREF(value);
+    return result;
+failed:
+    Py_XDECREF(value);
+    Py_XDECREF(result);
+    return NULL;
+}
+
+PyObject*
+ast2obj_alias(void* _o)
+{
+    alias_ty o = (alias_ty)_o;
+    PyObject *result = NULL, *value = NULL;
+    if (!o) {
+        Py_INCREF(Py_None);
+        return Py_None;
+    }
+
+    result = PyType_GenericNew(alias_type, NULL, NULL);
+    if (!result) return NULL;
+    value = ast2obj_identifier(o->name);
+    if (!value) goto failed;
+    if (_PyObject_SetAttrId(result, &PyId_name, value) == -1)
+        goto failed;
+    Py_DECREF(value);
+    value = ast2obj_identifier(o->asname);
+    if (!value) goto failed;
+    if (_PyObject_SetAttrId(result, &PyId_asname, value) == -1)
+        goto failed;
+    Py_DECREF(value);
+    return result;
+failed:
+    Py_XDECREF(value);
+    Py_XDECREF(result);
+    return NULL;
+}
+
+PyObject*
+ast2obj_withitem(void* _o)
+{
+    withitem_ty o = (withitem_ty)_o;
+    PyObject *result = NULL, *value = NULL;
+    if (!o) {
+        Py_INCREF(Py_None);
+        return Py_None;
+    }
+
+    result = PyType_GenericNew(withitem_type, NULL, NULL);
+    if (!result) return NULL;
+    value = ast2obj_expr(o->context_expr);
+    if (!value) goto failed;
+    if (_PyObject_SetAttrId(result, &PyId_context_expr, value) == -1)
+        goto failed;
+    Py_DECREF(value);
+    value = ast2obj_expr(o->optional_vars);
+    if (!value) goto failed;
+    if (_PyObject_SetAttrId(result, &PyId_optional_vars, value) == -1)
+        goto failed;
+    Py_DECREF(value);
+    return result;
+failed:
+    Py_XDECREF(value);
+    Py_XDECREF(result);
+    return NULL;
+}
+
+PyObject*
+ast2obj_type_ignore(void* _o)
+{
+    type_ignore_ty o = (type_ignore_ty)_o;
+    PyObject *result = NULL, *value = NULL;
+    if (!o) {
+        Py_INCREF(Py_None);
+        return Py_None;
+    }
+
+    switch (o->kind) {
+    case TypeIgnore_kind:
+        result = PyType_GenericNew(TypeIgnore_type, NULL, NULL);
+        if (!result) goto failed;
+        value = ast2obj_int(o->v.TypeIgnore.lineno);
+        if (!value) goto failed;
+        if (_PyObject_SetAttrId(result, &PyId_lineno, value) == -1)
+            goto failed;
+        Py_DECREF(value);
+        break;
+    }
+    return result;
+failed:
+    Py_XDECREF(value);
+    Py_XDECREF(result);
+    return NULL;
+}
+
+
+int
+obj2ast_mod(PyObject* obj, mod_ty* out, PyArena* arena)
+{
+    int isinstance;
+
+    PyObject *tmp = NULL;
+
+    if (obj == Py_None) {
+        *out = NULL;
+        return 0;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject*)Module_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        asdl_seq* body;
+        asdl_seq* type_ignores;
+
+        if (_PyObject_HasAttrId(obj, &PyId_body)) {
+            int res;
+            Py_ssize_t len;
+            Py_ssize_t i;
+            tmp = _PyObject_GetAttrId(obj, &PyId_body);
+            if (tmp == NULL) goto failed;
+            if (!PyList_Check(tmp)) {
+                PyErr_Format(PyExc_TypeError, "Module field \"body\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                goto failed;
+            }
+            len = PyList_GET_SIZE(tmp);
+            body = _Py_asdl_seq_new(len, arena);
+            if (body == NULL) goto failed;
+            for (i = 0; i < len; i++) {
+                stmt_ty value;
+                res = obj2ast_stmt(PyList_GET_ITEM(tmp, i), &value, arena);
+                if (res != 0) goto failed;
+                asdl_seq_SET(body, i, value);
+            }
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"body\" missing from Module");
+            return 1;
+        }
+        if (_PyObject_HasAttrId(obj, &PyId_type_ignores)) {
+            int res;
+            Py_ssize_t len;
+            Py_ssize_t i;
+            tmp = _PyObject_GetAttrId(obj, &PyId_type_ignores);
+            if (tmp == NULL) goto failed;
+            if (!PyList_Check(tmp)) {
+                PyErr_Format(PyExc_TypeError, "Module field \"type_ignores\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                goto failed;
+            }
+            len = PyList_GET_SIZE(tmp);
+            type_ignores = _Py_asdl_seq_new(len, arena);
+            if (type_ignores == NULL) goto failed;
+            for (i = 0; i < len; i++) {
+                type_ignore_ty value;
+                res = obj2ast_type_ignore(PyList_GET_ITEM(tmp, i), &value, arena);
+                if (res != 0) goto failed;
+                asdl_seq_SET(type_ignores, i, value);
+            }
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"type_ignores\" missing from Module");
+            return 1;
+        }
+        *out = Module(body, type_ignores, arena);
+        if (*out == NULL) goto failed;
+        return 0;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject*)Interactive_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        asdl_seq* body;
+
+        if (_PyObject_HasAttrId(obj, &PyId_body)) {
+            int res;
+            Py_ssize_t len;
+            Py_ssize_t i;
+            tmp = _PyObject_GetAttrId(obj, &PyId_body);
+            if (tmp == NULL) goto failed;
+            if (!PyList_Check(tmp)) {
+                PyErr_Format(PyExc_TypeError, "Interactive field \"body\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                goto failed;
+            }
+            len = PyList_GET_SIZE(tmp);
+            body = _Py_asdl_seq_new(len, arena);
+            if (body == NULL) goto failed;
+            for (i = 0; i < len; i++) {
+                stmt_ty value;
+                res = obj2ast_stmt(PyList_GET_ITEM(tmp, i), &value, arena);
+                if (res != 0) goto failed;
+                asdl_seq_SET(body, i, value);
+            }
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"body\" missing from Interactive");
+            return 1;
+        }
+        *out = Interactive(body, arena);
+        if (*out == NULL) goto failed;
+        return 0;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject*)Expression_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        expr_ty body;
+
+        if (_PyObject_HasAttrId(obj, &PyId_body)) {
+            int res;
+            tmp = _PyObject_GetAttrId(obj, &PyId_body);
+            if (tmp == NULL) goto failed;
+            res = obj2ast_expr(tmp, &body, arena);
+            if (res != 0) goto failed;
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"body\" missing from Expression");
+            return 1;
+        }
+        *out = Expression(body, arena);
+        if (*out == NULL) goto failed;
+        return 0;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject*)FunctionType_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        asdl_seq* argtypes;
+        expr_ty returns;
+
+        if (_PyObject_HasAttrId(obj, &PyId_argtypes)) {
+            int res;
+            Py_ssize_t len;
+            Py_ssize_t i;
+            tmp = _PyObject_GetAttrId(obj, &PyId_argtypes);
+            if (tmp == NULL) goto failed;
+            if (!PyList_Check(tmp)) {
+                PyErr_Format(PyExc_TypeError, "FunctionType field \"argtypes\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                goto failed;
+            }
+            len = PyList_GET_SIZE(tmp);
+            argtypes = _Py_asdl_seq_new(len, arena);
+            if (argtypes == NULL) goto failed;
+            for (i = 0; i < len; i++) {
+                expr_ty value;
+                res = obj2ast_expr(PyList_GET_ITEM(tmp, i), &value, arena);
+                if (res != 0) goto failed;
+                asdl_seq_SET(argtypes, i, value);
+            }
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"argtypes\" missing from FunctionType");
+            return 1;
+        }
+        if (_PyObject_HasAttrId(obj, &PyId_returns)) {
+            int res;
+            tmp = _PyObject_GetAttrId(obj, &PyId_returns);
+            if (tmp == NULL) goto failed;
+            res = obj2ast_expr(tmp, &returns, arena);
+            if (res != 0) goto failed;
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"returns\" missing from FunctionType");
+            return 1;
+        }
+        *out = FunctionType(argtypes, returns, arena);
+        if (*out == NULL) goto failed;
+        return 0;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject*)Suite_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        asdl_seq* body;
+
+        if (_PyObject_HasAttrId(obj, &PyId_body)) {
+            int res;
+            Py_ssize_t len;
+            Py_ssize_t i;
+            tmp = _PyObject_GetAttrId(obj, &PyId_body);
+            if (tmp == NULL) goto failed;
+            if (!PyList_Check(tmp)) {
+                PyErr_Format(PyExc_TypeError, "Suite field \"body\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                goto failed;
+            }
+            len = PyList_GET_SIZE(tmp);
+            body = _Py_asdl_seq_new(len, arena);
+            if (body == NULL) goto failed;
+            for (i = 0; i < len; i++) {
+                stmt_ty value;
+                res = obj2ast_stmt(PyList_GET_ITEM(tmp, i), &value, arena);
+                if (res != 0) goto failed;
+                asdl_seq_SET(body, i, value);
+            }
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"body\" missing from Suite");
+            return 1;
+        }
+        *out = Suite(body, arena);
+        if (*out == NULL) goto failed;
+        return 0;
+    }
+
+    PyErr_Format(PyExc_TypeError, "expected some sort of mod, but got %R", obj);
+    failed:
+    Py_XDECREF(tmp);
+    return 1;
+}
+
+int
+obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena)
+{
+    int isinstance;
+
+    PyObject *tmp = NULL;
+    int lineno;
+    int col_offset;
+
+    if (obj == Py_None) {
+        *out = NULL;
+        return 0;
+    }
+    if (_PyObject_HasAttrId(obj, &PyId_lineno)) {
+        int res;
+        tmp = _PyObject_GetAttrId(obj, &PyId_lineno);
+        if (tmp == NULL) goto failed;
+        res = obj2ast_int(tmp, &lineno, arena);
+        if (res != 0) goto failed;
+        Py_CLEAR(tmp);
+    } else {
+        PyErr_SetString(PyExc_TypeError, "required field \"lineno\" missing from stmt");
+        return 1;
+    }
+    if (_PyObject_HasAttrId(obj, &PyId_col_offset)) {
+        int res;
+        tmp = _PyObject_GetAttrId(obj, &PyId_col_offset);
+        if (tmp == NULL) goto failed;
+        res = obj2ast_int(tmp, &col_offset, arena);
+        if (res != 0) goto failed;
+        Py_CLEAR(tmp);
+    } else {
+        PyErr_SetString(PyExc_TypeError, "required field \"col_offset\" missing from stmt");
+        return 1;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject*)FunctionDef_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        identifier name;
+        arguments_ty args;
+        asdl_seq* body;
+        asdl_seq* decorator_list;
+        expr_ty returns;
+        string type_comment;
+
+        if (_PyObject_HasAttrId(obj, &PyId_name)) {
+            int res;
+            tmp = _PyObject_GetAttrId(obj, &PyId_name);
+            if (tmp == NULL) goto failed;
+            res = obj2ast_identifier(tmp, &name, arena);
+            if (res != 0) goto failed;
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"name\" missing from FunctionDef");
+            return 1;
+        }
+        if (_PyObject_HasAttrId(obj, &PyId_args)) {
+            int res;
+            tmp = _PyObject_GetAttrId(obj, &PyId_args);
+            if (tmp == NULL) goto failed;
+            res = obj2ast_arguments(tmp, &args, arena);
+            if (res != 0) goto failed;
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"args\" missing from FunctionDef");
+            return 1;
+        }
+        if (_PyObject_HasAttrId(obj, &PyId_body)) {
+            int res;
+            Py_ssize_t len;
+            Py_ssize_t i;
+            tmp = _PyObject_GetAttrId(obj, &PyId_body);
+            if (tmp == NULL) goto failed;
+            if (!PyList_Check(tmp)) {
+                PyErr_Format(PyExc_TypeError, "FunctionDef field \"body\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                goto failed;
+            }
+            len = PyList_GET_SIZE(tmp);
+            body = _Py_asdl_seq_new(len, arena);
+            if (body == NULL) goto failed;
+            for (i = 0; i < len; i++) {
+                stmt_ty value;
+                res = obj2ast_stmt(PyList_GET_ITEM(tmp, i), &value, arena);
+                if (res != 0) goto failed;
+                asdl_seq_SET(body, i, value);
+            }
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"body\" missing from FunctionDef");
+            return 1;
+        }
+        if (_PyObject_HasAttrId(obj, &PyId_decorator_list)) {
+            int res;
+            Py_ssize_t len;
+            Py_ssize_t i;
+            tmp = _PyObject_GetAttrId(obj, &PyId_decorator_list);
+            if (tmp == NULL) goto failed;
+            if (!PyList_Check(tmp)) {
+                PyErr_Format(PyExc_TypeError, "FunctionDef field \"decorator_list\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                goto failed;
+            }
+            len = PyList_GET_SIZE(tmp);
+            decorator_list = _Py_asdl_seq_new(len, arena);
+            if (decorator_list == NULL) goto failed;
+            for (i = 0; i < len; i++) {
+                expr_ty value;
+                res = obj2ast_expr(PyList_GET_ITEM(tmp, i), &value, arena);
+                if (res != 0) goto failed;
+                asdl_seq_SET(decorator_list, i, value);
+            }
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"decorator_list\" missing from FunctionDef");
+            return 1;
+        }
+        if (exists_not_none(obj, &PyId_returns)) {
+            int res;
+            tmp = _PyObject_GetAttrId(obj, &PyId_returns);
+            if (tmp == NULL) goto failed;
+            res = obj2ast_expr(tmp, &returns, arena);
+            if (res != 0) goto failed;
+            Py_CLEAR(tmp);
+        } else {
+            returns = NULL;
+        }
+        if (exists_not_none(obj, &PyId_type_comment)) {
+            int res;
+            tmp = _PyObject_GetAttrId(obj, &PyId_type_comment);
+            if (tmp == NULL) goto failed;
+            res = obj2ast_string(tmp, &type_comment, arena);
+            if (res != 0) goto failed;
+            Py_CLEAR(tmp);
+        } else {
+            type_comment = NULL;
+        }
+        *out = FunctionDef(name, args, body, decorator_list, returns,
+                           type_comment, lineno, col_offset, arena);
+        if (*out == NULL) goto failed;
+        return 0;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject*)AsyncFunctionDef_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        identifier name;
+        arguments_ty args;
+        asdl_seq* body;
+        asdl_seq* decorator_list;
+        expr_ty returns;
+        string type_comment;
+
+        if (_PyObject_HasAttrId(obj, &PyId_name)) {
+            int res;
+            tmp = _PyObject_GetAttrId(obj, &PyId_name);
+            if (tmp == NULL) goto failed;
+            res = obj2ast_identifier(tmp, &name, arena);
+            if (res != 0) goto failed;
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"name\" missing from AsyncFunctionDef");
+            return 1;
+        }
+        if (_PyObject_HasAttrId(obj, &PyId_args)) {
+            int res;
+            tmp = _PyObject_GetAttrId(obj, &PyId_args);
+            if (tmp == NULL) goto failed;
+            res = obj2ast_arguments(tmp, &args, arena);
+            if (res != 0) goto failed;
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"args\" missing from AsyncFunctionDef");
+            return 1;
+        }
+        if (_PyObject_HasAttrId(obj, &PyId_body)) {
+            int res;
+            Py_ssize_t len;
+            Py_ssize_t i;
+            tmp = _PyObject_GetAttrId(obj, &PyId_body);
+            if (tmp == NULL) goto failed;
+            if (!PyList_Check(tmp)) {
+                PyErr_Format(PyExc_TypeError, "AsyncFunctionDef field \"body\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                goto failed;
+            }
+            len = PyList_GET_SIZE(tmp);
+            body = _Py_asdl_seq_new(len, arena);
+            if (body == NULL) goto failed;
+            for (i = 0; i < len; i++) {
+                stmt_ty value;
+                res = obj2ast_stmt(PyList_GET_ITEM(tmp, i), &value, arena);
+                if (res != 0) goto failed;
+                asdl_seq_SET(body, i, value);
+            }
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"body\" missing from AsyncFunctionDef");
+            return 1;
+        }
+        if (_PyObject_HasAttrId(obj, &PyId_decorator_list)) {
+            int res;
+            Py_ssize_t len;
+            Py_ssize_t i;
+            tmp = _PyObject_GetAttrId(obj, &PyId_decorator_list);
+            if (tmp == NULL) goto failed;
+            if (!PyList_Check(tmp)) {
+                PyErr_Format(PyExc_TypeError, "AsyncFunctionDef field \"decorator_list\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                goto failed;
+            }
+            len = PyList_GET_SIZE(tmp);
+            decorator_list = _Py_asdl_seq_new(len, arena);
+            if (decorator_list == NULL) goto failed;
+            for (i = 0; i < len; i++) {
+                expr_ty value;
+                res = obj2ast_expr(PyList_GET_ITEM(tmp, i), &value, arena);
+                if (res != 0) goto failed;
+                asdl_seq_SET(decorator_list, i, value);
+            }
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"decorator_list\" missing from AsyncFunctionDef");
+            return 1;
+        }
+        if (exists_not_none(obj, &PyId_returns)) {
+            int res;
+            tmp = _PyObject_GetAttrId(obj, &PyId_returns);
+            if (tmp == NULL) goto failed;
+            res = obj2ast_expr(tmp, &returns, arena);
+            if (res != 0) goto failed;
+            Py_CLEAR(tmp);
+        } else {
+            returns = NULL;
+        }
+        if (exists_not_none(obj, &PyId_type_comment)) {
+            int res;
+            tmp = _PyObject_GetAttrId(obj, &PyId_type_comment);
+            if (tmp == NULL) goto failed;
+            res = obj2ast_string(tmp, &type_comment, arena);
+            if (res != 0) goto failed;
+            Py_CLEAR(tmp);
+        } else {
+            type_comment = NULL;
+        }
+        *out = AsyncFunctionDef(name, args, body, decorator_list, returns,
+                                type_comment, lineno, col_offset, arena);
+        if (*out == NULL) goto failed;
+        return 0;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject*)ClassDef_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        identifier name;
+        asdl_seq* bases;
+        asdl_seq* keywords;
+        asdl_seq* body;
+        asdl_seq* decorator_list;
+
+        if (_PyObject_HasAttrId(obj, &PyId_name)) {
+            int res;
+            tmp = _PyObject_GetAttrId(obj, &PyId_name);
+            if (tmp == NULL) goto failed;
+            res = obj2ast_identifier(tmp, &name, arena);
+            if (res != 0) goto failed;
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"name\" missing from ClassDef");
+            return 1;
+        }
+        if (_PyObject_HasAttrId(obj, &PyId_bases)) {
+            int res;
+            Py_ssize_t len;
+            Py_ssize_t i;
+            tmp = _PyObject_GetAttrId(obj, &PyId_bases);
+            if (tmp == NULL) goto failed;
+            if (!PyList_Check(tmp)) {
+                PyErr_Format(PyExc_TypeError, "ClassDef field \"bases\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                goto failed;
+            }
+            len = PyList_GET_SIZE(tmp);
+            bases = _Py_asdl_seq_new(len, arena);
+            if (bases == NULL) goto failed;
+            for (i = 0; i < len; i++) {
+                expr_ty value;
+                res = obj2ast_expr(PyList_GET_ITEM(tmp, i), &value, arena);
+                if (res != 0) goto failed;
+                asdl_seq_SET(bases, i, value);
+            }
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"bases\" missing from ClassDef");
+            return 1;
+        }
+        if (_PyObject_HasAttrId(obj, &PyId_keywords)) {
+            int res;
+            Py_ssize_t len;
+            Py_ssize_t i;
+            tmp = _PyObject_GetAttrId(obj, &PyId_keywords);
+            if (tmp == NULL) goto failed;
+            if (!PyList_Check(tmp)) {
+                PyErr_Format(PyExc_TypeError, "ClassDef field \"keywords\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                goto failed;
+            }
+            len = PyList_GET_SIZE(tmp);
+            keywords = _Py_asdl_seq_new(len, arena);
+            if (keywords == NULL) goto failed;
+            for (i = 0; i < len; i++) {
+                keyword_ty value;
+                res = obj2ast_keyword(PyList_GET_ITEM(tmp, i), &value, arena);
+                if (res != 0) goto failed;
+                asdl_seq_SET(keywords, i, value);
+            }
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"keywords\" missing from ClassDef");
+            return 1;
+        }
+        if (_PyObject_HasAttrId(obj, &PyId_body)) {
+            int res;
+            Py_ssize_t len;
+            Py_ssize_t i;
+            tmp = _PyObject_GetAttrId(obj, &PyId_body);
+            if (tmp == NULL) goto failed;
+            if (!PyList_Check(tmp)) {
+                PyErr_Format(PyExc_TypeError, "ClassDef field \"body\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                goto failed;
+            }
+            len = PyList_GET_SIZE(tmp);
+            body = _Py_asdl_seq_new(len, arena);
+            if (body == NULL) goto failed;
+            for (i = 0; i < len; i++) {
+                stmt_ty value;
+                res = obj2ast_stmt(PyList_GET_ITEM(tmp, i), &value, arena);
+                if (res != 0) goto failed;
+                asdl_seq_SET(body, i, value);
+            }
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"body\" missing from ClassDef");
+            return 1;
+        }
+        if (_PyObject_HasAttrId(obj, &PyId_decorator_list)) {
+            int res;
+            Py_ssize_t len;
+            Py_ssize_t i;
+            tmp = _PyObject_GetAttrId(obj, &PyId_decorator_list);
+            if (tmp == NULL) goto failed;
+            if (!PyList_Check(tmp)) {
+                PyErr_Format(PyExc_TypeError, "ClassDef field \"decorator_list\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                goto failed;
+            }
+            len = PyList_GET_SIZE(tmp);
+            decorator_list = _Py_asdl_seq_new(len, arena);
+            if (decorator_list == NULL) goto failed;
+            for (i = 0; i < len; i++) {
+                expr_ty value;
+                res = obj2ast_expr(PyList_GET_ITEM(tmp, i), &value, arena);
+                if (res != 0) goto failed;
+                asdl_seq_SET(decorator_list, i, value);
+            }
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"decorator_list\" missing from ClassDef");
+            return 1;
+        }
+        *out = ClassDef(name, bases, keywords, body, decorator_list, lineno,
+                        col_offset, arena);
+        if (*out == NULL) goto failed;
+        return 0;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject*)Return_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        expr_ty value;
+
+        if (exists_not_none(obj, &PyId_value)) {
+            int res;
+            tmp = _PyObject_GetAttrId(obj, &PyId_value);
+            if (tmp == NULL) goto failed;
+            res = obj2ast_expr(tmp, &value, arena);
+            if (res != 0) goto failed;
+            Py_CLEAR(tmp);
+        } else {
+            value = NULL;
+        }
+        *out = Return(value, lineno, col_offset, arena);
+        if (*out == NULL) goto failed;
+        return 0;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject*)Delete_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        asdl_seq* targets;
+
+        if (_PyObject_HasAttrId(obj, &PyId_targets)) {
+            int res;
+            Py_ssize_t len;
+            Py_ssize_t i;
+            tmp = _PyObject_GetAttrId(obj, &PyId_targets);
+            if (tmp == NULL) goto failed;
+            if (!PyList_Check(tmp)) {
+                PyErr_Format(PyExc_TypeError, "Delete field \"targets\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                goto failed;
+            }
+            len = PyList_GET_SIZE(tmp);
+            targets = _Py_asdl_seq_new(len, arena);
+            if (targets == NULL) goto failed;
+            for (i = 0; i < len; i++) {
+                expr_ty value;
+                res = obj2ast_expr(PyList_GET_ITEM(tmp, i), &value, arena);
+                if (res != 0) goto failed;
+                asdl_seq_SET(targets, i, value);
+            }
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"targets\" missing from Delete");
+            return 1;
+        }
+        *out = Delete(targets, lineno, col_offset, arena);
+        if (*out == NULL) goto failed;
+        return 0;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject*)Assign_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        asdl_seq* targets;
+        expr_ty value;
+        string type_comment;
+
+        if (_PyObject_HasAttrId(obj, &PyId_targets)) {
+            int res;
+            Py_ssize_t len;
+            Py_ssize_t i;
+            tmp = _PyObject_GetAttrId(obj, &PyId_targets);
+            if (tmp == NULL) goto failed;
+            if (!PyList_Check(tmp)) {
+                PyErr_Format(PyExc_TypeError, "Assign field \"targets\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                goto failed;
+            }
+            len = PyList_GET_SIZE(tmp);
+            targets = _Py_asdl_seq_new(len, arena);
+            if (targets == NULL) goto failed;
+            for (i = 0; i < len; i++) {
+                expr_ty value;
+                res = obj2ast_expr(PyList_GET_ITEM(tmp, i), &value, arena);
+                if (res != 0) goto failed;
+                asdl_seq_SET(targets, i, value);
+            }
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"targets\" missing from Assign");
+            return 1;
+        }
+        if (_PyObject_HasAttrId(obj, &PyId_value)) {
+            int res;
+            tmp = _PyObject_GetAttrId(obj, &PyId_value);
+            if (tmp == NULL) goto failed;
+            res = obj2ast_expr(tmp, &value, arena);
+            if (res != 0) goto failed;
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"value\" missing from Assign");
+            return 1;
+        }
+        if (exists_not_none(obj, &PyId_type_comment)) {
+            int res;
+            tmp = _PyObject_GetAttrId(obj, &PyId_type_comment);
+            if (tmp == NULL) goto failed;
+            res = obj2ast_string(tmp, &type_comment, arena);
+            if (res != 0) goto failed;
+            Py_CLEAR(tmp);
+        } else {
+            type_comment = NULL;
+        }
+        *out = Assign(targets, value, type_comment, lineno, col_offset, arena);
+        if (*out == NULL) goto failed;
+        return 0;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject*)AugAssign_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        expr_ty target;
+        operator_ty op;
+        expr_ty value;
+
+        if (_PyObject_HasAttrId(obj, &PyId_target)) {
+            int res;
+            tmp = _PyObject_GetAttrId(obj, &PyId_target);
+            if (tmp == NULL) goto failed;
+            res = obj2ast_expr(tmp, &target, arena);
+            if (res != 0) goto failed;
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"target\" missing from AugAssign");
+            return 1;
+        }
+        if (_PyObject_HasAttrId(obj, &PyId_op)) {
+            int res;
+            tmp = _PyObject_GetAttrId(obj, &PyId_op);
+            if (tmp == NULL) goto failed;
+            res = obj2ast_operator(tmp, &op, arena);
+            if (res != 0) goto failed;
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"op\" missing from AugAssign");
+            return 1;
+        }
+        if (_PyObject_HasAttrId(obj, &PyId_value)) {
+            int res;
+            tmp = _PyObject_GetAttrId(obj, &PyId_value);
+            if (tmp == NULL) goto failed;
+            res = obj2ast_expr(tmp, &value, arena);
+            if (res != 0) goto failed;
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"value\" missing from AugAssign");
+            return 1;
+        }
+        *out = AugAssign(target, op, value, lineno, col_offset, arena);
+        if (*out == NULL) goto failed;
+        return 0;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject*)For_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        expr_ty target;
+        expr_ty iter;
+        asdl_seq* body;
+        asdl_seq* orelse;
+        string type_comment;
+
+        if (_PyObject_HasAttrId(obj, &PyId_target)) {
+            int res;
+            tmp = _PyObject_GetAttrId(obj, &PyId_target);
+            if (tmp == NULL) goto failed;
+            res = obj2ast_expr(tmp, &target, arena);
+            if (res != 0) goto failed;
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"target\" missing from For");
+            return 1;
+        }
+        if (_PyObject_HasAttrId(obj, &PyId_iter)) {
+            int res;
+            tmp = _PyObject_GetAttrId(obj, &PyId_iter);
+            if (tmp == NULL) goto failed;
+            res = obj2ast_expr(tmp, &iter, arena);
+            if (res != 0) goto failed;
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"iter\" missing from For");
+            return 1;
+        }
+        if (_PyObject_HasAttrId(obj, &PyId_body)) {
+            int res;
+            Py_ssize_t len;
+            Py_ssize_t i;
+            tmp = _PyObject_GetAttrId(obj, &PyId_body);
+            if (tmp == NULL) goto failed;
+            if (!PyList_Check(tmp)) {
+                PyErr_Format(PyExc_TypeError, "For field \"body\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                goto failed;
+            }
+            len = PyList_GET_SIZE(tmp);
+            body = _Py_asdl_seq_new(len, arena);
+            if (body == NULL) goto failed;
+            for (i = 0; i < len; i++) {
+                stmt_ty value;
+                res = obj2ast_stmt(PyList_GET_ITEM(tmp, i), &value, arena);
+                if (res != 0) goto failed;
+                asdl_seq_SET(body, i, value);
+            }
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"body\" missing from For");
+            return 1;
+        }
+        if (_PyObject_HasAttrId(obj, &PyId_orelse)) {
+            int res;
+            Py_ssize_t len;
+            Py_ssize_t i;
+            tmp = _PyObject_GetAttrId(obj, &PyId_orelse);
+            if (tmp == NULL) goto failed;
+            if (!PyList_Check(tmp)) {
+                PyErr_Format(PyExc_TypeError, "For field \"orelse\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                goto failed;
+            }
+            len = PyList_GET_SIZE(tmp);
+            orelse = _Py_asdl_seq_new(len, arena);
+            if (orelse == NULL) goto failed;
+            for (i = 0; i < len; i++) {
+                stmt_ty value;
+                res = obj2ast_stmt(PyList_GET_ITEM(tmp, i), &value, arena);
+                if (res != 0) goto failed;
+                asdl_seq_SET(orelse, i, value);
+            }
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"orelse\" missing from For");
+            return 1;
+        }
+        if (exists_not_none(obj, &PyId_type_comment)) {
+            int res;
+            tmp = _PyObject_GetAttrId(obj, &PyId_type_comment);
+            if (tmp == NULL) goto failed;
+            res = obj2ast_string(tmp, &type_comment, arena);
+            if (res != 0) goto failed;
+            Py_CLEAR(tmp);
+        } else {
+            type_comment = NULL;
+        }
+        *out = For(target, iter, body, orelse, type_comment, lineno,
+                   col_offset, arena);
+        if (*out == NULL) goto failed;
+        return 0;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject*)AsyncFor_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        expr_ty target;
+        expr_ty iter;
+        asdl_seq* body;
+        asdl_seq* orelse;
+
+        if (_PyObject_HasAttrId(obj, &PyId_target)) {
+            int res;
+            tmp = _PyObject_GetAttrId(obj, &PyId_target);
+            if (tmp == NULL) goto failed;
+            res = obj2ast_expr(tmp, &target, arena);
+            if (res != 0) goto failed;
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"target\" missing from AsyncFor");
+            return 1;
+        }
+        if (_PyObject_HasAttrId(obj, &PyId_iter)) {
+            int res;
+            tmp = _PyObject_GetAttrId(obj, &PyId_iter);
+            if (tmp == NULL) goto failed;
+            res = obj2ast_expr(tmp, &iter, arena);
+            if (res != 0) goto failed;
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"iter\" missing from AsyncFor");
+            return 1;
+        }
+        if (_PyObject_HasAttrId(obj, &PyId_body)) {
+            int res;
+            Py_ssize_t len;
+            Py_ssize_t i;
+            tmp = _PyObject_GetAttrId(obj, &PyId_body);
+            if (tmp == NULL) goto failed;
+            if (!PyList_Check(tmp)) {
+                PyErr_Format(PyExc_TypeError, "AsyncFor field \"body\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                goto failed;
+            }
+            len = PyList_GET_SIZE(tmp);
+            body = _Py_asdl_seq_new(len, arena);
+            if (body == NULL) goto failed;
+            for (i = 0; i < len; i++) {
+                stmt_ty value;
+                res = obj2ast_stmt(PyList_GET_ITEM(tmp, i), &value, arena);
+                if (res != 0) goto failed;
+                asdl_seq_SET(body, i, value);
+            }
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"body\" missing from AsyncFor");
+            return 1;
+        }
+        if (_PyObject_HasAttrId(obj, &PyId_orelse)) {
+            int res;
+            Py_ssize_t len;
+            Py_ssize_t i;
+            tmp = _PyObject_GetAttrId(obj, &PyId_orelse);
+            if (tmp == NULL) goto failed;
+            if (!PyList_Check(tmp)) {
+                PyErr_Format(PyExc_TypeError, "AsyncFor field \"orelse\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                goto failed;
+            }
+            len = PyList_GET_SIZE(tmp);
+            orelse = _Py_asdl_seq_new(len, arena);
+            if (orelse == NULL) goto failed;
+            for (i = 0; i < len; i++) {
+                stmt_ty value;
+                res = obj2ast_stmt(PyList_GET_ITEM(tmp, i), &value, arena);
+                if (res != 0) goto failed;
+                asdl_seq_SET(orelse, i, value);
+            }
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"orelse\" missing from AsyncFor");
+            return 1;
+        }
+        *out = AsyncFor(target, iter, body, orelse, lineno, col_offset, arena);
+        if (*out == NULL) goto failed;
+        return 0;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject*)While_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        expr_ty test;
+        asdl_seq* body;
+        asdl_seq* orelse;
+
+        if (_PyObject_HasAttrId(obj, &PyId_test)) {
+            int res;
+            tmp = _PyObject_GetAttrId(obj, &PyId_test);
+            if (tmp == NULL) goto failed;
+            res = obj2ast_expr(tmp, &test, arena);
+            if (res != 0) goto failed;
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"test\" missing from While");
+            return 1;
+        }
+        if (_PyObject_HasAttrId(obj, &PyId_body)) {
+            int res;
+            Py_ssize_t len;
+            Py_ssize_t i;
+            tmp = _PyObject_GetAttrId(obj, &PyId_body);
+            if (tmp == NULL) goto failed;
+            if (!PyList_Check(tmp)) {
+                PyErr_Format(PyExc_TypeError, "While field \"body\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                goto failed;
+            }
+            len = PyList_GET_SIZE(tmp);
+            body = _Py_asdl_seq_new(len, arena);
+            if (body == NULL) goto failed;
+            for (i = 0; i < len; i++) {
+                stmt_ty value;
+                res = obj2ast_stmt(PyList_GET_ITEM(tmp, i), &value, arena);
+                if (res != 0) goto failed;
+                asdl_seq_SET(body, i, value);
+            }
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"body\" missing from While");
+            return 1;
+        }
+        if (_PyObject_HasAttrId(obj, &PyId_orelse)) {
+            int res;
+            Py_ssize_t len;
+            Py_ssize_t i;
+            tmp = _PyObject_GetAttrId(obj, &PyId_orelse);
+            if (tmp == NULL) goto failed;
+            if (!PyList_Check(tmp)) {
+                PyErr_Format(PyExc_TypeError, "While field \"orelse\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                goto failed;
+            }
+            len = PyList_GET_SIZE(tmp);
+            orelse = _Py_asdl_seq_new(len, arena);
+            if (orelse == NULL) goto failed;
+            for (i = 0; i < len; i++) {
+                stmt_ty value;
+                res = obj2ast_stmt(PyList_GET_ITEM(tmp, i), &value, arena);
+                if (res != 0) goto failed;
+                asdl_seq_SET(orelse, i, value);
+            }
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"orelse\" missing from While");
+            return 1;
+        }
+        *out = While(test, body, orelse, lineno, col_offset, arena);
+        if (*out == NULL) goto failed;
+        return 0;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject*)If_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        expr_ty test;
+        asdl_seq* body;
+        asdl_seq* orelse;
+
+        if (_PyObject_HasAttrId(obj, &PyId_test)) {
+            int res;
+            tmp = _PyObject_GetAttrId(obj, &PyId_test);
+            if (tmp == NULL) goto failed;
+            res = obj2ast_expr(tmp, &test, arena);
+            if (res != 0) goto failed;
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"test\" missing from If");
+            return 1;
+        }
+        if (_PyObject_HasAttrId(obj, &PyId_body)) {
+            int res;
+            Py_ssize_t len;
+            Py_ssize_t i;
+            tmp = _PyObject_GetAttrId(obj, &PyId_body);
+            if (tmp == NULL) goto failed;
+            if (!PyList_Check(tmp)) {
+                PyErr_Format(PyExc_TypeError, "If field \"body\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                goto failed;
+            }
+            len = PyList_GET_SIZE(tmp);
+            body = _Py_asdl_seq_new(len, arena);
+            if (body == NULL) goto failed;
+            for (i = 0; i < len; i++) {
+                stmt_ty value;
+                res = obj2ast_stmt(PyList_GET_ITEM(tmp, i), &value, arena);
+                if (res != 0) goto failed;
+                asdl_seq_SET(body, i, value);
+            }
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"body\" missing from If");
+            return 1;
+        }
+        if (_PyObject_HasAttrId(obj, &PyId_orelse)) {
+            int res;
+            Py_ssize_t len;
+            Py_ssize_t i;
+            tmp = _PyObject_GetAttrId(obj, &PyId_orelse);
+            if (tmp == NULL) goto failed;
+            if (!PyList_Check(tmp)) {
+                PyErr_Format(PyExc_TypeError, "If field \"orelse\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                goto failed;
+            }
+            len = PyList_GET_SIZE(tmp);
+            orelse = _Py_asdl_seq_new(len, arena);
+            if (orelse == NULL) goto failed;
+            for (i = 0; i < len; i++) {
+                stmt_ty value;
+                res = obj2ast_stmt(PyList_GET_ITEM(tmp, i), &value, arena);
+                if (res != 0) goto failed;
+                asdl_seq_SET(orelse, i, value);
+            }
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"orelse\" missing from If");
+            return 1;
+        }
+        *out = If(test, body, orelse, lineno, col_offset, arena);
+        if (*out == NULL) goto failed;
+        return 0;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject*)With_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        asdl_seq* items;
+        asdl_seq* body;
+        string type_comment;
+
+        if (_PyObject_HasAttrId(obj, &PyId_items)) {
+            int res;
+            Py_ssize_t len;
+            Py_ssize_t i;
+            tmp = _PyObject_GetAttrId(obj, &PyId_items);
+            if (tmp == NULL) goto failed;
+            if (!PyList_Check(tmp)) {
+                PyErr_Format(PyExc_TypeError, "With field \"items\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                goto failed;
+            }
+            len = PyList_GET_SIZE(tmp);
+            items = _Py_asdl_seq_new(len, arena);
+            if (items == NULL) goto failed;
+            for (i = 0; i < len; i++) {
+                withitem_ty value;
+                res = obj2ast_withitem(PyList_GET_ITEM(tmp, i), &value, arena);
+                if (res != 0) goto failed;
+                asdl_seq_SET(items, i, value);
+            }
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"items\" missing from With");
+            return 1;
+        }
+        if (_PyObject_HasAttrId(obj, &PyId_body)) {
+            int res;
+            Py_ssize_t len;
+            Py_ssize_t i;
+            tmp = _PyObject_GetAttrId(obj, &PyId_body);
+            if (tmp == NULL) goto failed;
+            if (!PyList_Check(tmp)) {
+                PyErr_Format(PyExc_TypeError, "With field \"body\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                goto failed;
+            }
+            len = PyList_GET_SIZE(tmp);
+            body = _Py_asdl_seq_new(len, arena);
+            if (body == NULL) goto failed;
+            for (i = 0; i < len; i++) {
+                stmt_ty value;
+                res = obj2ast_stmt(PyList_GET_ITEM(tmp, i), &value, arena);
+                if (res != 0) goto failed;
+                asdl_seq_SET(body, i, value);
+            }
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"body\" missing from With");
+            return 1;
+        }
+        if (exists_not_none(obj, &PyId_type_comment)) {
+            int res;
+            tmp = _PyObject_GetAttrId(obj, &PyId_type_comment);
+            if (tmp == NULL) goto failed;
+            res = obj2ast_string(tmp, &type_comment, arena);
+            if (res != 0) goto failed;
+            Py_CLEAR(tmp);
+        } else {
+            type_comment = NULL;
+        }
+        *out = With(items, body, type_comment, lineno, col_offset, arena);
+        if (*out == NULL) goto failed;
+        return 0;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject*)AsyncWith_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        asdl_seq* items;
+        asdl_seq* body;
+
+        if (_PyObject_HasAttrId(obj, &PyId_items)) {
+            int res;
+            Py_ssize_t len;
+            Py_ssize_t i;
+            tmp = _PyObject_GetAttrId(obj, &PyId_items);
+            if (tmp == NULL) goto failed;
+            if (!PyList_Check(tmp)) {
+                PyErr_Format(PyExc_TypeError, "AsyncWith field \"items\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                goto failed;
+            }
+            len = PyList_GET_SIZE(tmp);
+            items = _Py_asdl_seq_new(len, arena);
+            if (items == NULL) goto failed;
+            for (i = 0; i < len; i++) {
+                withitem_ty value;
+                res = obj2ast_withitem(PyList_GET_ITEM(tmp, i), &value, arena);
+                if (res != 0) goto failed;
+                asdl_seq_SET(items, i, value);
+            }
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"items\" missing from AsyncWith");
+            return 1;
+        }
+        if (_PyObject_HasAttrId(obj, &PyId_body)) {
+            int res;
+            Py_ssize_t len;
+            Py_ssize_t i;
+            tmp = _PyObject_GetAttrId(obj, &PyId_body);
+            if (tmp == NULL) goto failed;
+            if (!PyList_Check(tmp)) {
+                PyErr_Format(PyExc_TypeError, "AsyncWith field \"body\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                goto failed;
+            }
+            len = PyList_GET_SIZE(tmp);
+            body = _Py_asdl_seq_new(len, arena);
+            if (body == NULL) goto failed;
+            for (i = 0; i < len; i++) {
+                stmt_ty value;
+                res = obj2ast_stmt(PyList_GET_ITEM(tmp, i), &value, arena);
+                if (res != 0) goto failed;
+                asdl_seq_SET(body, i, value);
+            }
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"body\" missing from AsyncWith");
+            return 1;
+        }
+        *out = AsyncWith(items, body, lineno, col_offset, arena);
+        if (*out == NULL) goto failed;
+        return 0;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject*)Raise_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        expr_ty exc;
+        expr_ty cause;
+
+        if (exists_not_none(obj, &PyId_exc)) {
+            int res;
+            tmp = _PyObject_GetAttrId(obj, &PyId_exc);
+            if (tmp == NULL) goto failed;
+            res = obj2ast_expr(tmp, &exc, arena);
+            if (res != 0) goto failed;
+            Py_CLEAR(tmp);
+        } else {
+            exc = NULL;
+        }
+        if (exists_not_none(obj, &PyId_cause)) {
+            int res;
+            tmp = _PyObject_GetAttrId(obj, &PyId_cause);
+            if (tmp == NULL) goto failed;
+            res = obj2ast_expr(tmp, &cause, arena);
+            if (res != 0) goto failed;
+            Py_CLEAR(tmp);
+        } else {
+            cause = NULL;
+        }
+        *out = Raise(exc, cause, lineno, col_offset, arena);
+        if (*out == NULL) goto failed;
+        return 0;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject*)Try_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        asdl_seq* body;
+        asdl_seq* handlers;
+        asdl_seq* orelse;
+        asdl_seq* finalbody;
+
+        if (_PyObject_HasAttrId(obj, &PyId_body)) {
+            int res;
+            Py_ssize_t len;
+            Py_ssize_t i;
+            tmp = _PyObject_GetAttrId(obj, &PyId_body);
+            if (tmp == NULL) goto failed;
+            if (!PyList_Check(tmp)) {
+                PyErr_Format(PyExc_TypeError, "Try field \"body\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                goto failed;
+            }
+            len = PyList_GET_SIZE(tmp);
+            body = _Py_asdl_seq_new(len, arena);
+            if (body == NULL) goto failed;
+            for (i = 0; i < len; i++) {
+                stmt_ty value;
+                res = obj2ast_stmt(PyList_GET_ITEM(tmp, i), &value, arena);
+                if (res != 0) goto failed;
+                asdl_seq_SET(body, i, value);
+            }
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"body\" missing from Try");
+            return 1;
+        }
+        if (_PyObject_HasAttrId(obj, &PyId_handlers)) {
+            int res;
+            Py_ssize_t len;
+            Py_ssize_t i;
+            tmp = _PyObject_GetAttrId(obj, &PyId_handlers);
+            if (tmp == NULL) goto failed;
+            if (!PyList_Check(tmp)) {
+                PyErr_Format(PyExc_TypeError, "Try field \"handlers\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                goto failed;
+            }
+            len = PyList_GET_SIZE(tmp);
+            handlers = _Py_asdl_seq_new(len, arena);
+            if (handlers == NULL) goto failed;
+            for (i = 0; i < len; i++) {
+                excepthandler_ty value;
+                res = obj2ast_excepthandler(PyList_GET_ITEM(tmp, i), &value, arena);
+                if (res != 0) goto failed;
+                asdl_seq_SET(handlers, i, value);
+            }
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"handlers\" missing from Try");
+            return 1;
+        }
+        if (_PyObject_HasAttrId(obj, &PyId_orelse)) {
+            int res;
+            Py_ssize_t len;
+            Py_ssize_t i;
+            tmp = _PyObject_GetAttrId(obj, &PyId_orelse);
+            if (tmp == NULL) goto failed;
+            if (!PyList_Check(tmp)) {
+                PyErr_Format(PyExc_TypeError, "Try field \"orelse\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                goto failed;
+            }
+            len = PyList_GET_SIZE(tmp);
+            orelse = _Py_asdl_seq_new(len, arena);
+            if (orelse == NULL) goto failed;
+            for (i = 0; i < len; i++) {
+                stmt_ty value;
+                res = obj2ast_stmt(PyList_GET_ITEM(tmp, i), &value, arena);
+                if (res != 0) goto failed;
+                asdl_seq_SET(orelse, i, value);
+            }
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"orelse\" missing from Try");
+            return 1;
+        }
+        if (_PyObject_HasAttrId(obj, &PyId_finalbody)) {
+            int res;
+            Py_ssize_t len;
+            Py_ssize_t i;
+            tmp = _PyObject_GetAttrId(obj, &PyId_finalbody);
+            if (tmp == NULL) goto failed;
+            if (!PyList_Check(tmp)) {
+                PyErr_Format(PyExc_TypeError, "Try field \"finalbody\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                goto failed;
+            }
+            len = PyList_GET_SIZE(tmp);
+            finalbody = _Py_asdl_seq_new(len, arena);
+            if (finalbody == NULL) goto failed;
+            for (i = 0; i < len; i++) {
+                stmt_ty value;
+                res = obj2ast_stmt(PyList_GET_ITEM(tmp, i), &value, arena);
+                if (res != 0) goto failed;
+                asdl_seq_SET(finalbody, i, value);
+            }
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"finalbody\" missing from Try");
+            return 1;
+        }
+        *out = Try(body, handlers, orelse, finalbody, lineno, col_offset,
+                   arena);
+        if (*out == NULL) goto failed;
+        return 0;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject*)Assert_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        expr_ty test;
+        expr_ty msg;
+
+        if (_PyObject_HasAttrId(obj, &PyId_test)) {
+            int res;
+            tmp = _PyObject_GetAttrId(obj, &PyId_test);
+            if (tmp == NULL) goto failed;
+            res = obj2ast_expr(tmp, &test, arena);
+            if (res != 0) goto failed;
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"test\" missing from Assert");
+            return 1;
+        }
+        if (exists_not_none(obj, &PyId_msg)) {
+            int res;
+            tmp = _PyObject_GetAttrId(obj, &PyId_msg);
+            if (tmp == NULL) goto failed;
+            res = obj2ast_expr(tmp, &msg, arena);
+            if (res != 0) goto failed;
+            Py_CLEAR(tmp);
+        } else {
+            msg = NULL;
+        }
+        *out = Assert(test, msg, lineno, col_offset, arena);
+        if (*out == NULL) goto failed;
+        return 0;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject*)Import_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        asdl_seq* names;
+
+        if (_PyObject_HasAttrId(obj, &PyId_names)) {
+            int res;
+            Py_ssize_t len;
+            Py_ssize_t i;
+            tmp = _PyObject_GetAttrId(obj, &PyId_names);
+            if (tmp == NULL) goto failed;
+            if (!PyList_Check(tmp)) {
+                PyErr_Format(PyExc_TypeError, "Import field \"names\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                goto failed;
+            }
+            len = PyList_GET_SIZE(tmp);
+            names = _Py_asdl_seq_new(len, arena);
+            if (names == NULL) goto failed;
+            for (i = 0; i < len; i++) {
+                alias_ty value;
+                res = obj2ast_alias(PyList_GET_ITEM(tmp, i), &value, arena);
+                if (res != 0) goto failed;
+                asdl_seq_SET(names, i, value);
+            }
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"names\" missing from Import");
+            return 1;
+        }
+        *out = Import(names, lineno, col_offset, arena);
+        if (*out == NULL) goto failed;
+        return 0;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject*)ImportFrom_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        identifier module;
+        asdl_seq* names;
+        int level;
+
+        if (exists_not_none(obj, &PyId_module)) {
+            int res;
+            tmp = _PyObject_GetAttrId(obj, &PyId_module);
+            if (tmp == NULL) goto failed;
+            res = obj2ast_identifier(tmp, &module, arena);
+            if (res != 0) goto failed;
+            Py_CLEAR(tmp);
+        } else {
+            module = NULL;
+        }
+        if (_PyObject_HasAttrId(obj, &PyId_names)) {
+            int res;
+            Py_ssize_t len;
+            Py_ssize_t i;
+            tmp = _PyObject_GetAttrId(obj, &PyId_names);
+            if (tmp == NULL) goto failed;
+            if (!PyList_Check(tmp)) {
+                PyErr_Format(PyExc_TypeError, "ImportFrom field \"names\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                goto failed;
+            }
+            len = PyList_GET_SIZE(tmp);
+            names = _Py_asdl_seq_new(len, arena);
+            if (names == NULL) goto failed;
+            for (i = 0; i < len; i++) {
+                alias_ty value;
+                res = obj2ast_alias(PyList_GET_ITEM(tmp, i), &value, arena);
+                if (res != 0) goto failed;
+                asdl_seq_SET(names, i, value);
+            }
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"names\" missing from ImportFrom");
+            return 1;
+        }
+        if (exists_not_none(obj, &PyId_level)) {
+            int res;
+            tmp = _PyObject_GetAttrId(obj, &PyId_level);
+            if (tmp == NULL) goto failed;
+            res = obj2ast_int(tmp, &level, arena);
+            if (res != 0) goto failed;
+            Py_CLEAR(tmp);
+        } else {
+            level = 0;
+        }
+        *out = ImportFrom(module, names, level, lineno, col_offset, arena);
+        if (*out == NULL) goto failed;
+        return 0;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject*)Global_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        asdl_seq* names;
+
+        if (_PyObject_HasAttrId(obj, &PyId_names)) {
+            int res;
+            Py_ssize_t len;
+            Py_ssize_t i;
+            tmp = _PyObject_GetAttrId(obj, &PyId_names);
+            if (tmp == NULL) goto failed;
+            if (!PyList_Check(tmp)) {
+                PyErr_Format(PyExc_TypeError, "Global field \"names\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                goto failed;
+            }
+            len = PyList_GET_SIZE(tmp);
+            names = _Py_asdl_seq_new(len, arena);
+            if (names == NULL) goto failed;
+            for (i = 0; i < len; i++) {
+                identifier value;
+                res = obj2ast_identifier(PyList_GET_ITEM(tmp, i), &value, arena);
+                if (res != 0) goto failed;
+                asdl_seq_SET(names, i, value);
+            }
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"names\" missing from Global");
+            return 1;
+        }
+        *out = Global(names, lineno, col_offset, arena);
+        if (*out == NULL) goto failed;
+        return 0;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject*)Nonlocal_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        asdl_seq* names;
+
+        if (_PyObject_HasAttrId(obj, &PyId_names)) {
+            int res;
+            Py_ssize_t len;
+            Py_ssize_t i;
+            tmp = _PyObject_GetAttrId(obj, &PyId_names);
+            if (tmp == NULL) goto failed;
+            if (!PyList_Check(tmp)) {
+                PyErr_Format(PyExc_TypeError, "Nonlocal field \"names\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                goto failed;
+            }
+            len = PyList_GET_SIZE(tmp);
+            names = _Py_asdl_seq_new(len, arena);
+            if (names == NULL) goto failed;
+            for (i = 0; i < len; i++) {
+                identifier value;
+                res = obj2ast_identifier(PyList_GET_ITEM(tmp, i), &value, arena);
+                if (res != 0) goto failed;
+                asdl_seq_SET(names, i, value);
+            }
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"names\" missing from Nonlocal");
+            return 1;
+        }
+        *out = Nonlocal(names, lineno, col_offset, arena);
+        if (*out == NULL) goto failed;
+        return 0;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject*)Expr_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        expr_ty value;
+
+        if (_PyObject_HasAttrId(obj, &PyId_value)) {
+            int res;
+            tmp = _PyObject_GetAttrId(obj, &PyId_value);
+            if (tmp == NULL) goto failed;
+            res = obj2ast_expr(tmp, &value, arena);
+            if (res != 0) goto failed;
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"value\" missing from Expr");
+            return 1;
+        }
+        *out = Expr(value, lineno, col_offset, arena);
+        if (*out == NULL) goto failed;
+        return 0;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject*)Pass_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+
+        *out = Pass(lineno, col_offset, arena);
+        if (*out == NULL) goto failed;
+        return 0;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject*)Break_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+
+        *out = Break(lineno, col_offset, arena);
+        if (*out == NULL) goto failed;
+        return 0;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject*)Continue_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+
+        *out = Continue(lineno, col_offset, arena);
+        if (*out == NULL) goto failed;
+        return 0;
+    }
+
+    PyErr_Format(PyExc_TypeError, "expected some sort of stmt, but got %R", obj);
+    failed:
+    Py_XDECREF(tmp);
+    return 1;
+}
+
+int
+obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena)
+{
+    int isinstance;
+
+    PyObject *tmp = NULL;
+    int lineno;
+    int col_offset;
+
+    if (obj == Py_None) {
+        *out = NULL;
+        return 0;
+    }
+    if (_PyObject_HasAttrId(obj, &PyId_lineno)) {
+        int res;
+        tmp = _PyObject_GetAttrId(obj, &PyId_lineno);
+        if (tmp == NULL) goto failed;
+        res = obj2ast_int(tmp, &lineno, arena);
+        if (res != 0) goto failed;
+        Py_CLEAR(tmp);
+    } else {
+        PyErr_SetString(PyExc_TypeError, "required field \"lineno\" missing from expr");
+        return 1;
+    }
+    if (_PyObject_HasAttrId(obj, &PyId_col_offset)) {
+        int res;
+        tmp = _PyObject_GetAttrId(obj, &PyId_col_offset);
+        if (tmp == NULL) goto failed;
+        res = obj2ast_int(tmp, &col_offset, arena);
+        if (res != 0) goto failed;
+        Py_CLEAR(tmp);
+    } else {
+        PyErr_SetString(PyExc_TypeError, "required field \"col_offset\" missing from expr");
+        return 1;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject*)BoolOp_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        boolop_ty op;
+        asdl_seq* values;
+
+        if (_PyObject_HasAttrId(obj, &PyId_op)) {
+            int res;
+            tmp = _PyObject_GetAttrId(obj, &PyId_op);
+            if (tmp == NULL) goto failed;
+            res = obj2ast_boolop(tmp, &op, arena);
+            if (res != 0) goto failed;
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"op\" missing from BoolOp");
+            return 1;
+        }
+        if (_PyObject_HasAttrId(obj, &PyId_values)) {
+            int res;
+            Py_ssize_t len;
+            Py_ssize_t i;
+            tmp = _PyObject_GetAttrId(obj, &PyId_values);
+            if (tmp == NULL) goto failed;
+            if (!PyList_Check(tmp)) {
+                PyErr_Format(PyExc_TypeError, "BoolOp field \"values\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                goto failed;
+            }
+            len = PyList_GET_SIZE(tmp);
+            values = _Py_asdl_seq_new(len, arena);
+            if (values == NULL) goto failed;
+            for (i = 0; i < len; i++) {
+                expr_ty value;
+                res = obj2ast_expr(PyList_GET_ITEM(tmp, i), &value, arena);
+                if (res != 0) goto failed;
+                asdl_seq_SET(values, i, value);
+            }
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"values\" missing from BoolOp");
+            return 1;
+        }
+        *out = BoolOp(op, values, lineno, col_offset, arena);
+        if (*out == NULL) goto failed;
+        return 0;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject*)BinOp_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        expr_ty left;
+        operator_ty op;
+        expr_ty right;
+
+        if (_PyObject_HasAttrId(obj, &PyId_left)) {
+            int res;
+            tmp = _PyObject_GetAttrId(obj, &PyId_left);
+            if (tmp == NULL) goto failed;
+            res = obj2ast_expr(tmp, &left, arena);
+            if (res != 0) goto failed;
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"left\" missing from BinOp");
+            return 1;
+        }
+        if (_PyObject_HasAttrId(obj, &PyId_op)) {
+            int res;
+            tmp = _PyObject_GetAttrId(obj, &PyId_op);
+            if (tmp == NULL) goto failed;
+            res = obj2ast_operator(tmp, &op, arena);
+            if (res != 0) goto failed;
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"op\" missing from BinOp");
+            return 1;
+        }
+        if (_PyObject_HasAttrId(obj, &PyId_right)) {
+            int res;
+            tmp = _PyObject_GetAttrId(obj, &PyId_right);
+            if (tmp == NULL) goto failed;
+            res = obj2ast_expr(tmp, &right, arena);
+            if (res != 0) goto failed;
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"right\" missing from BinOp");
+            return 1;
+        }
+        *out = BinOp(left, op, right, lineno, col_offset, arena);
+        if (*out == NULL) goto failed;
+        return 0;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject*)UnaryOp_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        unaryop_ty op;
+        expr_ty operand;
+
+        if (_PyObject_HasAttrId(obj, &PyId_op)) {
+            int res;
+            tmp = _PyObject_GetAttrId(obj, &PyId_op);
+            if (tmp == NULL) goto failed;
+            res = obj2ast_unaryop(tmp, &op, arena);
+            if (res != 0) goto failed;
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"op\" missing from UnaryOp");
+            return 1;
+        }
+        if (_PyObject_HasAttrId(obj, &PyId_operand)) {
+            int res;
+            tmp = _PyObject_GetAttrId(obj, &PyId_operand);
+            if (tmp == NULL) goto failed;
+            res = obj2ast_expr(tmp, &operand, arena);
+            if (res != 0) goto failed;
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"operand\" missing from UnaryOp");
+            return 1;
+        }
+        *out = UnaryOp(op, operand, lineno, col_offset, arena);
+        if (*out == NULL) goto failed;
+        return 0;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject*)Lambda_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        arguments_ty args;
+        expr_ty body;
+
+        if (_PyObject_HasAttrId(obj, &PyId_args)) {
+            int res;
+            tmp = _PyObject_GetAttrId(obj, &PyId_args);
+            if (tmp == NULL) goto failed;
+            res = obj2ast_arguments(tmp, &args, arena);
+            if (res != 0) goto failed;
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"args\" missing from Lambda");
+            return 1;
+        }
+        if (_PyObject_HasAttrId(obj, &PyId_body)) {
+            int res;
+            tmp = _PyObject_GetAttrId(obj, &PyId_body);
+            if (tmp == NULL) goto failed;
+            res = obj2ast_expr(tmp, &body, arena);
+            if (res != 0) goto failed;
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"body\" missing from Lambda");
+            return 1;
+        }
+        *out = Lambda(args, body, lineno, col_offset, arena);
+        if (*out == NULL) goto failed;
+        return 0;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject*)IfExp_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        expr_ty test;
+        expr_ty body;
+        expr_ty orelse;
+
+        if (_PyObject_HasAttrId(obj, &PyId_test)) {
+            int res;
+            tmp = _PyObject_GetAttrId(obj, &PyId_test);
+            if (tmp == NULL) goto failed;
+            res = obj2ast_expr(tmp, &test, arena);
+            if (res != 0) goto failed;
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"test\" missing from IfExp");
+            return 1;
+        }
+        if (_PyObject_HasAttrId(obj, &PyId_body)) {
+            int res;
+            tmp = _PyObject_GetAttrId(obj, &PyId_body);
+            if (tmp == NULL) goto failed;
+            res = obj2ast_expr(tmp, &body, arena);
+            if (res != 0) goto failed;
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"body\" missing from IfExp");
+            return 1;
+        }
+        if (_PyObject_HasAttrId(obj, &PyId_orelse)) {
+            int res;
+            tmp = _PyObject_GetAttrId(obj, &PyId_orelse);
+            if (tmp == NULL) goto failed;
+            res = obj2ast_expr(tmp, &orelse, arena);
+            if (res != 0) goto failed;
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"orelse\" missing from IfExp");
+            return 1;
+        }
+        *out = IfExp(test, body, orelse, lineno, col_offset, arena);
+        if (*out == NULL) goto failed;
+        return 0;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject*)Dict_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        asdl_seq* keys;
+        asdl_seq* values;
+
+        if (_PyObject_HasAttrId(obj, &PyId_keys)) {
+            int res;
+            Py_ssize_t len;
+            Py_ssize_t i;
+            tmp = _PyObject_GetAttrId(obj, &PyId_keys);
+            if (tmp == NULL) goto failed;
+            if (!PyList_Check(tmp)) {
+                PyErr_Format(PyExc_TypeError, "Dict field \"keys\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                goto failed;
+            }
+            len = PyList_GET_SIZE(tmp);
+            keys = _Py_asdl_seq_new(len, arena);
+            if (keys == NULL) goto failed;
+            for (i = 0; i < len; i++) {
+                expr_ty value;
+                res = obj2ast_expr(PyList_GET_ITEM(tmp, i), &value, arena);
+                if (res != 0) goto failed;
+                asdl_seq_SET(keys, i, value);
+            }
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"keys\" missing from Dict");
+            return 1;
+        }
+        if (_PyObject_HasAttrId(obj, &PyId_values)) {
+            int res;
+            Py_ssize_t len;
+            Py_ssize_t i;
+            tmp = _PyObject_GetAttrId(obj, &PyId_values);
+            if (tmp == NULL) goto failed;
+            if (!PyList_Check(tmp)) {
+                PyErr_Format(PyExc_TypeError, "Dict field \"values\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                goto failed;
+            }
+            len = PyList_GET_SIZE(tmp);
+            values = _Py_asdl_seq_new(len, arena);
+            if (values == NULL) goto failed;
+            for (i = 0; i < len; i++) {
+                expr_ty value;
+                res = obj2ast_expr(PyList_GET_ITEM(tmp, i), &value, arena);
+                if (res != 0) goto failed;
+                asdl_seq_SET(values, i, value);
+            }
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"values\" missing from Dict");
+            return 1;
+        }
+        *out = Dict(keys, values, lineno, col_offset, arena);
+        if (*out == NULL) goto failed;
+        return 0;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject*)Set_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        asdl_seq* elts;
+
+        if (_PyObject_HasAttrId(obj, &PyId_elts)) {
+            int res;
+            Py_ssize_t len;
+            Py_ssize_t i;
+            tmp = _PyObject_GetAttrId(obj, &PyId_elts);
+            if (tmp == NULL) goto failed;
+            if (!PyList_Check(tmp)) {
+                PyErr_Format(PyExc_TypeError, "Set field \"elts\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                goto failed;
+            }
+            len = PyList_GET_SIZE(tmp);
+            elts = _Py_asdl_seq_new(len, arena);
+            if (elts == NULL) goto failed;
+            for (i = 0; i < len; i++) {
+                expr_ty value;
+                res = obj2ast_expr(PyList_GET_ITEM(tmp, i), &value, arena);
+                if (res != 0) goto failed;
+                asdl_seq_SET(elts, i, value);
+            }
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"elts\" missing from Set");
+            return 1;
+        }
+        *out = Set(elts, lineno, col_offset, arena);
+        if (*out == NULL) goto failed;
+        return 0;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject*)ListComp_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        expr_ty elt;
+        asdl_seq* generators;
+
+        if (_PyObject_HasAttrId(obj, &PyId_elt)) {
+            int res;
+            tmp = _PyObject_GetAttrId(obj, &PyId_elt);
+            if (tmp == NULL) goto failed;
+            res = obj2ast_expr(tmp, &elt, arena);
+            if (res != 0) goto failed;
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"elt\" missing from ListComp");
+            return 1;
+        }
+        if (_PyObject_HasAttrId(obj, &PyId_generators)) {
+            int res;
+            Py_ssize_t len;
+            Py_ssize_t i;
+            tmp = _PyObject_GetAttrId(obj, &PyId_generators);
+            if (tmp == NULL) goto failed;
+            if (!PyList_Check(tmp)) {
+                PyErr_Format(PyExc_TypeError, "ListComp field \"generators\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                goto failed;
+            }
+            len = PyList_GET_SIZE(tmp);
+            generators = _Py_asdl_seq_new(len, arena);
+            if (generators == NULL) goto failed;
+            for (i = 0; i < len; i++) {
+                comprehension_ty value;
+                res = obj2ast_comprehension(PyList_GET_ITEM(tmp, i), &value, arena);
+                if (res != 0) goto failed;
+                asdl_seq_SET(generators, i, value);
+            }
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"generators\" missing from ListComp");
+            return 1;
+        }
+        *out = ListComp(elt, generators, lineno, col_offset, arena);
+        if (*out == NULL) goto failed;
+        return 0;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject*)SetComp_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        expr_ty elt;
+        asdl_seq* generators;
+
+        if (_PyObject_HasAttrId(obj, &PyId_elt)) {
+            int res;
+            tmp = _PyObject_GetAttrId(obj, &PyId_elt);
+            if (tmp == NULL) goto failed;
+            res = obj2ast_expr(tmp, &elt, arena);
+            if (res != 0) goto failed;
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"elt\" missing from SetComp");
+            return 1;
+        }
+        if (_PyObject_HasAttrId(obj, &PyId_generators)) {
+            int res;
+            Py_ssize_t len;
+            Py_ssize_t i;
+            tmp = _PyObject_GetAttrId(obj, &PyId_generators);
+            if (tmp == NULL) goto failed;
+            if (!PyList_Check(tmp)) {
+                PyErr_Format(PyExc_TypeError, "SetComp field \"generators\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                goto failed;
+            }
+            len = PyList_GET_SIZE(tmp);
+            generators = _Py_asdl_seq_new(len, arena);
+            if (generators == NULL) goto failed;
+            for (i = 0; i < len; i++) {
+                comprehension_ty value;
+                res = obj2ast_comprehension(PyList_GET_ITEM(tmp, i), &value, arena);
+                if (res != 0) goto failed;
+                asdl_seq_SET(generators, i, value);
+            }
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"generators\" missing from SetComp");
+            return 1;
+        }
+        *out = SetComp(elt, generators, lineno, col_offset, arena);
+        if (*out == NULL) goto failed;
+        return 0;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject*)DictComp_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        expr_ty key;
+        expr_ty value;
+        asdl_seq* generators;
+
+        if (_PyObject_HasAttrId(obj, &PyId_key)) {
+            int res;
+            tmp = _PyObject_GetAttrId(obj, &PyId_key);
+            if (tmp == NULL) goto failed;
+            res = obj2ast_expr(tmp, &key, arena);
+            if (res != 0) goto failed;
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"key\" missing from DictComp");
+            return 1;
+        }
+        if (_PyObject_HasAttrId(obj, &PyId_value)) {
+            int res;
+            tmp = _PyObject_GetAttrId(obj, &PyId_value);
+            if (tmp == NULL) goto failed;
+            res = obj2ast_expr(tmp, &value, arena);
+            if (res != 0) goto failed;
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"value\" missing from DictComp");
+            return 1;
+        }
+        if (_PyObject_HasAttrId(obj, &PyId_generators)) {
+            int res;
+            Py_ssize_t len;
+            Py_ssize_t i;
+            tmp = _PyObject_GetAttrId(obj, &PyId_generators);
+            if (tmp == NULL) goto failed;
+            if (!PyList_Check(tmp)) {
+                PyErr_Format(PyExc_TypeError, "DictComp field \"generators\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                goto failed;
+            }
+            len = PyList_GET_SIZE(tmp);
+            generators = _Py_asdl_seq_new(len, arena);
+            if (generators == NULL) goto failed;
+            for (i = 0; i < len; i++) {
+                comprehension_ty value;
+                res = obj2ast_comprehension(PyList_GET_ITEM(tmp, i), &value, arena);
+                if (res != 0) goto failed;
+                asdl_seq_SET(generators, i, value);
+            }
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"generators\" missing from DictComp");
+            return 1;
+        }
+        *out = DictComp(key, value, generators, lineno, col_offset, arena);
+        if (*out == NULL) goto failed;
+        return 0;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject*)GeneratorExp_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        expr_ty elt;
+        asdl_seq* generators;
+
+        if (_PyObject_HasAttrId(obj, &PyId_elt)) {
+            int res;
+            tmp = _PyObject_GetAttrId(obj, &PyId_elt);
+            if (tmp == NULL) goto failed;
+            res = obj2ast_expr(tmp, &elt, arena);
+            if (res != 0) goto failed;
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"elt\" missing from GeneratorExp");
+            return 1;
+        }
+        if (_PyObject_HasAttrId(obj, &PyId_generators)) {
+            int res;
+            Py_ssize_t len;
+            Py_ssize_t i;
+            tmp = _PyObject_GetAttrId(obj, &PyId_generators);
+            if (tmp == NULL) goto failed;
+            if (!PyList_Check(tmp)) {
+                PyErr_Format(PyExc_TypeError, "GeneratorExp field \"generators\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                goto failed;
+            }
+            len = PyList_GET_SIZE(tmp);
+            generators = _Py_asdl_seq_new(len, arena);
+            if (generators == NULL) goto failed;
+            for (i = 0; i < len; i++) {
+                comprehension_ty value;
+                res = obj2ast_comprehension(PyList_GET_ITEM(tmp, i), &value, arena);
+                if (res != 0) goto failed;
+                asdl_seq_SET(generators, i, value);
+            }
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"generators\" missing from GeneratorExp");
+            return 1;
+        }
+        *out = GeneratorExp(elt, generators, lineno, col_offset, arena);
+        if (*out == NULL) goto failed;
+        return 0;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject*)Await_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        expr_ty value;
+
+        if (_PyObject_HasAttrId(obj, &PyId_value)) {
+            int res;
+            tmp = _PyObject_GetAttrId(obj, &PyId_value);
+            if (tmp == NULL) goto failed;
+            res = obj2ast_expr(tmp, &value, arena);
+            if (res != 0) goto failed;
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"value\" missing from Await");
+            return 1;
+        }
+        *out = Await(value, lineno, col_offset, arena);
+        if (*out == NULL) goto failed;
+        return 0;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject*)Yield_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        expr_ty value;
+
+        if (exists_not_none(obj, &PyId_value)) {
+            int res;
+            tmp = _PyObject_GetAttrId(obj, &PyId_value);
+            if (tmp == NULL) goto failed;
+            res = obj2ast_expr(tmp, &value, arena);
+            if (res != 0) goto failed;
+            Py_CLEAR(tmp);
+        } else {
+            value = NULL;
+        }
+        *out = Yield(value, lineno, col_offset, arena);
+        if (*out == NULL) goto failed;
+        return 0;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject*)YieldFrom_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        expr_ty value;
+
+        if (_PyObject_HasAttrId(obj, &PyId_value)) {
+            int res;
+            tmp = _PyObject_GetAttrId(obj, &PyId_value);
+            if (tmp == NULL) goto failed;
+            res = obj2ast_expr(tmp, &value, arena);
+            if (res != 0) goto failed;
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"value\" missing from YieldFrom");
+            return 1;
+        }
+        *out = YieldFrom(value, lineno, col_offset, arena);
+        if (*out == NULL) goto failed;
+        return 0;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject*)Compare_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        expr_ty left;
+        asdl_int_seq* ops;
+        asdl_seq* comparators;
+
+        if (_PyObject_HasAttrId(obj, &PyId_left)) {
+            int res;
+            tmp = _PyObject_GetAttrId(obj, &PyId_left);
+            if (tmp == NULL) goto failed;
+            res = obj2ast_expr(tmp, &left, arena);
+            if (res != 0) goto failed;
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"left\" missing from Compare");
+            return 1;
+        }
+        if (_PyObject_HasAttrId(obj, &PyId_ops)) {
+            int res;
+            Py_ssize_t len;
+            Py_ssize_t i;
+            tmp = _PyObject_GetAttrId(obj, &PyId_ops);
+            if (tmp == NULL) goto failed;
+            if (!PyList_Check(tmp)) {
+                PyErr_Format(PyExc_TypeError, "Compare field \"ops\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                goto failed;
+            }
+            len = PyList_GET_SIZE(tmp);
+            ops = _Py_asdl_int_seq_new(len, arena);
+            if (ops == NULL) goto failed;
+            for (i = 0; i < len; i++) {
+                cmpop_ty value;
+                res = obj2ast_cmpop(PyList_GET_ITEM(tmp, i), &value, arena);
+                if (res != 0) goto failed;
+                asdl_seq_SET(ops, i, value);
+            }
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"ops\" missing from Compare");
+            return 1;
+        }
+        if (_PyObject_HasAttrId(obj, &PyId_comparators)) {
+            int res;
+            Py_ssize_t len;
+            Py_ssize_t i;
+            tmp = _PyObject_GetAttrId(obj, &PyId_comparators);
+            if (tmp == NULL) goto failed;
+            if (!PyList_Check(tmp)) {
+                PyErr_Format(PyExc_TypeError, "Compare field \"comparators\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                goto failed;
+            }
+            len = PyList_GET_SIZE(tmp);
+            comparators = _Py_asdl_seq_new(len, arena);
+            if (comparators == NULL) goto failed;
+            for (i = 0; i < len; i++) {
+                expr_ty value;
+                res = obj2ast_expr(PyList_GET_ITEM(tmp, i), &value, arena);
+                if (res != 0) goto failed;
+                asdl_seq_SET(comparators, i, value);
+            }
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"comparators\" missing from Compare");
+            return 1;
+        }
+        *out = Compare(left, ops, comparators, lineno, col_offset, arena);
+        if (*out == NULL) goto failed;
+        return 0;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject*)Call_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        expr_ty func;
+        asdl_seq* args;
+        asdl_seq* keywords;
+
+        if (_PyObject_HasAttrId(obj, &PyId_func)) {
+            int res;
+            tmp = _PyObject_GetAttrId(obj, &PyId_func);
+            if (tmp == NULL) goto failed;
+            res = obj2ast_expr(tmp, &func, arena);
+            if (res != 0) goto failed;
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"func\" missing from Call");
+            return 1;
+        }
+        if (_PyObject_HasAttrId(obj, &PyId_args)) {
+            int res;
+            Py_ssize_t len;
+            Py_ssize_t i;
+            tmp = _PyObject_GetAttrId(obj, &PyId_args);
+            if (tmp == NULL) goto failed;
+            if (!PyList_Check(tmp)) {
+                PyErr_Format(PyExc_TypeError, "Call field \"args\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                goto failed;
+            }
+            len = PyList_GET_SIZE(tmp);
+            args = _Py_asdl_seq_new(len, arena);
+            if (args == NULL) goto failed;
+            for (i = 0; i < len; i++) {
+                expr_ty value;
+                res = obj2ast_expr(PyList_GET_ITEM(tmp, i), &value, arena);
+                if (res != 0) goto failed;
+                asdl_seq_SET(args, i, value);
+            }
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"args\" missing from Call");
+            return 1;
+        }
+        if (_PyObject_HasAttrId(obj, &PyId_keywords)) {
+            int res;
+            Py_ssize_t len;
+            Py_ssize_t i;
+            tmp = _PyObject_GetAttrId(obj, &PyId_keywords);
+            if (tmp == NULL) goto failed;
+            if (!PyList_Check(tmp)) {
+                PyErr_Format(PyExc_TypeError, "Call field \"keywords\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                goto failed;
+            }
+            len = PyList_GET_SIZE(tmp);
+            keywords = _Py_asdl_seq_new(len, arena);
+            if (keywords == NULL) goto failed;
+            for (i = 0; i < len; i++) {
+                keyword_ty value;
+                res = obj2ast_keyword(PyList_GET_ITEM(tmp, i), &value, arena);
+                if (res != 0) goto failed;
+                asdl_seq_SET(keywords, i, value);
+            }
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"keywords\" missing from Call");
+            return 1;
+        }
+        *out = Call(func, args, keywords, lineno, col_offset, arena);
+        if (*out == NULL) goto failed;
+        return 0;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject*)Num_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        object n;
+
+        if (_PyObject_HasAttrId(obj, &PyId_n)) {
+            int res;
+            tmp = _PyObject_GetAttrId(obj, &PyId_n);
+            if (tmp == NULL) goto failed;
+            res = obj2ast_object(tmp, &n, arena);
+            if (res != 0) goto failed;
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"n\" missing from Num");
+            return 1;
+        }
+        *out = Num(n, lineno, col_offset, arena);
+        if (*out == NULL) goto failed;
+        return 0;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject*)Str_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        string s;
+
+        if (_PyObject_HasAttrId(obj, &PyId_s)) {
+            int res;
+            tmp = _PyObject_GetAttrId(obj, &PyId_s);
+            if (tmp == NULL) goto failed;
+            res = obj2ast_string(tmp, &s, arena);
+            if (res != 0) goto failed;
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"s\" missing from Str");
+            return 1;
+        }
+        *out = Str(s, lineno, col_offset, arena);
+        if (*out == NULL) goto failed;
+        return 0;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject*)Bytes_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        bytes s;
+
+        if (_PyObject_HasAttrId(obj, &PyId_s)) {
+            int res;
+            tmp = _PyObject_GetAttrId(obj, &PyId_s);
+            if (tmp == NULL) goto failed;
+            res = obj2ast_bytes(tmp, &s, arena);
+            if (res != 0) goto failed;
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"s\" missing from Bytes");
+            return 1;
+        }
+        *out = Bytes(s, lineno, col_offset, arena);
+        if (*out == NULL) goto failed;
+        return 0;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject*)NameConstant_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        singleton value;
+
+        if (_PyObject_HasAttrId(obj, &PyId_value)) {
+            int res;
+            tmp = _PyObject_GetAttrId(obj, &PyId_value);
+            if (tmp == NULL) goto failed;
+            res = obj2ast_singleton(tmp, &value, arena);
+            if (res != 0) goto failed;
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"value\" missing from NameConstant");
+            return 1;
+        }
+        *out = NameConstant(value, lineno, col_offset, arena);
+        if (*out == NULL) goto failed;
+        return 0;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject*)Ellipsis_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+
+        *out = Ellipsis(lineno, col_offset, arena);
+        if (*out == NULL) goto failed;
+        return 0;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject*)Attribute_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        expr_ty value;
+        identifier attr;
+        expr_context_ty ctx;
+
+        if (_PyObject_HasAttrId(obj, &PyId_value)) {
+            int res;
+            tmp = _PyObject_GetAttrId(obj, &PyId_value);
+            if (tmp == NULL) goto failed;
+            res = obj2ast_expr(tmp, &value, arena);
+            if (res != 0) goto failed;
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"value\" missing from Attribute");
+            return 1;
+        }
+        if (_PyObject_HasAttrId(obj, &PyId_attr)) {
+            int res;
+            tmp = _PyObject_GetAttrId(obj, &PyId_attr);
+            if (tmp == NULL) goto failed;
+            res = obj2ast_identifier(tmp, &attr, arena);
+            if (res != 0) goto failed;
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"attr\" missing from Attribute");
+            return 1;
+        }
+        if (_PyObject_HasAttrId(obj, &PyId_ctx)) {
+            int res;
+            tmp = _PyObject_GetAttrId(obj, &PyId_ctx);
+            if (tmp == NULL) goto failed;
+            res = obj2ast_expr_context(tmp, &ctx, arena);
+            if (res != 0) goto failed;
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"ctx\" missing from Attribute");
+            return 1;
+        }
+        *out = Attribute(value, attr, ctx, lineno, col_offset, arena);
+        if (*out == NULL) goto failed;
+        return 0;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject*)Subscript_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        expr_ty value;
+        slice_ty slice;
+        expr_context_ty ctx;
+
+        if (_PyObject_HasAttrId(obj, &PyId_value)) {
+            int res;
+            tmp = _PyObject_GetAttrId(obj, &PyId_value);
+            if (tmp == NULL) goto failed;
+            res = obj2ast_expr(tmp, &value, arena);
+            if (res != 0) goto failed;
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"value\" missing from Subscript");
+            return 1;
+        }
+        if (_PyObject_HasAttrId(obj, &PyId_slice)) {
+            int res;
+            tmp = _PyObject_GetAttrId(obj, &PyId_slice);
+            if (tmp == NULL) goto failed;
+            res = obj2ast_slice(tmp, &slice, arena);
+            if (res != 0) goto failed;
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"slice\" missing from Subscript");
+            return 1;
+        }
+        if (_PyObject_HasAttrId(obj, &PyId_ctx)) {
+            int res;
+            tmp = _PyObject_GetAttrId(obj, &PyId_ctx);
+            if (tmp == NULL) goto failed;
+            res = obj2ast_expr_context(tmp, &ctx, arena);
+            if (res != 0) goto failed;
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"ctx\" missing from Subscript");
+            return 1;
+        }
+        *out = Subscript(value, slice, ctx, lineno, col_offset, arena);
+        if (*out == NULL) goto failed;
+        return 0;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject*)Starred_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        expr_ty value;
+        expr_context_ty ctx;
+
+        if (_PyObject_HasAttrId(obj, &PyId_value)) {
+            int res;
+            tmp = _PyObject_GetAttrId(obj, &PyId_value);
+            if (tmp == NULL) goto failed;
+            res = obj2ast_expr(tmp, &value, arena);
+            if (res != 0) goto failed;
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"value\" missing from Starred");
+            return 1;
+        }
+        if (_PyObject_HasAttrId(obj, &PyId_ctx)) {
+            int res;
+            tmp = _PyObject_GetAttrId(obj, &PyId_ctx);
+            if (tmp == NULL) goto failed;
+            res = obj2ast_expr_context(tmp, &ctx, arena);
+            if (res != 0) goto failed;
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"ctx\" missing from Starred");
+            return 1;
+        }
+        *out = Starred(value, ctx, lineno, col_offset, arena);
+        if (*out == NULL) goto failed;
+        return 0;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject*)Name_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        identifier id;
+        expr_context_ty ctx;
+
+        if (_PyObject_HasAttrId(obj, &PyId_id)) {
+            int res;
+            tmp = _PyObject_GetAttrId(obj, &PyId_id);
+            if (tmp == NULL) goto failed;
+            res = obj2ast_identifier(tmp, &id, arena);
+            if (res != 0) goto failed;
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"id\" missing from Name");
+            return 1;
+        }
+        if (_PyObject_HasAttrId(obj, &PyId_ctx)) {
+            int res;
+            tmp = _PyObject_GetAttrId(obj, &PyId_ctx);
+            if (tmp == NULL) goto failed;
+            res = obj2ast_expr_context(tmp, &ctx, arena);
+            if (res != 0) goto failed;
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"ctx\" missing from Name");
+            return 1;
+        }
+        *out = Name(id, ctx, lineno, col_offset, arena);
+        if (*out == NULL) goto failed;
+        return 0;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject*)List_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        asdl_seq* elts;
+        expr_context_ty ctx;
+
+        if (_PyObject_HasAttrId(obj, &PyId_elts)) {
+            int res;
+            Py_ssize_t len;
+            Py_ssize_t i;
+            tmp = _PyObject_GetAttrId(obj, &PyId_elts);
+            if (tmp == NULL) goto failed;
+            if (!PyList_Check(tmp)) {
+                PyErr_Format(PyExc_TypeError, "List field \"elts\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                goto failed;
+            }
+            len = PyList_GET_SIZE(tmp);
+            elts = _Py_asdl_seq_new(len, arena);
+            if (elts == NULL) goto failed;
+            for (i = 0; i < len; i++) {
+                expr_ty value;
+                res = obj2ast_expr(PyList_GET_ITEM(tmp, i), &value, arena);
+                if (res != 0) goto failed;
+                asdl_seq_SET(elts, i, value);
+            }
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"elts\" missing from List");
+            return 1;
+        }
+        if (_PyObject_HasAttrId(obj, &PyId_ctx)) {
+            int res;
+            tmp = _PyObject_GetAttrId(obj, &PyId_ctx);
+            if (tmp == NULL) goto failed;
+            res = obj2ast_expr_context(tmp, &ctx, arena);
+            if (res != 0) goto failed;
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"ctx\" missing from List");
+            return 1;
+        }
+        *out = List(elts, ctx, lineno, col_offset, arena);
+        if (*out == NULL) goto failed;
+        return 0;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject*)Tuple_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        asdl_seq* elts;
+        expr_context_ty ctx;
+
+        if (_PyObject_HasAttrId(obj, &PyId_elts)) {
+            int res;
+            Py_ssize_t len;
+            Py_ssize_t i;
+            tmp = _PyObject_GetAttrId(obj, &PyId_elts);
+            if (tmp == NULL) goto failed;
+            if (!PyList_Check(tmp)) {
+                PyErr_Format(PyExc_TypeError, "Tuple field \"elts\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                goto failed;
+            }
+            len = PyList_GET_SIZE(tmp);
+            elts = _Py_asdl_seq_new(len, arena);
+            if (elts == NULL) goto failed;
+            for (i = 0; i < len; i++) {
+                expr_ty value;
+                res = obj2ast_expr(PyList_GET_ITEM(tmp, i), &value, arena);
+                if (res != 0) goto failed;
+                asdl_seq_SET(elts, i, value);
+            }
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"elts\" missing from Tuple");
+            return 1;
+        }
+        if (_PyObject_HasAttrId(obj, &PyId_ctx)) {
+            int res;
+            tmp = _PyObject_GetAttrId(obj, &PyId_ctx);
+            if (tmp == NULL) goto failed;
+            res = obj2ast_expr_context(tmp, &ctx, arena);
+            if (res != 0) goto failed;
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"ctx\" missing from Tuple");
+            return 1;
+        }
+        *out = Tuple(elts, ctx, lineno, col_offset, arena);
+        if (*out == NULL) goto failed;
+        return 0;
+    }
+
+    PyErr_Format(PyExc_TypeError, "expected some sort of expr, but got %R", obj);
+    failed:
+    Py_XDECREF(tmp);
+    return 1;
+}
+
+int
+obj2ast_expr_context(PyObject* obj, expr_context_ty* out, PyArena* arena)
+{
+    int isinstance;
+
+    isinstance = PyObject_IsInstance(obj, (PyObject *)Load_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        *out = Load;
+        return 0;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject *)Store_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        *out = Store;
+        return 0;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject *)Del_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        *out = Del;
+        return 0;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject *)AugLoad_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        *out = AugLoad;
+        return 0;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject *)AugStore_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        *out = AugStore;
+        return 0;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject *)Param_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        *out = Param;
+        return 0;
+    }
+
+    PyErr_Format(PyExc_TypeError, "expected some sort of expr_context, but got %R", obj);
+    return 1;
+}
+
+int
+obj2ast_slice(PyObject* obj, slice_ty* out, PyArena* arena)
+{
+    int isinstance;
+
+    PyObject *tmp = NULL;
+
+    if (obj == Py_None) {
+        *out = NULL;
+        return 0;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject*)Slice_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        expr_ty lower;
+        expr_ty upper;
+        expr_ty step;
+
+        if (exists_not_none(obj, &PyId_lower)) {
+            int res;
+            tmp = _PyObject_GetAttrId(obj, &PyId_lower);
+            if (tmp == NULL) goto failed;
+            res = obj2ast_expr(tmp, &lower, arena);
+            if (res != 0) goto failed;
+            Py_CLEAR(tmp);
+        } else {
+            lower = NULL;
+        }
+        if (exists_not_none(obj, &PyId_upper)) {
+            int res;
+            tmp = _PyObject_GetAttrId(obj, &PyId_upper);
+            if (tmp == NULL) goto failed;
+            res = obj2ast_expr(tmp, &upper, arena);
+            if (res != 0) goto failed;
+            Py_CLEAR(tmp);
+        } else {
+            upper = NULL;
+        }
+        if (exists_not_none(obj, &PyId_step)) {
+            int res;
+            tmp = _PyObject_GetAttrId(obj, &PyId_step);
+            if (tmp == NULL) goto failed;
+            res = obj2ast_expr(tmp, &step, arena);
+            if (res != 0) goto failed;
+            Py_CLEAR(tmp);
+        } else {
+            step = NULL;
+        }
+        *out = Slice(lower, upper, step, arena);
+        if (*out == NULL) goto failed;
+        return 0;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject*)ExtSlice_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        asdl_seq* dims;
+
+        if (_PyObject_HasAttrId(obj, &PyId_dims)) {
+            int res;
+            Py_ssize_t len;
+            Py_ssize_t i;
+            tmp = _PyObject_GetAttrId(obj, &PyId_dims);
+            if (tmp == NULL) goto failed;
+            if (!PyList_Check(tmp)) {
+                PyErr_Format(PyExc_TypeError, "ExtSlice field \"dims\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                goto failed;
+            }
+            len = PyList_GET_SIZE(tmp);
+            dims = _Py_asdl_seq_new(len, arena);
+            if (dims == NULL) goto failed;
+            for (i = 0; i < len; i++) {
+                slice_ty value;
+                res = obj2ast_slice(PyList_GET_ITEM(tmp, i), &value, arena);
+                if (res != 0) goto failed;
+                asdl_seq_SET(dims, i, value);
+            }
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"dims\" missing from ExtSlice");
+            return 1;
+        }
+        *out = ExtSlice(dims, arena);
+        if (*out == NULL) goto failed;
+        return 0;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject*)Index_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        expr_ty value;
+
+        if (_PyObject_HasAttrId(obj, &PyId_value)) {
+            int res;
+            tmp = _PyObject_GetAttrId(obj, &PyId_value);
+            if (tmp == NULL) goto failed;
+            res = obj2ast_expr(tmp, &value, arena);
+            if (res != 0) goto failed;
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"value\" missing from Index");
+            return 1;
+        }
+        *out = Index(value, arena);
+        if (*out == NULL) goto failed;
+        return 0;
+    }
+
+    PyErr_Format(PyExc_TypeError, "expected some sort of slice, but got %R", obj);
+    failed:
+    Py_XDECREF(tmp);
+    return 1;
+}
+
+int
+obj2ast_boolop(PyObject* obj, boolop_ty* out, PyArena* arena)
+{
+    int isinstance;
+
+    isinstance = PyObject_IsInstance(obj, (PyObject *)And_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        *out = And;
+        return 0;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject *)Or_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        *out = Or;
+        return 0;
+    }
+
+    PyErr_Format(PyExc_TypeError, "expected some sort of boolop, but got %R", obj);
+    return 1;
+}
+
+int
+obj2ast_operator(PyObject* obj, operator_ty* out, PyArena* arena)
+{
+    int isinstance;
+
+    isinstance = PyObject_IsInstance(obj, (PyObject *)Add_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        *out = Add;
+        return 0;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject *)Sub_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        *out = Sub;
+        return 0;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject *)Mult_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        *out = Mult;
+        return 0;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject *)MatMult_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        *out = MatMult;
+        return 0;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject *)Div_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        *out = Div;
+        return 0;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject *)Mod_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        *out = Mod;
+        return 0;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject *)Pow_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        *out = Pow;
+        return 0;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject *)LShift_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        *out = LShift;
+        return 0;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject *)RShift_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        *out = RShift;
+        return 0;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject *)BitOr_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        *out = BitOr;
+        return 0;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject *)BitXor_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        *out = BitXor;
+        return 0;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject *)BitAnd_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        *out = BitAnd;
+        return 0;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject *)FloorDiv_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        *out = FloorDiv;
+        return 0;
+    }
+
+    PyErr_Format(PyExc_TypeError, "expected some sort of operator, but got %R", obj);
+    return 1;
+}
+
+int
+obj2ast_unaryop(PyObject* obj, unaryop_ty* out, PyArena* arena)
+{
+    int isinstance;
+
+    isinstance = PyObject_IsInstance(obj, (PyObject *)Invert_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        *out = Invert;
+        return 0;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject *)Not_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        *out = Not;
+        return 0;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject *)UAdd_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        *out = UAdd;
+        return 0;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject *)USub_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        *out = USub;
+        return 0;
+    }
+
+    PyErr_Format(PyExc_TypeError, "expected some sort of unaryop, but got %R", obj);
+    return 1;
+}
+
+int
+obj2ast_cmpop(PyObject* obj, cmpop_ty* out, PyArena* arena)
+{
+    int isinstance;
+
+    isinstance = PyObject_IsInstance(obj, (PyObject *)Eq_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        *out = Eq;
+        return 0;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject *)NotEq_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        *out = NotEq;
+        return 0;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject *)Lt_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        *out = Lt;
+        return 0;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject *)LtE_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        *out = LtE;
+        return 0;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject *)Gt_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        *out = Gt;
+        return 0;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject *)GtE_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        *out = GtE;
+        return 0;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject *)Is_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        *out = Is;
+        return 0;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject *)IsNot_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        *out = IsNot;
+        return 0;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject *)In_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        *out = In;
+        return 0;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject *)NotIn_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        *out = NotIn;
+        return 0;
+    }
+
+    PyErr_Format(PyExc_TypeError, "expected some sort of cmpop, but got %R", obj);
+    return 1;
+}
+
+int
+obj2ast_comprehension(PyObject* obj, comprehension_ty* out, PyArena* arena)
+{
+    PyObject* tmp = NULL;
+    expr_ty target;
+    expr_ty iter;
+    asdl_seq* ifs;
+
+    if (_PyObject_HasAttrId(obj, &PyId_target)) {
+        int res;
+        tmp = _PyObject_GetAttrId(obj, &PyId_target);
+        if (tmp == NULL) goto failed;
+        res = obj2ast_expr(tmp, &target, arena);
+        if (res != 0) goto failed;
+        Py_CLEAR(tmp);
+    } else {
+        PyErr_SetString(PyExc_TypeError, "required field \"target\" missing from comprehension");
+        return 1;
+    }
+    if (_PyObject_HasAttrId(obj, &PyId_iter)) {
+        int res;
+        tmp = _PyObject_GetAttrId(obj, &PyId_iter);
+        if (tmp == NULL) goto failed;
+        res = obj2ast_expr(tmp, &iter, arena);
+        if (res != 0) goto failed;
+        Py_CLEAR(tmp);
+    } else {
+        PyErr_SetString(PyExc_TypeError, "required field \"iter\" missing from comprehension");
+        return 1;
+    }
+    if (_PyObject_HasAttrId(obj, &PyId_ifs)) {
+        int res;
+        Py_ssize_t len;
+        Py_ssize_t i;
+        tmp = _PyObject_GetAttrId(obj, &PyId_ifs);
+        if (tmp == NULL) goto failed;
+        if (!PyList_Check(tmp)) {
+            PyErr_Format(PyExc_TypeError, "comprehension field \"ifs\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+            goto failed;
+        }
+        len = PyList_GET_SIZE(tmp);
+        ifs = _Py_asdl_seq_new(len, arena);
+        if (ifs == NULL) goto failed;
+        for (i = 0; i < len; i++) {
+            expr_ty value;
+            res = obj2ast_expr(PyList_GET_ITEM(tmp, i), &value, arena);
+            if (res != 0) goto failed;
+            asdl_seq_SET(ifs, i, value);
+        }
+        Py_CLEAR(tmp);
+    } else {
+        PyErr_SetString(PyExc_TypeError, "required field \"ifs\" missing from comprehension");
+        return 1;
+    }
+    *out = comprehension(target, iter, ifs, arena);
+    return 0;
+failed:
+    Py_XDECREF(tmp);
+    return 1;
+}
+
+int
+obj2ast_excepthandler(PyObject* obj, excepthandler_ty* out, PyArena* arena)
+{
+    int isinstance;
+
+    PyObject *tmp = NULL;
+    int lineno;
+    int col_offset;
+
+    if (obj == Py_None) {
+        *out = NULL;
+        return 0;
+    }
+    if (_PyObject_HasAttrId(obj, &PyId_lineno)) {
+        int res;
+        tmp = _PyObject_GetAttrId(obj, &PyId_lineno);
+        if (tmp == NULL) goto failed;
+        res = obj2ast_int(tmp, &lineno, arena);
+        if (res != 0) goto failed;
+        Py_CLEAR(tmp);
+    } else {
+        PyErr_SetString(PyExc_TypeError, "required field \"lineno\" missing from excepthandler");
+        return 1;
+    }
+    if (_PyObject_HasAttrId(obj, &PyId_col_offset)) {
+        int res;
+        tmp = _PyObject_GetAttrId(obj, &PyId_col_offset);
+        if (tmp == NULL) goto failed;
+        res = obj2ast_int(tmp, &col_offset, arena);
+        if (res != 0) goto failed;
+        Py_CLEAR(tmp);
+    } else {
+        PyErr_SetString(PyExc_TypeError, "required field \"col_offset\" missing from excepthandler");
+        return 1;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject*)ExceptHandler_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        expr_ty type;
+        identifier name;
+        asdl_seq* body;
+
+        if (exists_not_none(obj, &PyId_type)) {
+            int res;
+            tmp = _PyObject_GetAttrId(obj, &PyId_type);
+            if (tmp == NULL) goto failed;
+            res = obj2ast_expr(tmp, &type, arena);
+            if (res != 0) goto failed;
+            Py_CLEAR(tmp);
+        } else {
+            type = NULL;
+        }
+        if (exists_not_none(obj, &PyId_name)) {
+            int res;
+            tmp = _PyObject_GetAttrId(obj, &PyId_name);
+            if (tmp == NULL) goto failed;
+            res = obj2ast_identifier(tmp, &name, arena);
+            if (res != 0) goto failed;
+            Py_CLEAR(tmp);
+        } else {
+            name = NULL;
+        }
+        if (_PyObject_HasAttrId(obj, &PyId_body)) {
+            int res;
+            Py_ssize_t len;
+            Py_ssize_t i;
+            tmp = _PyObject_GetAttrId(obj, &PyId_body);
+            if (tmp == NULL) goto failed;
+            if (!PyList_Check(tmp)) {
+                PyErr_Format(PyExc_TypeError, "ExceptHandler field \"body\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+                goto failed;
+            }
+            len = PyList_GET_SIZE(tmp);
+            body = _Py_asdl_seq_new(len, arena);
+            if (body == NULL) goto failed;
+            for (i = 0; i < len; i++) {
+                stmt_ty value;
+                res = obj2ast_stmt(PyList_GET_ITEM(tmp, i), &value, arena);
+                if (res != 0) goto failed;
+                asdl_seq_SET(body, i, value);
+            }
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"body\" missing from ExceptHandler");
+            return 1;
+        }
+        *out = ExceptHandler(type, name, body, lineno, col_offset, arena);
+        if (*out == NULL) goto failed;
+        return 0;
+    }
+
+    PyErr_Format(PyExc_TypeError, "expected some sort of excepthandler, but got %R", obj);
+    failed:
+    Py_XDECREF(tmp);
+    return 1;
+}
+
+int
+obj2ast_arguments(PyObject* obj, arguments_ty* out, PyArena* arena)
+{
+    PyObject* tmp = NULL;
+    asdl_seq* args;
+    arg_ty vararg;
+    asdl_seq* kwonlyargs;
+    asdl_seq* kw_defaults;
+    arg_ty kwarg;
+    asdl_seq* defaults;
+
+    if (_PyObject_HasAttrId(obj, &PyId_args)) {
+        int res;
+        Py_ssize_t len;
+        Py_ssize_t i;
+        tmp = _PyObject_GetAttrId(obj, &PyId_args);
+        if (tmp == NULL) goto failed;
+        if (!PyList_Check(tmp)) {
+            PyErr_Format(PyExc_TypeError, "arguments field \"args\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+            goto failed;
+        }
+        len = PyList_GET_SIZE(tmp);
+        args = _Py_asdl_seq_new(len, arena);
+        if (args == NULL) goto failed;
+        for (i = 0; i < len; i++) {
+            arg_ty value;
+            res = obj2ast_arg(PyList_GET_ITEM(tmp, i), &value, arena);
+            if (res != 0) goto failed;
+            asdl_seq_SET(args, i, value);
+        }
+        Py_CLEAR(tmp);
+    } else {
+        PyErr_SetString(PyExc_TypeError, "required field \"args\" missing from arguments");
+        return 1;
+    }
+    if (exists_not_none(obj, &PyId_vararg)) {
+        int res;
+        tmp = _PyObject_GetAttrId(obj, &PyId_vararg);
+        if (tmp == NULL) goto failed;
+        res = obj2ast_arg(tmp, &vararg, arena);
+        if (res != 0) goto failed;
+        Py_CLEAR(tmp);
+    } else {
+        vararg = NULL;
+    }
+    if (_PyObject_HasAttrId(obj, &PyId_kwonlyargs)) {
+        int res;
+        Py_ssize_t len;
+        Py_ssize_t i;
+        tmp = _PyObject_GetAttrId(obj, &PyId_kwonlyargs);
+        if (tmp == NULL) goto failed;
+        if (!PyList_Check(tmp)) {
+            PyErr_Format(PyExc_TypeError, "arguments field \"kwonlyargs\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+            goto failed;
+        }
+        len = PyList_GET_SIZE(tmp);
+        kwonlyargs = _Py_asdl_seq_new(len, arena);
+        if (kwonlyargs == NULL) goto failed;
+        for (i = 0; i < len; i++) {
+            arg_ty value;
+            res = obj2ast_arg(PyList_GET_ITEM(tmp, i), &value, arena);
+            if (res != 0) goto failed;
+            asdl_seq_SET(kwonlyargs, i, value);
+        }
+        Py_CLEAR(tmp);
+    } else {
+        PyErr_SetString(PyExc_TypeError, "required field \"kwonlyargs\" missing from arguments");
+        return 1;
+    }
+    if (_PyObject_HasAttrId(obj, &PyId_kw_defaults)) {
+        int res;
+        Py_ssize_t len;
+        Py_ssize_t i;
+        tmp = _PyObject_GetAttrId(obj, &PyId_kw_defaults);
+        if (tmp == NULL) goto failed;
+        if (!PyList_Check(tmp)) {
+            PyErr_Format(PyExc_TypeError, "arguments field \"kw_defaults\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+            goto failed;
+        }
+        len = PyList_GET_SIZE(tmp);
+        kw_defaults = _Py_asdl_seq_new(len, arena);
+        if (kw_defaults == NULL) goto failed;
+        for (i = 0; i < len; i++) {
+            expr_ty value;
+            res = obj2ast_expr(PyList_GET_ITEM(tmp, i), &value, arena);
+            if (res != 0) goto failed;
+            asdl_seq_SET(kw_defaults, i, value);
+        }
+        Py_CLEAR(tmp);
+    } else {
+        PyErr_SetString(PyExc_TypeError, "required field \"kw_defaults\" missing from arguments");
+        return 1;
+    }
+    if (exists_not_none(obj, &PyId_kwarg)) {
+        int res;
+        tmp = _PyObject_GetAttrId(obj, &PyId_kwarg);
+        if (tmp == NULL) goto failed;
+        res = obj2ast_arg(tmp, &kwarg, arena);
+        if (res != 0) goto failed;
+        Py_CLEAR(tmp);
+    } else {
+        kwarg = NULL;
+    }
+    if (_PyObject_HasAttrId(obj, &PyId_defaults)) {
+        int res;
+        Py_ssize_t len;
+        Py_ssize_t i;
+        tmp = _PyObject_GetAttrId(obj, &PyId_defaults);
+        if (tmp == NULL) goto failed;
+        if (!PyList_Check(tmp)) {
+            PyErr_Format(PyExc_TypeError, "arguments field \"defaults\" must be a list, not a %.200s", tmp->ob_type->tp_name);
+            goto failed;
+        }
+        len = PyList_GET_SIZE(tmp);
+        defaults = _Py_asdl_seq_new(len, arena);
+        if (defaults == NULL) goto failed;
+        for (i = 0; i < len; i++) {
+            expr_ty value;
+            res = obj2ast_expr(PyList_GET_ITEM(tmp, i), &value, arena);
+            if (res != 0) goto failed;
+            asdl_seq_SET(defaults, i, value);
+        }
+        Py_CLEAR(tmp);
+    } else {
+        PyErr_SetString(PyExc_TypeError, "required field \"defaults\" missing from arguments");
+        return 1;
+    }
+    *out = arguments(args, vararg, kwonlyargs, kw_defaults, kwarg, defaults,
+                     arena);
+    return 0;
+failed:
+    Py_XDECREF(tmp);
+    return 1;
+}
+
+int
+obj2ast_arg(PyObject* obj, arg_ty* out, PyArena* arena)
+{
+    PyObject* tmp = NULL;
+    identifier arg;
+    expr_ty annotation;
+    int lineno;
+    int col_offset;
+
+    if (_PyObject_HasAttrId(obj, &PyId_arg)) {
+        int res;
+        tmp = _PyObject_GetAttrId(obj, &PyId_arg);
+        if (tmp == NULL) goto failed;
+        res = obj2ast_identifier(tmp, &arg, arena);
+        if (res != 0) goto failed;
+        Py_CLEAR(tmp);
+    } else {
+        PyErr_SetString(PyExc_TypeError, "required field \"arg\" missing from arg");
+        return 1;
+    }
+    if (exists_not_none(obj, &PyId_annotation)) {
+        int res;
+        tmp = _PyObject_GetAttrId(obj, &PyId_annotation);
+        if (tmp == NULL) goto failed;
+        res = obj2ast_expr(tmp, &annotation, arena);
+        if (res != 0) goto failed;
+        Py_CLEAR(tmp);
+    } else {
+        annotation = NULL;
+    }
+    if (_PyObject_HasAttrId(obj, &PyId_lineno)) {
+        int res;
+        tmp = _PyObject_GetAttrId(obj, &PyId_lineno);
+        if (tmp == NULL) goto failed;
+        res = obj2ast_int(tmp, &lineno, arena);
+        if (res != 0) goto failed;
+        Py_CLEAR(tmp);
+    } else {
+        PyErr_SetString(PyExc_TypeError, "required field \"lineno\" missing from arg");
+        return 1;
+    }
+    if (_PyObject_HasAttrId(obj, &PyId_col_offset)) {
+        int res;
+        tmp = _PyObject_GetAttrId(obj, &PyId_col_offset);
+        if (tmp == NULL) goto failed;
+        res = obj2ast_int(tmp, &col_offset, arena);
+        if (res != 0) goto failed;
+        Py_CLEAR(tmp);
+    } else {
+        PyErr_SetString(PyExc_TypeError, "required field \"col_offset\" missing from arg");
+        return 1;
+    }
+    *out = arg(arg, annotation, lineno, col_offset, arena);
+    return 0;
+failed:
+    Py_XDECREF(tmp);
+    return 1;
+}
+
+int
+obj2ast_keyword(PyObject* obj, keyword_ty* out, PyArena* arena)
+{
+    PyObject* tmp = NULL;
+    identifier arg;
+    expr_ty value;
+
+    if (exists_not_none(obj, &PyId_arg)) {
+        int res;
+        tmp = _PyObject_GetAttrId(obj, &PyId_arg);
+        if (tmp == NULL) goto failed;
+        res = obj2ast_identifier(tmp, &arg, arena);
+        if (res != 0) goto failed;
+        Py_CLEAR(tmp);
+    } else {
+        arg = NULL;
+    }
+    if (_PyObject_HasAttrId(obj, &PyId_value)) {
+        int res;
+        tmp = _PyObject_GetAttrId(obj, &PyId_value);
+        if (tmp == NULL) goto failed;
+        res = obj2ast_expr(tmp, &value, arena);
+        if (res != 0) goto failed;
+        Py_CLEAR(tmp);
+    } else {
+        PyErr_SetString(PyExc_TypeError, "required field \"value\" missing from keyword");
+        return 1;
+    }
+    *out = keyword(arg, value, arena);
+    return 0;
+failed:
+    Py_XDECREF(tmp);
+    return 1;
+}
+
+int
+obj2ast_alias(PyObject* obj, alias_ty* out, PyArena* arena)
+{
+    PyObject* tmp = NULL;
+    identifier name;
+    identifier asname;
+
+    if (_PyObject_HasAttrId(obj, &PyId_name)) {
+        int res;
+        tmp = _PyObject_GetAttrId(obj, &PyId_name);
+        if (tmp == NULL) goto failed;
+        res = obj2ast_identifier(tmp, &name, arena);
+        if (res != 0) goto failed;
+        Py_CLEAR(tmp);
+    } else {
+        PyErr_SetString(PyExc_TypeError, "required field \"name\" missing from alias");
+        return 1;
+    }
+    if (exists_not_none(obj, &PyId_asname)) {
+        int res;
+        tmp = _PyObject_GetAttrId(obj, &PyId_asname);
+        if (tmp == NULL) goto failed;
+        res = obj2ast_identifier(tmp, &asname, arena);
+        if (res != 0) goto failed;
+        Py_CLEAR(tmp);
+    } else {
+        asname = NULL;
+    }
+    *out = alias(name, asname, arena);
+    return 0;
+failed:
+    Py_XDECREF(tmp);
+    return 1;
+}
+
+int
+obj2ast_withitem(PyObject* obj, withitem_ty* out, PyArena* arena)
+{
+    PyObject* tmp = NULL;
+    expr_ty context_expr;
+    expr_ty optional_vars;
+
+    if (_PyObject_HasAttrId(obj, &PyId_context_expr)) {
+        int res;
+        tmp = _PyObject_GetAttrId(obj, &PyId_context_expr);
+        if (tmp == NULL) goto failed;
+        res = obj2ast_expr(tmp, &context_expr, arena);
+        if (res != 0) goto failed;
+        Py_CLEAR(tmp);
+    } else {
+        PyErr_SetString(PyExc_TypeError, "required field \"context_expr\" missing from withitem");
+        return 1;
+    }
+    if (exists_not_none(obj, &PyId_optional_vars)) {
+        int res;
+        tmp = _PyObject_GetAttrId(obj, &PyId_optional_vars);
+        if (tmp == NULL) goto failed;
+        res = obj2ast_expr(tmp, &optional_vars, arena);
+        if (res != 0) goto failed;
+        Py_CLEAR(tmp);
+    } else {
+        optional_vars = NULL;
+    }
+    *out = withitem(context_expr, optional_vars, arena);
+    return 0;
+failed:
+    Py_XDECREF(tmp);
+    return 1;
+}
+
+int
+obj2ast_type_ignore(PyObject* obj, type_ignore_ty* out, PyArena* arena)
+{
+    int isinstance;
+
+    PyObject *tmp = NULL;
+
+    if (obj == Py_None) {
+        *out = NULL;
+        return 0;
+    }
+    isinstance = PyObject_IsInstance(obj, (PyObject*)TypeIgnore_type);
+    if (isinstance == -1) {
+        return 1;
+    }
+    if (isinstance) {
+        int lineno;
+
+        if (_PyObject_HasAttrId(obj, &PyId_lineno)) {
+            int res;
+            tmp = _PyObject_GetAttrId(obj, &PyId_lineno);
+            if (tmp == NULL) goto failed;
+            res = obj2ast_int(tmp, &lineno, arena);
+            if (res != 0) goto failed;
+            Py_CLEAR(tmp);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "required field \"lineno\" missing from TypeIgnore");
+            return 1;
+        }
+        *out = TypeIgnore(lineno, arena);
+        if (*out == NULL) goto failed;
+        return 0;
+    }
+
+    PyErr_Format(PyExc_TypeError, "expected some sort of type_ignore, but got %R", obj);
+    failed:
+    Py_XDECREF(tmp);
+    return 1;
+}
+
+
+PyObject *ast35_parse(PyObject *self, PyObject *args);
+static PyMethodDef ast35_methods[] = {
+    {"_parse",  ast35_parse, METH_VARARGS, "Parse string into typed AST."},
+    {NULL, NULL, 0, NULL}
+};
+static struct PyModuleDef _astmodule35 = {
+  PyModuleDef_HEAD_INIT, "_ast35", NULL, 0, ast35_methods
+};
+PyMODINIT_FUNC
+PyInit__ast35(void)
+{
+    PyObject *m, *d;
+    if (!init_types()) return NULL;
+    m = PyModule_Create(&_astmodule35);
+    if (!m) return NULL;
+    d = PyModule_GetDict(m);
+    if (PyDict_SetItemString(d, "AST", (PyObject*)&AST_type) < 0) return NULL;
+    if (PyModule_AddIntMacro(m, PyCF_ONLY_AST) < 0)
+        return NULL;
+    if (PyDict_SetItemString(d, "mod", (PyObject*)mod_type) < 0) return NULL;
+    if (PyDict_SetItemString(d, "Module", (PyObject*)Module_type) < 0) return
+        NULL;
+    if (PyDict_SetItemString(d, "Interactive", (PyObject*)Interactive_type) <
+        0) return NULL;
+    if (PyDict_SetItemString(d, "Expression", (PyObject*)Expression_type) < 0)
+        return NULL;
+    if (PyDict_SetItemString(d, "FunctionType", (PyObject*)FunctionType_type) <
+        0) return NULL;
+    if (PyDict_SetItemString(d, "Suite", (PyObject*)Suite_type) < 0) return
+        NULL;
+    if (PyDict_SetItemString(d, "stmt", (PyObject*)stmt_type) < 0) return NULL;
+    if (PyDict_SetItemString(d, "FunctionDef", (PyObject*)FunctionDef_type) <
+        0) return NULL;
+    if (PyDict_SetItemString(d, "AsyncFunctionDef",
+        (PyObject*)AsyncFunctionDef_type) < 0) return NULL;
+    if (PyDict_SetItemString(d, "ClassDef", (PyObject*)ClassDef_type) < 0)
+        return NULL;
+    if (PyDict_SetItemString(d, "Return", (PyObject*)Return_type) < 0) return
+        NULL;
+    if (PyDict_SetItemString(d, "Delete", (PyObject*)Delete_type) < 0) return
+        NULL;
+    if (PyDict_SetItemString(d, "Assign", (PyObject*)Assign_type) < 0) return
+        NULL;
+    if (PyDict_SetItemString(d, "AugAssign", (PyObject*)AugAssign_type) < 0)
+        return NULL;
+    if (PyDict_SetItemString(d, "For", (PyObject*)For_type) < 0) return NULL;
+    if (PyDict_SetItemString(d, "AsyncFor", (PyObject*)AsyncFor_type) < 0)
+        return NULL;
+    if (PyDict_SetItemString(d, "While", (PyObject*)While_type) < 0) return
+        NULL;
+    if (PyDict_SetItemString(d, "If", (PyObject*)If_type) < 0) return NULL;
+    if (PyDict_SetItemString(d, "With", (PyObject*)With_type) < 0) return NULL;
+    if (PyDict_SetItemString(d, "AsyncWith", (PyObject*)AsyncWith_type) < 0)
+        return NULL;
+    if (PyDict_SetItemString(d, "Raise", (PyObject*)Raise_type) < 0) return
+        NULL;
+    if (PyDict_SetItemString(d, "Try", (PyObject*)Try_type) < 0) return NULL;
+    if (PyDict_SetItemString(d, "Assert", (PyObject*)Assert_type) < 0) return
+        NULL;
+    if (PyDict_SetItemString(d, "Import", (PyObject*)Import_type) < 0) return
+        NULL;
+    if (PyDict_SetItemString(d, "ImportFrom", (PyObject*)ImportFrom_type) < 0)
+        return NULL;
+    if (PyDict_SetItemString(d, "Global", (PyObject*)Global_type) < 0) return
+        NULL;
+    if (PyDict_SetItemString(d, "Nonlocal", (PyObject*)Nonlocal_type) < 0)
+        return NULL;
+    if (PyDict_SetItemString(d, "Expr", (PyObject*)Expr_type) < 0) return NULL;
+    if (PyDict_SetItemString(d, "Pass", (PyObject*)Pass_type) < 0) return NULL;
+    if (PyDict_SetItemString(d, "Break", (PyObject*)Break_type) < 0) return
+        NULL;
+    if (PyDict_SetItemString(d, "Continue", (PyObject*)Continue_type) < 0)
+        return NULL;
+    if (PyDict_SetItemString(d, "expr", (PyObject*)expr_type) < 0) return NULL;
+    if (PyDict_SetItemString(d, "BoolOp", (PyObject*)BoolOp_type) < 0) return
+        NULL;
+    if (PyDict_SetItemString(d, "BinOp", (PyObject*)BinOp_type) < 0) return
+        NULL;
+    if (PyDict_SetItemString(d, "UnaryOp", (PyObject*)UnaryOp_type) < 0) return
+        NULL;
+    if (PyDict_SetItemString(d, "Lambda", (PyObject*)Lambda_type) < 0) return
+        NULL;
+    if (PyDict_SetItemString(d, "IfExp", (PyObject*)IfExp_type) < 0) return
+        NULL;
+    if (PyDict_SetItemString(d, "Dict", (PyObject*)Dict_type) < 0) return NULL;
+    if (PyDict_SetItemString(d, "Set", (PyObject*)Set_type) < 0) return NULL;
+    if (PyDict_SetItemString(d, "ListComp", (PyObject*)ListComp_type) < 0)
+        return NULL;
+    if (PyDict_SetItemString(d, "SetComp", (PyObject*)SetComp_type) < 0) return
+        NULL;
+    if (PyDict_SetItemString(d, "DictComp", (PyObject*)DictComp_type) < 0)
+        return NULL;
+    if (PyDict_SetItemString(d, "GeneratorExp", (PyObject*)GeneratorExp_type) <
+        0) return NULL;
+    if (PyDict_SetItemString(d, "Await", (PyObject*)Await_type) < 0) return
+        NULL;
+    if (PyDict_SetItemString(d, "Yield", (PyObject*)Yield_type) < 0) return
+        NULL;
+    if (PyDict_SetItemString(d, "YieldFrom", (PyObject*)YieldFrom_type) < 0)
+        return NULL;
+    if (PyDict_SetItemString(d, "Compare", (PyObject*)Compare_type) < 0) return
+        NULL;
+    if (PyDict_SetItemString(d, "Call", (PyObject*)Call_type) < 0) return NULL;
+    if (PyDict_SetItemString(d, "Num", (PyObject*)Num_type) < 0) return NULL;
+    if (PyDict_SetItemString(d, "Str", (PyObject*)Str_type) < 0) return NULL;
+    if (PyDict_SetItemString(d, "Bytes", (PyObject*)Bytes_type) < 0) return
+        NULL;
+    if (PyDict_SetItemString(d, "NameConstant", (PyObject*)NameConstant_type) <
+        0) return NULL;
+    if (PyDict_SetItemString(d, "Ellipsis", (PyObject*)Ellipsis_type) < 0)
+        return NULL;
+    if (PyDict_SetItemString(d, "Attribute", (PyObject*)Attribute_type) < 0)
+        return NULL;
+    if (PyDict_SetItemString(d, "Subscript", (PyObject*)Subscript_type) < 0)
+        return NULL;
+    if (PyDict_SetItemString(d, "Starred", (PyObject*)Starred_type) < 0) return
+        NULL;
+    if (PyDict_SetItemString(d, "Name", (PyObject*)Name_type) < 0) return NULL;
+    if (PyDict_SetItemString(d, "List", (PyObject*)List_type) < 0) return NULL;
+    if (PyDict_SetItemString(d, "Tuple", (PyObject*)Tuple_type) < 0) return
+        NULL;
+    if (PyDict_SetItemString(d, "expr_context", (PyObject*)expr_context_type) <
+        0) return NULL;
+    if (PyDict_SetItemString(d, "Load", (PyObject*)Load_type) < 0) return NULL;
+    if (PyDict_SetItemString(d, "Store", (PyObject*)Store_type) < 0) return
+        NULL;
+    if (PyDict_SetItemString(d, "Del", (PyObject*)Del_type) < 0) return NULL;
+    if (PyDict_SetItemString(d, "AugLoad", (PyObject*)AugLoad_type) < 0) return
+        NULL;
+    if (PyDict_SetItemString(d, "AugStore", (PyObject*)AugStore_type) < 0)
+        return NULL;
+    if (PyDict_SetItemString(d, "Param", (PyObject*)Param_type) < 0) return
+        NULL;
+    if (PyDict_SetItemString(d, "slice", (PyObject*)slice_type) < 0) return
+        NULL;
+    if (PyDict_SetItemString(d, "Slice", (PyObject*)Slice_type) < 0) return
+        NULL;
+    if (PyDict_SetItemString(d, "ExtSlice", (PyObject*)ExtSlice_type) < 0)
+        return NULL;
+    if (PyDict_SetItemString(d, "Index", (PyObject*)Index_type) < 0) return
+        NULL;
+    if (PyDict_SetItemString(d, "boolop", (PyObject*)boolop_type) < 0) return
+        NULL;
+    if (PyDict_SetItemString(d, "And", (PyObject*)And_type) < 0) return NULL;
+    if (PyDict_SetItemString(d, "Or", (PyObject*)Or_type) < 0) return NULL;
+    if (PyDict_SetItemString(d, "operator", (PyObject*)operator_type) < 0)
+        return NULL;
+    if (PyDict_SetItemString(d, "Add", (PyObject*)Add_type) < 0) return NULL;
+    if (PyDict_SetItemString(d, "Sub", (PyObject*)Sub_type) < 0) return NULL;
+    if (PyDict_SetItemString(d, "Mult", (PyObject*)Mult_type) < 0) return NULL;
+    if (PyDict_SetItemString(d, "MatMult", (PyObject*)MatMult_type) < 0) return
+        NULL;
+    if (PyDict_SetItemString(d, "Div", (PyObject*)Div_type) < 0) return NULL;
+    if (PyDict_SetItemString(d, "Mod", (PyObject*)Mod_type) < 0) return NULL;
+    if (PyDict_SetItemString(d, "Pow", (PyObject*)Pow_type) < 0) return NULL;
+    if (PyDict_SetItemString(d, "LShift", (PyObject*)LShift_type) < 0) return
+        NULL;
+    if (PyDict_SetItemString(d, "RShift", (PyObject*)RShift_type) < 0) return
+        NULL;
+    if (PyDict_SetItemString(d, "BitOr", (PyObject*)BitOr_type) < 0) return
+        NULL;
+    if (PyDict_SetItemString(d, "BitXor", (PyObject*)BitXor_type) < 0) return
+        NULL;
+    if (PyDict_SetItemString(d, "BitAnd", (PyObject*)BitAnd_type) < 0) return
+        NULL;
+    if (PyDict_SetItemString(d, "FloorDiv", (PyObject*)FloorDiv_type) < 0)
+        return NULL;
+    if (PyDict_SetItemString(d, "unaryop", (PyObject*)unaryop_type) < 0) return
+        NULL;
+    if (PyDict_SetItemString(d, "Invert", (PyObject*)Invert_type) < 0) return
+        NULL;
+    if (PyDict_SetItemString(d, "Not", (PyObject*)Not_type) < 0) return NULL;
+    if (PyDict_SetItemString(d, "UAdd", (PyObject*)UAdd_type) < 0) return NULL;
+    if (PyDict_SetItemString(d, "USub", (PyObject*)USub_type) < 0) return NULL;
+    if (PyDict_SetItemString(d, "cmpop", (PyObject*)cmpop_type) < 0) return
+        NULL;
+    if (PyDict_SetItemString(d, "Eq", (PyObject*)Eq_type) < 0) return NULL;
+    if (PyDict_SetItemString(d, "NotEq", (PyObject*)NotEq_type) < 0) return
+        NULL;
+    if (PyDict_SetItemString(d, "Lt", (PyObject*)Lt_type) < 0) return NULL;
+    if (PyDict_SetItemString(d, "LtE", (PyObject*)LtE_type) < 0) return NULL;
+    if (PyDict_SetItemString(d, "Gt", (PyObject*)Gt_type) < 0) return NULL;
+    if (PyDict_SetItemString(d, "GtE", (PyObject*)GtE_type) < 0) return NULL;
+    if (PyDict_SetItemString(d, "Is", (PyObject*)Is_type) < 0) return NULL;
+    if (PyDict_SetItemString(d, "IsNot", (PyObject*)IsNot_type) < 0) return
+        NULL;
+    if (PyDict_SetItemString(d, "In", (PyObject*)In_type) < 0) return NULL;
+    if (PyDict_SetItemString(d, "NotIn", (PyObject*)NotIn_type) < 0) return
+        NULL;
+    if (PyDict_SetItemString(d, "comprehension", (PyObject*)comprehension_type)
+        < 0) return NULL;
+    if (PyDict_SetItemString(d, "excepthandler", (PyObject*)excepthandler_type)
+        < 0) return NULL;
+    if (PyDict_SetItemString(d, "ExceptHandler", (PyObject*)ExceptHandler_type)
+        < 0) return NULL;
+    if (PyDict_SetItemString(d, "arguments", (PyObject*)arguments_type) < 0)
+        return NULL;
+    if (PyDict_SetItemString(d, "arg", (PyObject*)arg_type) < 0) return NULL;
+    if (PyDict_SetItemString(d, "keyword", (PyObject*)keyword_type) < 0) return
+        NULL;
+    if (PyDict_SetItemString(d, "alias", (PyObject*)alias_type) < 0) return
+        NULL;
+    if (PyDict_SetItemString(d, "withitem", (PyObject*)withitem_type) < 0)
+        return NULL;
+    if (PyDict_SetItemString(d, "type_ignore", (PyObject*)type_ignore_type) <
+        0) return NULL;
+    if (PyDict_SetItemString(d, "TypeIgnore", (PyObject*)TypeIgnore_type) < 0)
+        return NULL;
+    return m;
+}
+
+
+PyObject* Ta35AST_mod2obj(mod_ty t)
+{
+    if (!init_types())
+        return NULL;
+    return ast2obj_mod(t);
+}
+
+/* mode is 0 for "exec", 1 for "eval" and 2 for "single" input */
+mod_ty Ta35AST_obj2mod(PyObject* ast, PyArena* arena, int mode)
+{
+    mod_ty res;
+    PyObject *req_type[3];
+    char *req_name[] = {"Module", "Expression", "Interactive"};
+    int isinstance;
+
+    req_type[0] = (PyObject*)Module_type;
+    req_type[1] = (PyObject*)Expression_type;
+    req_type[2] = (PyObject*)Interactive_type;
+
+    assert(0 <= mode && mode <= 2);
+
+    if (!init_types())
+        return NULL;
+
+    isinstance = PyObject_IsInstance(ast, req_type[mode]);
+    if (isinstance == -1)
+        return NULL;
+    if (!isinstance) {
+        PyErr_Format(PyExc_TypeError, "expected %s node, got %.400s",
+                     req_name[mode], Py_TYPE(ast)->tp_name);
+        return NULL;
+    }
+    if (obj2ast_mod(ast, &res, arena) != 0)
+        return NULL;
+    else
+        return res;
+}
+
+int Ta35AST_Check(PyObject* obj)
+{
+    if (!init_types())
+        return -1;
+    return PyObject_IsInstance(obj, (PyObject*)&AST_type);
+}
+
+
diff --git a/ast35/Python/ast.c b/ast35/Python/ast.c
new file mode 100644
index 0000000..34186f0
--- /dev/null
+++ b/ast35/Python/ast.c
@@ -0,0 +1,4304 @@
+/*
+ * This file includes functions to transform a concrete syntax tree (CST) to
+ * an abstract syntax tree (AST). The main function is Ta35AST_FromNode().
+ *
+ */
+#include "Python.h"
+#include "Python-ast.h"
+#include "node.h"
+#include "ast.h"
+#include "token.h"
+
+#include <assert.h>
+
+#if PY_MINOR_VERSION < 4
+#define PyErr_ProgramTextObject PyErr_ProgramText
+#endif
+
+static int validate_stmts(asdl_seq *);
+static int validate_exprs(asdl_seq *, expr_context_ty, int);
+static int validate_nonempty_seq(asdl_seq *, const char *, const char *);
+static int validate_stmt(stmt_ty);
+static int validate_expr(expr_ty, expr_context_ty);
+
+static int
+validate_comprehension(asdl_seq *gens)
+{
+    int i;
+    if (!asdl_seq_LEN(gens)) {
+        PyErr_SetString(PyExc_ValueError, "comprehension with no generators");
+        return 0;
+    }
+    for (i = 0; i < asdl_seq_LEN(gens); i++) {
+        comprehension_ty comp = asdl_seq_GET(gens, i);
+        if (!validate_expr(comp->target, Store) ||
+            !validate_expr(comp->iter, Load) ||
+            !validate_exprs(comp->ifs, Load, 0))
+            return 0;
+    }
+    return 1;
+}
+
+static int
+validate_slice(slice_ty slice)
+{
+    switch (slice->kind) {
+    case Slice_kind:
+        return (!slice->v.Slice.lower || validate_expr(slice->v.Slice.lower, Load)) &&
+            (!slice->v.Slice.upper || validate_expr(slice->v.Slice.upper, Load)) &&
+            (!slice->v.Slice.step || validate_expr(slice->v.Slice.step, Load));
+    case ExtSlice_kind: {
+        int i;
+        if (!validate_nonempty_seq(slice->v.ExtSlice.dims, "dims", "ExtSlice"))
+            return 0;
+        for (i = 0; i < asdl_seq_LEN(slice->v.ExtSlice.dims); i++)
+            if (!validate_slice(asdl_seq_GET(slice->v.ExtSlice.dims, i)))
+                return 0;
+        return 1;
+    }
+    case Index_kind:
+        return validate_expr(slice->v.Index.value, Load);
+    default:
+        PyErr_SetString(PyExc_SystemError, "unknown slice node");
+        return 0;
+    }
+}
+
+static int
+validate_keywords(asdl_seq *keywords)
+{
+    int i;
+    for (i = 0; i < asdl_seq_LEN(keywords); i++)
+        if (!validate_expr(((keyword_ty)asdl_seq_GET(keywords, i))->value, Load))
+            return 0;
+    return 1;
+}
+
+static int
+validate_args(asdl_seq *args)
+{
+    int i;
+    for (i = 0; i < asdl_seq_LEN(args); i++) {
+        arg_ty arg = asdl_seq_GET(args, i);
+        if (arg->annotation && !validate_expr(arg->annotation, Load))
+            return 0;
+    }
+    return 1;
+}
+
+static const char *
+expr_context_name(expr_context_ty ctx)
+{
+    switch (ctx) {
+    case Load:
+        return "Load";
+    case Store:
+        return "Store";
+    case Del:
+        return "Del";
+    case AugLoad:
+        return "AugLoad";
+    case AugStore:
+        return "AugStore";
+    case Param:
+        return "Param";
+    default:
+        assert(0);
+        return "(unknown)";
+    }
+}
+
+static int
+validate_arguments(arguments_ty args)
+{
+    if (!validate_args(args->args))
+        return 0;
+    if (args->vararg && args->vararg->annotation
+        && !validate_expr(args->vararg->annotation, Load)) {
+            return 0;
+    }
+    if (!validate_args(args->kwonlyargs))
+        return 0;
+    if (args->kwarg && args->kwarg->annotation
+        && !validate_expr(args->kwarg->annotation, Load)) {
+            return 0;
+    }
+    if (asdl_seq_LEN(args->defaults) > asdl_seq_LEN(args->args)) {
+        PyErr_SetString(PyExc_ValueError, "more positional defaults than args on arguments");
+        return 0;
+    }
+    if (asdl_seq_LEN(args->kw_defaults) != asdl_seq_LEN(args->kwonlyargs)) {
+        PyErr_SetString(PyExc_ValueError, "length of kwonlyargs is not the same as "
+                        "kw_defaults on arguments");
+        return 0;
+    }
+    return validate_exprs(args->defaults, Load, 0) && validate_exprs(args->kw_defaults, Load, 1);
+}
+
+static int
+validate_expr(expr_ty exp, expr_context_ty ctx)
+{
+    int check_ctx = 1;
+    expr_context_ty actual_ctx;
+
+    /* First check expression context. */
+    switch (exp->kind) {
+    case Attribute_kind:
+        actual_ctx = exp->v.Attribute.ctx;
+        break;
+    case Subscript_kind:
+        actual_ctx = exp->v.Subscript.ctx;
+        break;
+    case Starred_kind:
+        actual_ctx = exp->v.Starred.ctx;
+        break;
+    case Name_kind:
+        actual_ctx = exp->v.Name.ctx;
+        break;
+    case List_kind:
+        actual_ctx = exp->v.List.ctx;
+        break;
+    case Tuple_kind:
+        actual_ctx = exp->v.Tuple.ctx;
+        break;
+    default:
+        if (ctx != Load) {
+            PyErr_Format(PyExc_ValueError, "expression which can't be "
+                         "assigned to in %s context", expr_context_name(ctx));
+            return 0;
+        }
+        check_ctx = 0;
+        /* set actual_ctx to prevent gcc warning */
+        actual_ctx = 0;
+    }
+    if (check_ctx && actual_ctx != ctx) {
+        PyErr_Format(PyExc_ValueError, "expression must have %s context but has %s instead",
+                     expr_context_name(ctx), expr_context_name(actual_ctx));
+        return 0;
+    }
+
+    /* Now validate expression. */
+    switch (exp->kind) {
+    case BoolOp_kind:
+        if (asdl_seq_LEN(exp->v.BoolOp.values) < 2) {
+            PyErr_SetString(PyExc_ValueError, "BoolOp with less than 2 values");
+            return 0;
+        }
+        return validate_exprs(exp->v.BoolOp.values, Load, 0);
+    case BinOp_kind:
+        return validate_expr(exp->v.BinOp.left, Load) &&
+            validate_expr(exp->v.BinOp.right, Load);
+    case UnaryOp_kind:
+        return validate_expr(exp->v.UnaryOp.operand, Load);
+    case Lambda_kind:
+        return validate_arguments(exp->v.Lambda.args) &&
+            validate_expr(exp->v.Lambda.body, Load);
+    case IfExp_kind:
+        return validate_expr(exp->v.IfExp.test, Load) &&
+            validate_expr(exp->v.IfExp.body, Load) &&
+            validate_expr(exp->v.IfExp.orelse, Load);
+    case Dict_kind:
+        if (asdl_seq_LEN(exp->v.Dict.keys) != asdl_seq_LEN(exp->v.Dict.values)) {
+            PyErr_SetString(PyExc_ValueError,
+                            "Dict doesn't have the same number of keys as values");
+            return 0;
+        }
+        /* null_ok=1 for keys expressions to allow dict unpacking to work in
+           dict literals, i.e. ``{**{a:b}}`` */
+        return validate_exprs(exp->v.Dict.keys, Load, /*null_ok=*/ 1) &&
+            validate_exprs(exp->v.Dict.values, Load, /*null_ok=*/ 0);
+    case Set_kind:
+        return validate_exprs(exp->v.Set.elts, Load, 0);
+#define COMP(NAME) \
+        case NAME ## _kind: \
+            return validate_comprehension(exp->v.NAME.generators) && \
+                validate_expr(exp->v.NAME.elt, Load);
+    COMP(ListComp)
+    COMP(SetComp)
+    COMP(GeneratorExp)
+#undef COMP
+    case DictComp_kind:
+        return validate_comprehension(exp->v.DictComp.generators) &&
+            validate_expr(exp->v.DictComp.key, Load) &&
+            validate_expr(exp->v.DictComp.value, Load);
+    case Yield_kind:
+        return !exp->v.Yield.value || validate_expr(exp->v.Yield.value, Load);
+    case YieldFrom_kind:
+        return validate_expr(exp->v.YieldFrom.value, Load);
+    case Await_kind:
+        return validate_expr(exp->v.Await.value, Load);
+    case Compare_kind:
+        if (!asdl_seq_LEN(exp->v.Compare.comparators)) {
+            PyErr_SetString(PyExc_ValueError, "Compare with no comparators");
+            return 0;
+        }
+        if (asdl_seq_LEN(exp->v.Compare.comparators) !=
+            asdl_seq_LEN(exp->v.Compare.ops)) {
+            PyErr_SetString(PyExc_ValueError, "Compare has a different number "
+                            "of comparators and operands");
+            return 0;
+        }
+        return validate_exprs(exp->v.Compare.comparators, Load, 0) &&
+            validate_expr(exp->v.Compare.left, Load);
+    case Call_kind:
+        return validate_expr(exp->v.Call.func, Load) &&
+            validate_exprs(exp->v.Call.args, Load, 0) &&
+            validate_keywords(exp->v.Call.keywords);
+    case Num_kind: {
+        PyObject *n = exp->v.Num.n;
+        if (!PyLong_CheckExact(n) && !PyFloat_CheckExact(n) &&
+            !PyComplex_CheckExact(n)) {
+            PyErr_SetString(PyExc_TypeError, "non-numeric type in Num");
+            return 0;
+        }
+        return 1;
+    }
+    case Str_kind: {
+        PyObject *s = exp->v.Str.s;
+        if (!PyUnicode_CheckExact(s)) {
+            PyErr_SetString(PyExc_TypeError, "non-string type in Str");
+            return 0;
+        }
+        return 1;
+    }
+    case Bytes_kind: {
+        PyObject *b = exp->v.Bytes.s;
+        if (!PyBytes_CheckExact(b)) {
+            PyErr_SetString(PyExc_TypeError, "non-bytes type in Bytes");
+            return 0;
+        }
+        return 1;
+    }
+    case Attribute_kind:
+        return validate_expr(exp->v.Attribute.value, Load);
+    case Subscript_kind:
+        return validate_slice(exp->v.Subscript.slice) &&
+            validate_expr(exp->v.Subscript.value, Load);
+    case Starred_kind:
+        return validate_expr(exp->v.Starred.value, ctx);
+    case List_kind:
+        return validate_exprs(exp->v.List.elts, ctx, 0);
+    case Tuple_kind:
+        return validate_exprs(exp->v.Tuple.elts, ctx, 0);
+    /* These last cases don't have any checking. */
+    case Name_kind:
+    case NameConstant_kind:
+    case Ellipsis_kind:
+        return 1;
+    default:
+        PyErr_SetString(PyExc_SystemError, "unexpected expression");
+        return 0;
+    }
+}
+
+static int
+validate_nonempty_seq(asdl_seq *seq, const char *what, const char *owner)
+{
+    if (asdl_seq_LEN(seq))
+        return 1;
+    PyErr_Format(PyExc_ValueError, "empty %s on %s", what, owner);
+    return 0;
+}
+
+static int
+validate_assignlist(asdl_seq *targets, expr_context_ty ctx)
+{
+    return validate_nonempty_seq(targets, "targets", ctx == Del ? "Delete" : "Assign") &&
+        validate_exprs(targets, ctx, 0);
+}
+
+static int
+validate_body(asdl_seq *body, const char *owner)
+{
+    return validate_nonempty_seq(body, "body", owner) && validate_stmts(body);
+}
+
+static int
+validate_stmt(stmt_ty stmt)
+{
+    int i;
+    switch (stmt->kind) {
+    case FunctionDef_kind:
+        return validate_body(stmt->v.FunctionDef.body, "FunctionDef") &&
+            validate_arguments(stmt->v.FunctionDef.args) &&
+            validate_exprs(stmt->v.FunctionDef.decorator_list, Load, 0) &&
+            (!stmt->v.FunctionDef.returns ||
+             validate_expr(stmt->v.FunctionDef.returns, Load));
+    case ClassDef_kind:
+        return validate_body(stmt->v.ClassDef.body, "ClassDef") &&
+            validate_exprs(stmt->v.ClassDef.bases, Load, 0) &&
+            validate_keywords(stmt->v.ClassDef.keywords) &&
+            validate_exprs(stmt->v.ClassDef.decorator_list, Load, 0);
+    case Return_kind:
+        return !stmt->v.Return.value || validate_expr(stmt->v.Return.value, Load);
+    case Delete_kind:
+        return validate_assignlist(stmt->v.Delete.targets, Del);
+    case Assign_kind:
+        return validate_assignlist(stmt->v.Assign.targets, Store) &&
+            validate_expr(stmt->v.Assign.value, Load);
+    case AugAssign_kind:
+        return validate_expr(stmt->v.AugAssign.target, Store) &&
+            validate_expr(stmt->v.AugAssign.value, Load);
+    case For_kind:
+        return validate_expr(stmt->v.For.target, Store) &&
+            validate_expr(stmt->v.For.iter, Load) &&
+            validate_body(stmt->v.For.body, "For") &&
+            validate_stmts(stmt->v.For.orelse);
+    case AsyncFor_kind:
+        return validate_expr(stmt->v.AsyncFor.target, Store) &&
+            validate_expr(stmt->v.AsyncFor.iter, Load) &&
+            validate_body(stmt->v.AsyncFor.body, "AsyncFor") &&
+            validate_stmts(stmt->v.AsyncFor.orelse);
+    case While_kind:
+        return validate_expr(stmt->v.While.test, Load) &&
+            validate_body(stmt->v.While.body, "While") &&
+            validate_stmts(stmt->v.While.orelse);
+    case If_kind:
+        return validate_expr(stmt->v.If.test, Load) &&
+            validate_body(stmt->v.If.body, "If") &&
+            validate_stmts(stmt->v.If.orelse);
+    case With_kind:
+        if (!validate_nonempty_seq(stmt->v.With.items, "items", "With"))
+            return 0;
+        for (i = 0; i < asdl_seq_LEN(stmt->v.With.items); i++) {
+            withitem_ty item = asdl_seq_GET(stmt->v.With.items, i);
+            if (!validate_expr(item->context_expr, Load) ||
+                (item->optional_vars && !validate_expr(item->optional_vars, Store)))
+                return 0;
+        }
+        return validate_body(stmt->v.With.body, "With");
+    case AsyncWith_kind:
+        if (!validate_nonempty_seq(stmt->v.AsyncWith.items, "items", "AsyncWith"))
+            return 0;
+        for (i = 0; i < asdl_seq_LEN(stmt->v.AsyncWith.items); i++) {
+            withitem_ty item = asdl_seq_GET(stmt->v.AsyncWith.items, i);
+            if (!validate_expr(item->context_expr, Load) ||
+                (item->optional_vars && !validate_expr(item->optional_vars, Store)))
+                return 0;
+        }
+        return validate_body(stmt->v.AsyncWith.body, "AsyncWith");
+    case Raise_kind:
+        if (stmt->v.Raise.exc) {
+            return validate_expr(stmt->v.Raise.exc, Load) &&
+                (!stmt->v.Raise.cause || validate_expr(stmt->v.Raise.cause, Load));
+        }
+        if (stmt->v.Raise.cause) {
+            PyErr_SetString(PyExc_ValueError, "Raise with cause but no exception");
+            return 0;
+        }
+        return 1;
+    case Try_kind:
+        if (!validate_body(stmt->v.Try.body, "Try"))
+            return 0;
+        if (!asdl_seq_LEN(stmt->v.Try.handlers) &&
+            !asdl_seq_LEN(stmt->v.Try.finalbody)) {
+            PyErr_SetString(PyExc_ValueError, "Try has neither except handlers nor finalbody");
+            return 0;
+        }
+        if (!asdl_seq_LEN(stmt->v.Try.handlers) &&
+            asdl_seq_LEN(stmt->v.Try.orelse)) {
+            PyErr_SetString(PyExc_ValueError, "Try has orelse but no except handlers");
+            return 0;
+        }
+        for (i = 0; i < asdl_seq_LEN(stmt->v.Try.handlers); i++) {
+            excepthandler_ty handler = asdl_seq_GET(stmt->v.Try.handlers, i);
+            if ((handler->v.ExceptHandler.type &&
+                 !validate_expr(handler->v.ExceptHandler.type, Load)) ||
+                !validate_body(handler->v.ExceptHandler.body, "ExceptHandler"))
+                return 0;
+        }
+        return (!asdl_seq_LEN(stmt->v.Try.finalbody) ||
+                validate_stmts(stmt->v.Try.finalbody)) &&
+            (!asdl_seq_LEN(stmt->v.Try.orelse) ||
+             validate_stmts(stmt->v.Try.orelse));
+    case Assert_kind:
+        return validate_expr(stmt->v.Assert.test, Load) &&
+            (!stmt->v.Assert.msg || validate_expr(stmt->v.Assert.msg, Load));
+    case Import_kind:
+        return validate_nonempty_seq(stmt->v.Import.names, "names", "Import");
+    case ImportFrom_kind:
+        if (stmt->v.ImportFrom.level < -1) {
+            PyErr_SetString(PyExc_ValueError, "ImportFrom level less than -1");
+            return 0;
+        }
+        return validate_nonempty_seq(stmt->v.ImportFrom.names, "names", "ImportFrom");
+    case Global_kind:
+        return validate_nonempty_seq(stmt->v.Global.names, "names", "Global");
+    case Nonlocal_kind:
+        return validate_nonempty_seq(stmt->v.Nonlocal.names, "names", "Nonlocal");
+    case Expr_kind:
+        return validate_expr(stmt->v.Expr.value, Load);
+    case AsyncFunctionDef_kind:
+        return validate_body(stmt->v.AsyncFunctionDef.body, "AsyncFunctionDef") &&
+            validate_arguments(stmt->v.AsyncFunctionDef.args) &&
+            validate_exprs(stmt->v.AsyncFunctionDef.decorator_list, Load, 0) &&
+            (!stmt->v.AsyncFunctionDef.returns ||
+             validate_expr(stmt->v.AsyncFunctionDef.returns, Load));
+    case Pass_kind:
+    case Break_kind:
+    case Continue_kind:
+        return 1;
+    default:
+        PyErr_SetString(PyExc_SystemError, "unexpected statement");
+        return 0;
+    }
+}
+
+static int
+validate_stmts(asdl_seq *seq)
+{
+    int i;
+    for (i = 0; i < asdl_seq_LEN(seq); i++) {
+        stmt_ty stmt = asdl_seq_GET(seq, i);
+        if (stmt) {
+            if (!validate_stmt(stmt))
+                return 0;
+        }
+        else {
+            PyErr_SetString(PyExc_ValueError,
+                            "None disallowed in statement list");
+            return 0;
+        }
+    }
+    return 1;
+}
+
+static int
+validate_exprs(asdl_seq *exprs, expr_context_ty ctx, int null_ok)
+{
+    int i;
+    for (i = 0; i < asdl_seq_LEN(exprs); i++) {
+        expr_ty expr = asdl_seq_GET(exprs, i);
+        if (expr) {
+            if (!validate_expr(expr, ctx))
+                return 0;
+        }
+        else if (!null_ok) {
+            PyErr_SetString(PyExc_ValueError,
+                            "None disallowed in expression list");
+            return 0;
+        }
+
+    }
+    return 1;
+}
+
+int
+Ta35AST_Validate(mod_ty mod)
+{
+    int res = 0;
+
+    switch (mod->kind) {
+    case Module_kind:
+        res = validate_stmts(mod->v.Module.body);
+        break;
+    case Interactive_kind:
+        res = validate_stmts(mod->v.Interactive.body);
+        break;
+    case Expression_kind:
+        res = validate_expr(mod->v.Expression.body, Load);
+        break;
+    case Suite_kind:
+        PyErr_SetString(PyExc_ValueError, "Suite is not valid in the CPython compiler");
+        break;
+    default:
+        PyErr_SetString(PyExc_SystemError, "impossible module node");
+        res = 0;
+        break;
+    }
+    return res;
+}
+
+/* This is done here, so defines like "test" don't interfere with AST use above. */
+#include "grammar.h"
+#include "parsetok.h"
+#include "graminit.h"
+
+/* Data structure used internally */
+struct compiling {
+    char *c_encoding; /* source encoding */
+    PyArena *c_arena; /* arena for allocating memeory */
+    PyObject *c_filename; /* filename */
+    PyObject *c_normalize; /* Normalization function from unicodedata. */
+    PyObject *c_normalize_args; /* Normalization argument tuple. */
+};
+
+static asdl_seq *seq_for_testlist(struct compiling *, const node *);
+static expr_ty ast_for_expr(struct compiling *, const node *);
+static stmt_ty ast_for_stmt(struct compiling *, const node *);
+static asdl_seq *ast_for_suite(struct compiling *, const node *);
+static asdl_seq *ast_for_exprlist(struct compiling *, const node *,
+                                  expr_context_ty);
+static expr_ty ast_for_testlist(struct compiling *, const node *);
+static stmt_ty ast_for_classdef(struct compiling *, const node *, asdl_seq *);
+
+static stmt_ty ast_for_with_stmt(struct compiling *, const node *, int);
+static stmt_ty ast_for_for_stmt(struct compiling *, const node *, int);
+
+/* Note different signature for ast_for_call */
+static expr_ty ast_for_call(struct compiling *, const node *, expr_ty);
+
+static PyObject *parsenumber(struct compiling *, const char *);
+static PyObject *parsestr(struct compiling *, const node *n, int *bytesmode);
+static PyObject *parsestrplus(struct compiling *, const node *n,
+                              int *bytesmode);
+
+#define COMP_GENEXP   0
+#define COMP_LISTCOMP 1
+#define COMP_SETCOMP  2
+
+static int
+init_normalization(struct compiling *c)
+{
+    PyObject *m = PyImport_ImportModuleNoBlock("unicodedata");
+    if (!m)
+        return 0;
+    c->c_normalize = PyObject_GetAttrString(m, "normalize");
+    Py_DECREF(m);
+    if (!c->c_normalize)
+        return 0;
+    c->c_normalize_args = Py_BuildValue("(sN)", "NFKC", Py_None);
+    if (!c->c_normalize_args) {
+        Py_CLEAR(c->c_normalize);
+        return 0;
+    }
+    PyTuple_SET_ITEM(c->c_normalize_args, 1, NULL);
+    return 1;
+}
+
+static identifier
+new_identifier(const char *n, struct compiling *c)
+{
+    PyObject *id = PyUnicode_DecodeUTF8(n, strlen(n), NULL);
+    if (!id)
+        return NULL;
+    /* PyUnicode_DecodeUTF8 should always return a ready string. */
+    assert(PyUnicode_IS_READY(id));
+    /* Check whether there are non-ASCII characters in the
+       identifier; if so, normalize to NFKC. */
+    if (!PyUnicode_IS_ASCII(id)) {
+        PyObject *id2;
+        if (!c->c_normalize && !init_normalization(c)) {
+            Py_DECREF(id);
+            return NULL;
+        }
+        PyTuple_SET_ITEM(c->c_normalize_args, 1, id);
+        id2 = PyObject_Call(c->c_normalize, c->c_normalize_args, NULL);
+        Py_DECREF(id);
+        if (!id2)
+            return NULL;
+        id = id2;
+    }
+    PyUnicode_InternInPlace(&id);
+    if (PyArena_AddPyObject(c->c_arena, id) < 0) {
+        Py_DECREF(id);
+        return NULL;
+    }
+    return id;
+}
+
+#define NEW_IDENTIFIER(n) new_identifier(STR(n), c)
+
+static string
+new_type_comment(const char *s, struct compiling *c)
+{
+  return PyUnicode_DecodeUTF8(s, strlen(s), NULL);
+}
+#define NEW_TYPE_COMMENT(n) new_type_comment(STR(n), c)
+
+static int
+ast_error(struct compiling *c, const node *n, const char *errmsg)
+{
+    PyObject *value, *errstr, *loc, *tmp;
+
+    loc = PyErr_ProgramTextObject(c->c_filename, LINENO(n));
+    if (!loc) {
+        Py_INCREF(Py_None);
+        loc = Py_None;
+    }
+    tmp = Py_BuildValue("(OiiN)", c->c_filename, LINENO(n), n->n_col_offset, loc);
+    if (!tmp)
+        return 0;
+    errstr = PyUnicode_FromString(errmsg);
+    if (!errstr) {
+        Py_DECREF(tmp);
+        return 0;
+    }
+    value = PyTuple_Pack(2, errstr, tmp);
+    Py_DECREF(errstr);
+    Py_DECREF(tmp);
+    if (value) {
+        PyErr_SetObject(PyExc_SyntaxError, value);
+        Py_DECREF(value);
+    }
+    return 0;
+}
+
+/* num_stmts() returns number of contained statements.
+
+   Use this routine to determine how big a sequence is needed for
+   the statements in a parse tree.  Its raison d'etre is this bit of
+   grammar:
+
+   stmt: simple_stmt | compound_stmt
+   simple_stmt: small_stmt (';' small_stmt)* [';'] NEWLINE
+
+   A simple_stmt can contain multiple small_stmt elements joined
+   by semicolons.  If the arg is a simple_stmt, the number of
+   small_stmt elements is returned.
+*/
+
+static int
+num_stmts(const node *n)
+{
+    int i, l;
+    node *ch;
+
+    switch (TYPE(n)) {
+        case single_input:
+            if (TYPE(CHILD(n, 0)) == NEWLINE)
+                return 0;
+            else
+                return num_stmts(CHILD(n, 0));
+        case file_input:
+            l = 0;
+            for (i = 0; i < NCH(n); i++) {
+                ch = CHILD(n, i);
+                if (TYPE(ch) == stmt)
+                    l += num_stmts(ch);
+            }
+            return l;
+        case stmt:
+            return num_stmts(CHILD(n, 0));
+        case compound_stmt:
+            return 1;
+        case simple_stmt:
+            return NCH(n) / 2; /* Divide by 2 to remove count of semi-colons */
+        case suite:
+            /* suite: simple_stmt | NEWLINE [TYPE_COMMENT NEWLINE] INDENT stmt+ DEDENT */
+            if (NCH(n) == 1)
+                return num_stmts(CHILD(n, 0));
+            else {
+                i = 2;
+                l = 0;
+                if (TYPE(CHILD(n, 1)) == TYPE_COMMENT)
+                    i += 2;
+                for (; i < (NCH(n) - 1); i++)
+                    l += num_stmts(CHILD(n, i));
+                return l;
+            }
+        default: {
+            char buf[128];
+
+            sprintf(buf, "Non-statement found: %d %d",
+                    TYPE(n), NCH(n));
+            Py_FatalError(buf);
+        }
+    }
+    assert(0);
+    return 0;
+}
+
+/* Transform the CST rooted at node * to the appropriate AST
+*/
+
+mod_ty
+Ta35AST_FromNodeObject(const node *n, PyCompilerFlags *flags,
+                     PyObject *filename, PyArena *arena)
+{
+    int i, j, k, num;
+    asdl_seq *stmts = NULL;
+    asdl_seq *type_ignores = NULL;
+    stmt_ty s;
+    node *ch;
+    struct compiling c;
+    mod_ty res = NULL;
+    asdl_seq *argtypes = NULL;
+    expr_ty ret, arg;
+
+    c.c_arena = arena;
+    /* borrowed reference */
+    c.c_filename = filename;
+    c.c_normalize = c.c_normalize_args = NULL;
+    if (flags && flags->cf_flags & PyCF_SOURCE_IS_UTF8) {
+        c.c_encoding = "utf-8";
+        if (TYPE(n) == encoding_decl) {
+#if 0
+            ast_error(c, n, "encoding declaration in Unicode string");
+            goto out;
+#endif
+            n = CHILD(n, 0);
+        }
+    } else if (TYPE(n) == encoding_decl) {
+        c.c_encoding = STR(n);
+        n = CHILD(n, 0);
+    } else {
+        /* PEP 3120 */
+        c.c_encoding = "utf-8";
+    }
+
+    k = 0;
+    switch (TYPE(n)) {
+        case file_input:
+            stmts = _Py_asdl_seq_new(num_stmts(n), arena);
+            if (!stmts)
+                goto out;
+            for (i = 0; i < NCH(n) - 1; i++) {
+                ch = CHILD(n, i);
+                if (TYPE(ch) == NEWLINE)
+                    continue;
+                REQ(ch, stmt);
+                num = num_stmts(ch);
+                if (num == 1) {
+                    s = ast_for_stmt(&c, ch);
+                    if (!s)
+                        goto out;
+                    asdl_seq_SET(stmts, k++, s);
+                }
+                else {
+                    ch = CHILD(ch, 0);
+                    REQ(ch, simple_stmt);
+                    for (j = 0; j < num; j++) {
+                        s = ast_for_stmt(&c, CHILD(ch, j * 2));
+                        if (!s)
+                            goto out;
+                        asdl_seq_SET(stmts, k++, s);
+                    }
+                }
+            }
+
+            /* Type ignores are stored under the ENDMARKER in file_input. */
+            ch = CHILD(n, NCH(n) - 1);
+            REQ(ch, ENDMARKER);
+            num = NCH(ch);
+            type_ignores = _Py_asdl_seq_new(num, arena);
+            if (!type_ignores)
+                goto out;
+
+            for (i = 0; i < num; i++) {
+                type_ignore_ty ti = TypeIgnore(LINENO(CHILD(ch, i)), arena);
+                if (!ti)
+                    goto out;
+                asdl_seq_SET(type_ignores, i, ti);
+            }
+
+            res = Module(stmts, type_ignores, arena);
+            break;
+        case eval_input: {
+            expr_ty testlist_ast;
+
+            /* XXX Why not comp_for here? */
+            testlist_ast = ast_for_testlist(&c, CHILD(n, 0));
+            if (!testlist_ast)
+                goto out;
+            res = Expression(testlist_ast, arena);
+            break;
+        }
+        case single_input:
+            if (TYPE(CHILD(n, 0)) == NEWLINE) {
+                stmts = _Py_asdl_seq_new(1, arena);
+                if (!stmts)
+                    goto out;
+                asdl_seq_SET(stmts, 0, Pass(n->n_lineno, n->n_col_offset,
+                                            arena));
+                if (!asdl_seq_GET(stmts, 0))
+                    goto out;
+                res = Interactive(stmts, arena);
+            }
+            else {
+                n = CHILD(n, 0);
+                num = num_stmts(n);
+                stmts = _Py_asdl_seq_new(num, arena);
+                if (!stmts)
+                    goto out;
+                if (num == 1) {
+                    s = ast_for_stmt(&c, n);
+                    if (!s)
+                        goto out;
+                    asdl_seq_SET(stmts, 0, s);
+                }
+                else {
+                    /* Only a simple_stmt can contain multiple statements. */
+                    REQ(n, simple_stmt);
+                    for (i = 0; i < NCH(n); i += 2) {
+                        if (TYPE(CHILD(n, i)) == NEWLINE)
+                            break;
+                        s = ast_for_stmt(&c, CHILD(n, i));
+                        if (!s)
+                            goto out;
+                        asdl_seq_SET(stmts, i / 2, s);
+                    }
+                }
+
+                res = Interactive(stmts, arena);
+            }
+            break;
+        case func_type_input:
+            n = CHILD(n, 0);
+            REQ(n, func_type);
+
+            if (TYPE(CHILD(n, 1)) == typelist) {
+                ch = CHILD(n, 1);
+                /* this is overly permissive -- we don't pay any attention to
+                 * stars on the args -- just parse them into an ordered list */
+                num = 0;
+                for (i = 0; i < NCH(ch); i++) {
+                    if (TYPE(CHILD(ch, i)) == test)
+                        num++;
+                }
+
+                argtypes = _Py_asdl_seq_new(num, arena);
+
+                j = 0;
+                for (i = 0; i < NCH(ch); i++) {
+                    if (TYPE(CHILD(ch, i)) == test) {
+                        arg = ast_for_expr(&c, CHILD(ch, i));
+                        if (!arg)
+                            goto out;
+                        asdl_seq_SET(argtypes, j++, arg);
+                    }
+                }
+            }
+            else
+                argtypes = _Py_asdl_seq_new(0, arena);
+
+            ret = ast_for_expr(&c, CHILD(n, NCH(n) - 1));
+            if (!ret)
+                goto out;
+            res = FunctionType(argtypes, ret, arena);
+            break;
+        default:
+            PyErr_Format(PyExc_SystemError,
+                         "invalid node %d for Ta35AST_FromNode", TYPE(n));
+            goto out;
+    }
+ out:
+    if (c.c_normalize) {
+        Py_DECREF(c.c_normalize);
+        PyTuple_SET_ITEM(c.c_normalize_args, 1, NULL);
+        Py_DECREF(c.c_normalize_args);
+    }
+    return res;
+}
+
+mod_ty
+Ta35AST_FromNode(const node *n, PyCompilerFlags *flags, const char *filename_str,
+               PyArena *arena)
+{
+    mod_ty mod;
+    PyObject *filename;
+    filename = PyUnicode_DecodeFSDefault(filename_str);
+    if (filename == NULL)
+        return NULL;
+    mod = Ta35AST_FromNodeObject(n, flags, filename, arena);
+    Py_DECREF(filename);
+    return mod;
+
+}
+
+/* Return the AST repr. of the operator represented as syntax (|, ^, etc.)
+*/
+
+static operator_ty
+get_operator(const node *n)
+{
+    switch (TYPE(n)) {
+        case VBAR:
+            return BitOr;
+        case CIRCUMFLEX:
+            return BitXor;
+        case AMPER:
+            return BitAnd;
+        case LEFTSHIFT:
+            return LShift;
+        case RIGHTSHIFT:
+            return RShift;
+        case PLUS:
+            return Add;
+        case MINUS:
+            return Sub;
+        case STAR:
+            return Mult;
+        case AT:
+            return MatMult;
+        case SLASH:
+            return Div;
+        case DOUBLESLASH:
+            return FloorDiv;
+        case PERCENT:
+            return Mod;
+        default:
+            return (operator_ty)0;
+    }
+}
+
+static const char* FORBIDDEN[] = {
+    "None",
+    "True",
+    "False",
+    NULL,
+};
+
+static int
+forbidden_name(struct compiling *c, identifier name, const node *n,
+               int full_checks)
+{
+    assert(PyUnicode_Check(name));
+    if (PyUnicode_CompareWithASCIIString(name, "__debug__") == 0) {
+        ast_error(c, n, "assignment to keyword");
+        return 1;
+    }
+    if (full_checks) {
+        const char **p;
+        for (p = FORBIDDEN; *p; p++) {
+            if (PyUnicode_CompareWithASCIIString(name, *p) == 0) {
+                ast_error(c, n, "assignment to keyword");
+                return 1;
+            }
+        }
+    }
+    return 0;
+}
+
+/* Set the context ctx for expr_ty e, recursively traversing e.
+
+   Only sets context for expr kinds that "can appear in assignment context"
+   (according to ../Parser/Python.asdl).  For other expr kinds, it sets
+   an appropriate syntax error and returns false.
+*/
+
+static int
+set_context(struct compiling *c, expr_ty e, expr_context_ty ctx, const node *n)
+{
+    asdl_seq *s = NULL;
+    /* If a particular expression type can't be used for assign / delete,
+       set expr_name to its name and an error message will be generated.
+    */
+    const char* expr_name = NULL;
+
+    /* The ast defines augmented store and load contexts, but the
+       implementation here doesn't actually use them.  The code may be
+       a little more complex than necessary as a result.  It also means
+       that expressions in an augmented assignment have a Store context.
+       Consider restructuring so that augmented assignment uses
+       set_context(), too.
+    */
+    assert(ctx != AugStore && ctx != AugLoad);
+
+    switch (e->kind) {
+        case Attribute_kind:
+            e->v.Attribute.ctx = ctx;
+            if (ctx == Store && forbidden_name(c, e->v.Attribute.attr, n, 1))
+                return 0;
+            break;
+        case Subscript_kind:
+            e->v.Subscript.ctx = ctx;
+            break;
+        case Starred_kind:
+            e->v.Starred.ctx = ctx;
+            if (!set_context(c, e->v.Starred.value, ctx, n))
+                return 0;
+            break;
+        case Name_kind:
+            if (ctx == Store) {
+                if (forbidden_name(c, e->v.Name.id, n, 0))
+                    return 0; /* forbidden_name() calls ast_error() */
+            }
+            e->v.Name.ctx = ctx;
+            break;
+        case List_kind:
+            e->v.List.ctx = ctx;
+            s = e->v.List.elts;
+            break;
+        case Tuple_kind:
+            if (asdl_seq_LEN(e->v.Tuple.elts))  {
+                e->v.Tuple.ctx = ctx;
+                s = e->v.Tuple.elts;
+            }
+            else {
+                expr_name = "()";
+            }
+            break;
+        case Lambda_kind:
+            expr_name = "lambda";
+            break;
+        case Call_kind:
+            expr_name = "function call";
+            break;
+        case BoolOp_kind:
+        case BinOp_kind:
+        case UnaryOp_kind:
+            expr_name = "operator";
+            break;
+        case GeneratorExp_kind:
+            expr_name = "generator expression";
+            break;
+        case Yield_kind:
+        case YieldFrom_kind:
+            expr_name = "yield expression";
+            break;
+        case Await_kind:
+            expr_name = "await expression";
+            break;
+        case ListComp_kind:
+            expr_name = "list comprehension";
+            break;
+        case SetComp_kind:
+            expr_name = "set comprehension";
+            break;
+        case DictComp_kind:
+            expr_name = "dict comprehension";
+            break;
+        case Dict_kind:
+        case Set_kind:
+        case Num_kind:
+        case Str_kind:
+        case Bytes_kind:
+            expr_name = "literal";
+            break;
+        case NameConstant_kind:
+            expr_name = "keyword";
+            break;
+        case Ellipsis_kind:
+            expr_name = "Ellipsis";
+            break;
+        case Compare_kind:
+            expr_name = "comparison";
+            break;
+        case IfExp_kind:
+            expr_name = "conditional expression";
+            break;
+        default:
+            PyErr_Format(PyExc_SystemError,
+                         "unexpected expression in assignment %d (line %d)",
+                         e->kind, e->lineno);
+            return 0;
+    }
+    /* Check for error string set by switch */
+    if (expr_name) {
+        char buf[300];
+        PyOS_snprintf(buf, sizeof(buf),
+                      "can't %s %s",
+                      ctx == Store ? "assign to" : "delete",
+                      expr_name);
+        return ast_error(c, n, buf);
+    }
+
+    /* If the LHS is a list or tuple, we need to set the assignment
+       context for all the contained elements.
+    */
+    if (s) {
+        int i;
+
+        for (i = 0; i < asdl_seq_LEN(s); i++) {
+            if (!set_context(c, (expr_ty)asdl_seq_GET(s, i), ctx, n))
+                return 0;
+        }
+    }
+    return 1;
+}
+
+static operator_ty
+ast_for_augassign(struct compiling *c, const node *n)
+{
+    REQ(n, augassign);
+    n = CHILD(n, 0);
+    switch (STR(n)[0]) {
+        case '+':
+            return Add;
+        case '-':
+            return Sub;
+        case '/':
+            if (STR(n)[1] == '/')
+                return FloorDiv;
+            else
+                return Div;
+        case '%':
+            return Mod;
+        case '<':
+            return LShift;
+        case '>':
+            return RShift;
+        case '&':
+            return BitAnd;
+        case '^':
+            return BitXor;
+        case '|':
+            return BitOr;
+        case '*':
+            if (STR(n)[1] == '*')
+                return Pow;
+            else
+                return Mult;
+        case '@':
+            return MatMult;
+        default:
+            PyErr_Format(PyExc_SystemError, "invalid augassign: %s", STR(n));
+            return (operator_ty)0;
+    }
+}
+
+static cmpop_ty
+ast_for_comp_op(struct compiling *c, const node *n)
+{
+    /* comp_op: '<'|'>'|'=='|'>='|'<='|'!='|'in'|'not' 'in'|'is'
+               |'is' 'not'
+    */
+    REQ(n, comp_op);
+    if (NCH(n) == 1) {
+        n = CHILD(n, 0);
+        switch (TYPE(n)) {
+            case LESS:
+                return Lt;
+            case GREATER:
+                return Gt;
+            case EQEQUAL:                       /* == */
+                return Eq;
+            case LESSEQUAL:
+                return LtE;
+            case GREATEREQUAL:
+                return GtE;
+            case NOTEQUAL:
+                return NotEq;
+            case NAME:
+                if (strcmp(STR(n), "in") == 0)
+                    return In;
+                if (strcmp(STR(n), "is") == 0)
+                    return Is;
+            default:
+                PyErr_Format(PyExc_SystemError, "invalid comp_op: %s",
+                             STR(n));
+                return (cmpop_ty)0;
+        }
+    }
+    else if (NCH(n) == 2) {
+        /* handle "not in" and "is not" */
+        switch (TYPE(CHILD(n, 0))) {
+            case NAME:
+                if (strcmp(STR(CHILD(n, 1)), "in") == 0)
+                    return NotIn;
+                if (strcmp(STR(CHILD(n, 0)), "is") == 0)
+                    return IsNot;
+            default:
+                PyErr_Format(PyExc_SystemError, "invalid comp_op: %s %s",
+                             STR(CHILD(n, 0)), STR(CHILD(n, 1)));
+                return (cmpop_ty)0;
+        }
+    }
+    PyErr_Format(PyExc_SystemError, "invalid comp_op: has %d children",
+                 NCH(n));
+    return (cmpop_ty)0;
+}
+
+static asdl_seq *
+seq_for_testlist(struct compiling *c, const node *n)
+{
+    /* testlist: test (',' test)* [',']
+       testlist_star_expr: test|star_expr (',' test|star_expr)* [',']
+    */
+    asdl_seq *seq;
+    expr_ty expression;
+    int i;
+    assert(TYPE(n) == testlist || TYPE(n) == testlist_star_expr || TYPE(n) == testlist_comp);
+
+    seq = _Py_asdl_seq_new((NCH(n) + 1) / 2, c->c_arena);
+    if (!seq)
+        return NULL;
+
+    for (i = 0; i < NCH(n); i += 2) {
+        const node *ch = CHILD(n, i);
+        assert(TYPE(ch) == test || TYPE(ch) == test_nocond || TYPE(ch) == star_expr);
+
+        expression = ast_for_expr(c, ch);
+        if (!expression)
+            return NULL;
+
+        assert(i / 2 < seq->size);
+        asdl_seq_SET(seq, i / 2, expression);
+    }
+    return seq;
+}
+
+static arg_ty
+ast_for_arg(struct compiling *c, const node *n)
+{
+    identifier name;
+    expr_ty annotation = NULL;
+    node *ch;
+    arg_ty ret;
+
+    assert(TYPE(n) == tfpdef || TYPE(n) == vfpdef);
+    ch = CHILD(n, 0);
+    name = NEW_IDENTIFIER(ch);
+    if (!name)
+        return NULL;
+    if (forbidden_name(c, name, ch, 0))
+        return NULL;
+
+    if (NCH(n) == 3 && TYPE(CHILD(n, 1)) == COLON) {
+        annotation = ast_for_expr(c, CHILD(n, 2));
+        if (!annotation)
+            return NULL;
+    }
+
+    ret = arg(name, annotation, LINENO(n), n->n_col_offset, c->c_arena);
+    if (!ret)
+        return NULL;
+    return ret;
+}
+
+static int
+set_arg_comment_annotation(struct compiling *c, arg_ty arg, node *tc)
+{
+    if (arg->annotation) {
+        ast_error(c, tc,
+                "annotated arg has associated type comment");
+        return 0;
+    }
+
+    arg->annotation = Str(NEW_TYPE_COMMENT(tc), LINENO(tc), tc->n_col_offset, c->c_arena);
+    if (!arg->annotation)
+        return 0;
+
+    return 1;
+}
+
+/* returns -1 if failed to handle keyword only arguments
+   returns new position to keep processing if successful
+               (',' tfpdef ['=' test])*
+                     ^^^
+   start pointing here
+ */
+static int
+handle_keywordonly_args(struct compiling *c, const node *n, int start,
+                        asdl_seq *kwonlyargs, asdl_seq *kwdefaults)
+{
+    PyObject *argname;
+    node *ch;
+    expr_ty expression, annotation;
+    arg_ty arg;
+    int i = start;
+    int j = 0; /* index for kwdefaults and kwonlyargs */
+
+    if (kwonlyargs == NULL) {
+        ast_error(c, CHILD(n, start), "named arguments must follow bare *");
+        return -1;
+    }
+    assert(kwdefaults != NULL);
+    while (i < NCH(n)) {
+        ch = CHILD(n, i);
+        switch (TYPE(ch)) {
+            case vfpdef:
+            case tfpdef:
+                if (i + 1 < NCH(n) && TYPE(CHILD(n, i + 1)) == EQUAL) {
+                    expression = ast_for_expr(c, CHILD(n, i + 2));
+                    if (!expression)
+                        goto error;
+                    asdl_seq_SET(kwdefaults, j, expression);
+                    i += 2; /* '=' and test */
+                }
+                else { /* setting NULL if no default value exists */
+                    asdl_seq_SET(kwdefaults, j, NULL);
+                }
+                if (NCH(ch) == 3) {
+                    /* ch is NAME ':' test */
+                    annotation = ast_for_expr(c, CHILD(ch, 2));
+                    if (!annotation)
+                        goto error;
+                }
+                else {
+                    annotation = NULL;
+                }
+                ch = CHILD(ch, 0);
+                argname = NEW_IDENTIFIER(ch);
+                if (!argname)
+                    goto error;
+                if (forbidden_name(c, argname, ch, 0))
+                    goto error;
+                arg = arg(argname, annotation, LINENO(ch), ch->n_col_offset,
+                          c->c_arena);
+                if (!arg)
+                    goto error;
+                asdl_seq_SET(kwonlyargs, j++, arg);
+                i += 1; /* the name */
+                if (TYPE(CHILD(n, i)) == COMMA)
+                    i += 1; /* the comma, if present */
+                break;
+            case TYPE_COMMENT:
+                /* arg will be equal to the last argument processed */
+                if (!set_arg_comment_annotation(c, arg, ch))
+                    return -1;
+                i += 1;
+                break;
+            case DOUBLESTAR:
+                return i;
+            default:
+                ast_error(c, ch, "unexpected node");
+                goto error;
+        }
+    }
+    return i;
+ error:
+    return -1;
+}
+
+/* Create AST for argument list. */
+
+static arguments_ty
+ast_for_arguments(struct compiling *c, const node *n)
+{
+    /* This function handles both typedargslist (function definition)
+       and varargslist (lambda definition).
+
+       parameters: '(' [typedargslist] ')'
+       typedargslist: ((tfpdef ['=' test] ',')*
+           ('*' [tfpdef] (',' tfpdef ['=' test])* [',' '**' tfpdef]
+           | '**' tfpdef)
+           | tfpdef ['=' test] (',' tfpdef ['=' test])* [','])
+       tfpdef: NAME [':' test]
+       varargslist: ((vfpdef ['=' test] ',')*
+           ('*' [vfpdef] (',' vfpdef ['=' test])*  [',' '**' vfpdef]
+           | '**' vfpdef)
+           | vfpdef ['=' test] (',' vfpdef ['=' test])* [','])
+       vfpdef: NAME
+    */
+    int i, j, k, nposargs = 0, nkwonlyargs = 0;
+    int nposdefaults = 0, found_default = 0;
+    asdl_seq *posargs, *posdefaults, *kwonlyargs, *kwdefaults;
+    arg_ty vararg = NULL, kwarg = NULL;
+    arg_ty arg;
+    node *ch;
+
+    if (TYPE(n) == parameters) {
+        if (NCH(n) == 2) /* () as argument list */
+            return arguments(NULL, NULL, NULL, NULL, NULL, NULL, c->c_arena);
+        n = CHILD(n, 1);
+    }
+    assert(TYPE(n) == typedargslist || TYPE(n) == varargslist);
+
+    /* First count the number of positional args & defaults.  The
+       variable i is the loop index for this for loop and the next.
+       The next loop picks up where the first leaves off.
+    */
+    for (i = 0; i < NCH(n); i++) {
+        ch = CHILD(n, i);
+        if (TYPE(ch) == STAR) {
+            /* skip star */
+            i++;
+            if (i < NCH(n) && /* skip argument following star */
+                (TYPE(CHILD(n, i)) == tfpdef ||
+                 TYPE(CHILD(n, i)) == vfpdef)) {
+                i++;
+            }
+            break;
+        }
+        if (TYPE(ch) == DOUBLESTAR) break;
+        if (TYPE(ch) == vfpdef || TYPE(ch) == tfpdef) nposargs++;
+        if (TYPE(ch) == EQUAL) nposdefaults++;
+    }
+    /* count the number of keyword only args &
+       defaults for keyword only args */
+    for ( ; i < NCH(n); ++i) {
+        ch = CHILD(n, i);
+        if (TYPE(ch) == DOUBLESTAR) break;
+        if (TYPE(ch) == tfpdef || TYPE(ch) == vfpdef) nkwonlyargs++;
+    }
+    posargs = (nposargs ? _Py_asdl_seq_new(nposargs, c->c_arena) : NULL);
+    if (!posargs && nposargs)
+        return NULL;
+    kwonlyargs = (nkwonlyargs ?
+                   _Py_asdl_seq_new(nkwonlyargs, c->c_arena) : NULL);
+    if (!kwonlyargs && nkwonlyargs)
+        return NULL;
+    posdefaults = (nposdefaults ?
+                    _Py_asdl_seq_new(nposdefaults, c->c_arena) : NULL);
+    if (!posdefaults && nposdefaults)
+        return NULL;
+    /* The length of kwonlyargs and kwdefaults are same
+       since we set NULL as default for keyword only argument w/o default
+       - we have sequence data structure, but no dictionary */
+    kwdefaults = (nkwonlyargs ?
+                   _Py_asdl_seq_new(nkwonlyargs, c->c_arena) : NULL);
+    if (!kwdefaults && nkwonlyargs)
+        return NULL;
+
+    if (nposargs + nkwonlyargs > 255) {
+        ast_error(c, n, "more than 255 arguments");
+        return NULL;
+    }
+
+    /* tfpdef: NAME [':' test]
+       vfpdef: NAME
+    */
+    i = 0;
+    j = 0;  /* index for defaults */
+    k = 0;  /* index for args */
+    while (i < NCH(n)) {
+        ch = CHILD(n, i);
+        switch (TYPE(ch)) {
+            case tfpdef:
+            case vfpdef:
+                /* XXX Need to worry about checking if TYPE(CHILD(n, i+1)) is
+                   anything other than EQUAL or a comma? */
+                /* XXX Should NCH(n) check be made a separate check? */
+                if (i + 1 < NCH(n) && TYPE(CHILD(n, i + 1)) == EQUAL) {
+                    expr_ty expression = ast_for_expr(c, CHILD(n, i + 2));
+                    if (!expression)
+                        return NULL;
+                    assert(posdefaults != NULL);
+                    asdl_seq_SET(posdefaults, j++, expression);
+                    i += 2;
+                    found_default = 1;
+                }
+                else if (found_default) {
+                    ast_error(c, n,
+                             "non-default argument follows default argument");
+                    return NULL;
+                }
+                arg = ast_for_arg(c, ch);
+                if (!arg)
+                    return NULL;
+                asdl_seq_SET(posargs, k++, arg);
+                i += 1; /* the name */
+                if (TYPE(CHILD(n, i)) == COMMA)
+                    i += 1; /* the comma, if present */
+                break;
+            case STAR:
+                if (i+1 >= NCH(n) || TYPE(CHILD(n, i+1)) == TYPE_COMMENT) {
+                    ast_error(c, CHILD(n, i),
+                        "named arguments must follow bare *");
+                    return NULL;
+                }
+                ch = CHILD(n, i+1);  /* tfpdef or COMMA */
+                if (TYPE(ch) == COMMA) {
+                    int res = 0;
+                    i += 2; /* now follows keyword only arguments */
+
+                    if (TYPE(CHILD(n, i)) == TYPE_COMMENT) {
+                        ast_error(c, CHILD(n, i),
+                                "bare * has associated type comment");
+                        return NULL;
+                    }
+
+                    res = handle_keywordonly_args(c, n, i,
+                                                  kwonlyargs, kwdefaults);
+                    if (res == -1) return NULL;
+                    i = res; /* res has new position to process */
+                }
+                else {
+                    vararg = ast_for_arg(c, ch);
+                    if (!vararg)
+                        return NULL;
+
+                i += 2; /* the star and the name */
+                if (TYPE(CHILD(n, i)) == COMMA)
+                    i += 1; /* the comma, if present */
+
+                    if (TYPE(CHILD(n, i)) == TYPE_COMMENT) {
+                        if (!set_arg_comment_annotation(c, vararg, CHILD(n, i)))
+                            return NULL;
+
+                        i += 1;
+                    }
+
+                    if (i < NCH(n) && (TYPE(CHILD(n, i)) == tfpdef
+                                    || TYPE(CHILD(n, i)) == vfpdef)) {
+                        int res = 0;
+                        res = handle_keywordonly_args(c, n, i,
+                                                      kwonlyargs, kwdefaults);
+                        if (res == -1) return NULL;
+                        i = res; /* res has new position to process */
+                    }
+                }
+                break;
+            case DOUBLESTAR:
+                ch = CHILD(n, i+1);  /* tfpdef */
+                assert(TYPE(ch) == tfpdef || TYPE(ch) == vfpdef);
+                kwarg = ast_for_arg(c, ch);
+                if (!kwarg)
+                    return NULL;
+                i += 2; /* the double star and the name */
+                if (TYPE(CHILD(n, i)) == COMMA)
+                    i += 1; /* the comma, if present */
+                break;
+            case TYPE_COMMENT:
+                assert(i);
+
+                if (kwarg)
+                    arg = kwarg;
+
+                /* arg will be equal to the last argument processed */
+                if (!set_arg_comment_annotation(c, arg, ch))
+                    return NULL;
+
+                i += 1;
+                break;
+            default:
+                PyErr_Format(PyExc_SystemError,
+                             "unexpected node in varargslist: %d @ %d",
+                             TYPE(ch), i);
+                return NULL;
+        }
+    }
+    return arguments(posargs, vararg, kwonlyargs, kwdefaults, kwarg, posdefaults, c->c_arena);
+}
+
+static expr_ty
+ast_for_dotted_name(struct compiling *c, const node *n)
+{
+    expr_ty e;
+    identifier id;
+    int lineno, col_offset;
+    int i;
+
+    REQ(n, dotted_name);
+
+    lineno = LINENO(n);
+    col_offset = n->n_col_offset;
+
+    id = NEW_IDENTIFIER(CHILD(n, 0));
+    if (!id)
+        return NULL;
+    e = Name(id, Load, lineno, col_offset, c->c_arena);
+    if (!e)
+        return NULL;
+
+    for (i = 2; i < NCH(n); i+=2) {
+        id = NEW_IDENTIFIER(CHILD(n, i));
+        if (!id)
+            return NULL;
+        e = Attribute(e, id, Load, lineno, col_offset, c->c_arena);
+        if (!e)
+            return NULL;
+    }
+
+    return e;
+}
+
+static expr_ty
+ast_for_decorator(struct compiling *c, const node *n)
+{
+    /* decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE */
+    expr_ty d = NULL;
+    expr_ty name_expr;
+
+    REQ(n, decorator);
+    REQ(CHILD(n, 0), AT);
+    REQ(RCHILD(n, -1), NEWLINE);
+
+    name_expr = ast_for_dotted_name(c, CHILD(n, 1));
+    if (!name_expr)
+        return NULL;
+
+    if (NCH(n) == 3) { /* No arguments */
+        d = name_expr;
+        name_expr = NULL;
+    }
+    else if (NCH(n) == 5) { /* Call with no arguments */
+        d = Call(name_expr, NULL, NULL, LINENO(n),
+                 n->n_col_offset, c->c_arena);
+        if (!d)
+            return NULL;
+        name_expr = NULL;
+    }
+    else {
+        d = ast_for_call(c, CHILD(n, 3), name_expr);
+        if (!d)
+            return NULL;
+        name_expr = NULL;
+    }
+
+    return d;
+}
+
+static asdl_seq*
+ast_for_decorators(struct compiling *c, const node *n)
+{
+    asdl_seq* decorator_seq;
+    expr_ty d;
+    int i;
+
+    REQ(n, decorators);
+    decorator_seq = _Py_asdl_seq_new(NCH(n), c->c_arena);
+    if (!decorator_seq)
+        return NULL;
+
+    for (i = 0; i < NCH(n); i++) {
+        d = ast_for_decorator(c, CHILD(n, i));
+        if (!d)
+            return NULL;
+        asdl_seq_SET(decorator_seq, i, d);
+    }
+    return decorator_seq;
+}
+
+static stmt_ty
+ast_for_funcdef_impl(struct compiling *c, const node *n,
+                     asdl_seq *decorator_seq, int is_async)
+{
+    /* funcdef: 'def' NAME parameters ['->' test] ':' [TYPE_COMMENT] suite */
+    identifier name;
+    arguments_ty args;
+    asdl_seq *body;
+    expr_ty returns = NULL;
+    int name_i = 1;
+    node *tc;
+    string type_comment = NULL;
+
+    REQ(n, funcdef);
+
+    name = NEW_IDENTIFIER(CHILD(n, name_i));
+    if (!name)
+        return NULL;
+    if (forbidden_name(c, name, CHILD(n, name_i), 0))
+        return NULL;
+    args = ast_for_arguments(c, CHILD(n, name_i + 1));
+    if (!args)
+        return NULL;
+    if (TYPE(CHILD(n, name_i+2)) == RARROW) {
+        returns = ast_for_expr(c, CHILD(n, name_i + 3));
+        if (!returns)
+            return NULL;
+        name_i += 2;
+    }
+    if (TYPE(CHILD(n, name_i + 3)) == TYPE_COMMENT) {
+        type_comment = NEW_TYPE_COMMENT(CHILD(n, name_i + 3));
+        name_i += 1;
+    }
+    body = ast_for_suite(c, CHILD(n, name_i + 3));
+    if (!body)
+        return NULL;
+
+    if (!type_comment && NCH(CHILD(n, name_i + 3)) > 1) {
+        /* If the function doesn't have a type comment on the same line, check
+         * if the suite has a type comment in it. */
+        tc = CHILD(CHILD(n, name_i + 3), 1);
+
+        if (TYPE(tc) == TYPE_COMMENT)
+            type_comment = NEW_TYPE_COMMENT(tc);
+    }
+
+    if (is_async)
+        return AsyncFunctionDef(name, args, body, decorator_seq, returns,
+                                type_comment, LINENO(n),
+                                n->n_col_offset, c->c_arena);
+    else
+        return FunctionDef(name, args, body, decorator_seq, returns,
+                           type_comment, LINENO(n),
+                           n->n_col_offset, c->c_arena);
+}
+
+static stmt_ty
+ast_for_async_funcdef(struct compiling *c, const node *n, asdl_seq *decorator_seq)
+{
+    /* async_funcdef: ASYNC funcdef */
+    REQ(n, async_funcdef);
+    REQ(CHILD(n, 0), ASYNC);
+    REQ(CHILD(n, 1), funcdef);
+
+    return ast_for_funcdef_impl(c, CHILD(n, 1), decorator_seq,
+                                1 /* is_async */);
+}
+
+static stmt_ty
+ast_for_funcdef(struct compiling *c, const node *n, asdl_seq *decorator_seq)
+{
+    /* funcdef: 'def' NAME parameters ['->' test] ':' suite */
+    return ast_for_funcdef_impl(c, n, decorator_seq,
+                                0 /* is_async */);
+}
+
+
+static stmt_ty
+ast_for_async_stmt(struct compiling *c, const node *n)
+{
+    /* async_stmt: ASYNC (funcdef | with_stmt | for_stmt) */
+    REQ(n, async_stmt);
+    REQ(CHILD(n, 0), ASYNC);
+
+    switch (TYPE(CHILD(n, 1))) {
+        case funcdef:
+            return ast_for_funcdef_impl(c, CHILD(n, 1), NULL,
+                                        1 /* is_async */);
+        case with_stmt:
+            return ast_for_with_stmt(c, CHILD(n, 1),
+                                     1 /* is_async */);
+
+        case for_stmt:
+            return ast_for_for_stmt(c, CHILD(n, 1),
+                                    1 /* is_async */);
+
+        default:
+            PyErr_Format(PyExc_SystemError,
+                         "invalid async stament: %s",
+                         STR(CHILD(n, 1)));
+            return NULL;
+    }
+}
+
+static stmt_ty
+ast_for_decorated(struct compiling *c, const node *n)
+{
+    /* decorated: decorators (classdef | funcdef | async_funcdef) */
+    stmt_ty thing = NULL;
+    asdl_seq *decorator_seq = NULL;
+
+    REQ(n, decorated);
+
+    decorator_seq = ast_for_decorators(c, CHILD(n, 0));
+    if (!decorator_seq)
+      return NULL;
+
+    assert(TYPE(CHILD(n, 1)) == funcdef ||
+           TYPE(CHILD(n, 1)) == async_funcdef ||
+           TYPE(CHILD(n, 1)) == classdef);
+
+    if (TYPE(CHILD(n, 1)) == funcdef) {
+      thing = ast_for_funcdef(c, CHILD(n, 1), decorator_seq);
+    } else if (TYPE(CHILD(n, 1)) == classdef) {
+      thing = ast_for_classdef(c, CHILD(n, 1), decorator_seq);
+    } else if (TYPE(CHILD(n, 1)) == async_funcdef) {
+      thing = ast_for_async_funcdef(c, CHILD(n, 1), decorator_seq);
+    }
+    /* we count the decorators in when talking about the class' or
+     * function's line number */
+    if (thing) {
+        thing->lineno = LINENO(n);
+        thing->col_offset = n->n_col_offset;
+    }
+    return thing;
+}
+
+static expr_ty
+ast_for_lambdef(struct compiling *c, const node *n)
+{
+    /* lambdef: 'lambda' [varargslist] ':' test
+       lambdef_nocond: 'lambda' [varargslist] ':' test_nocond */
+    arguments_ty args;
+    expr_ty expression;
+
+    if (NCH(n) == 3) {
+        args = arguments(NULL, NULL, NULL, NULL, NULL, NULL, c->c_arena);
+        if (!args)
+            return NULL;
+        expression = ast_for_expr(c, CHILD(n, 2));
+        if (!expression)
+            return NULL;
+    }
+    else {
+        args = ast_for_arguments(c, CHILD(n, 1));
+        if (!args)
+            return NULL;
+        expression = ast_for_expr(c, CHILD(n, 3));
+        if (!expression)
+            return NULL;
+    }
+
+    return Lambda(args, expression, LINENO(n), n->n_col_offset, c->c_arena);
+}
+
+static expr_ty
+ast_for_ifexpr(struct compiling *c, const node *n)
+{
+    /* test: or_test 'if' or_test 'else' test */
+    expr_ty expression, body, orelse;
+
+    assert(NCH(n) == 5);
+    body = ast_for_expr(c, CHILD(n, 0));
+    if (!body)
+        return NULL;
+    expression = ast_for_expr(c, CHILD(n, 2));
+    if (!expression)
+        return NULL;
+    orelse = ast_for_expr(c, CHILD(n, 4));
+    if (!orelse)
+        return NULL;
+    return IfExp(expression, body, orelse, LINENO(n), n->n_col_offset,
+                 c->c_arena);
+}
+
+/*
+   Count the number of 'for' loops in a comprehension.
+
+   Helper for ast_for_comprehension().
+*/
+
+static int
+count_comp_fors(struct compiling *c, const node *n)
+{
+    int n_fors = 0;
+
+  count_comp_for:
+    n_fors++;
+    REQ(n, comp_for);
+    if (NCH(n) == 5)
+        n = CHILD(n, 4);
+    else
+        return n_fors;
+  count_comp_iter:
+    REQ(n, comp_iter);
+    n = CHILD(n, 0);
+    if (TYPE(n) == comp_for)
+        goto count_comp_for;
+    else if (TYPE(n) == comp_if) {
+        if (NCH(n) == 3) {
+            n = CHILD(n, 2);
+            goto count_comp_iter;
+        }
+        else
+            return n_fors;
+    }
+
+    /* Should never be reached */
+    PyErr_SetString(PyExc_SystemError,
+                    "logic error in count_comp_fors");
+    return -1;
+}
+
+/* Count the number of 'if' statements in a comprehension.
+
+   Helper for ast_for_comprehension().
+*/
+
+static int
+count_comp_ifs(struct compiling *c, const node *n)
+{
+    int n_ifs = 0;
+
+    while (1) {
+        REQ(n, comp_iter);
+        if (TYPE(CHILD(n, 0)) == comp_for)
+            return n_ifs;
+        n = CHILD(n, 0);
+        REQ(n, comp_if);
+        n_ifs++;
+        if (NCH(n) == 2)
+            return n_ifs;
+        n = CHILD(n, 2);
+    }
+}
+
+static asdl_seq *
+ast_for_comprehension(struct compiling *c, const node *n)
+{
+    int i, n_fors;
+    asdl_seq *comps;
+
+    n_fors = count_comp_fors(c, n);
+    if (n_fors == -1)
+        return NULL;
+
+    comps = _Py_asdl_seq_new(n_fors, c->c_arena);
+    if (!comps)
+        return NULL;
+
+    for (i = 0; i < n_fors; i++) {
+        comprehension_ty comp;
+        asdl_seq *t;
+        expr_ty expression, first;
+        node *for_ch;
+
+        REQ(n, comp_for);
+
+        for_ch = CHILD(n, 1);
+        t = ast_for_exprlist(c, for_ch, Store);
+        if (!t)
+            return NULL;
+        expression = ast_for_expr(c, CHILD(n, 3));
+        if (!expression)
+            return NULL;
+
+        /* Check the # of children rather than the length of t, since
+           (x for x, in ...) has 1 element in t, but still requires a Tuple. */
+        first = (expr_ty)asdl_seq_GET(t, 0);
+        if (NCH(for_ch) == 1)
+            comp = comprehension(first, expression, NULL, c->c_arena);
+        else
+            comp = comprehension(Tuple(t, Store, first->lineno, first->col_offset,
+                                     c->c_arena),
+                               expression, NULL, c->c_arena);
+        if (!comp)
+            return NULL;
+
+        if (NCH(n) == 5) {
+            int j, n_ifs;
+            asdl_seq *ifs;
+
+            n = CHILD(n, 4);
+            n_ifs = count_comp_ifs(c, n);
+            if (n_ifs == -1)
+                return NULL;
+
+            ifs = _Py_asdl_seq_new(n_ifs, c->c_arena);
+            if (!ifs)
+                return NULL;
+
+            for (j = 0; j < n_ifs; j++) {
+                REQ(n, comp_iter);
+                n = CHILD(n, 0);
+                REQ(n, comp_if);
+
+                expression = ast_for_expr(c, CHILD(n, 1));
+                if (!expression)
+                    return NULL;
+                asdl_seq_SET(ifs, j, expression);
+                if (NCH(n) == 3)
+                    n = CHILD(n, 2);
+            }
+            /* on exit, must guarantee that n is a comp_for */
+            if (TYPE(n) == comp_iter)
+                n = CHILD(n, 0);
+            comp->ifs = ifs;
+        }
+        asdl_seq_SET(comps, i, comp);
+    }
+    return comps;
+}
+
+static expr_ty
+ast_for_itercomp(struct compiling *c, const node *n, int type)
+{
+    /* testlist_comp: (test|star_expr)
+     *                ( comp_for | (',' (test|star_expr))* [','] ) */
+    expr_ty elt;
+    asdl_seq *comps;
+    node *ch;
+
+    assert(NCH(n) > 1);
+
+    ch = CHILD(n, 0);
+    elt = ast_for_expr(c, ch);
+    if (!elt)
+        return NULL;
+    if (elt->kind == Starred_kind) {
+        ast_error(c, ch, "iterable unpacking cannot be used in comprehension");
+        return NULL;
+    }
+
+    comps = ast_for_comprehension(c, CHILD(n, 1));
+    if (!comps)
+        return NULL;
+
+    if (type == COMP_GENEXP)
+        return GeneratorExp(elt, comps, LINENO(n), n->n_col_offset, c->c_arena);
+    else if (type == COMP_LISTCOMP)
+        return ListComp(elt, comps, LINENO(n), n->n_col_offset, c->c_arena);
+    else if (type == COMP_SETCOMP)
+        return SetComp(elt, comps, LINENO(n), n->n_col_offset, c->c_arena);
+    else
+        /* Should never happen */
+        return NULL;
+}
+
+/* Fills in the key, value pair corresponding to the dict element.  In case
+ * of an unpacking, key is NULL.  *i is advanced by the number of ast
+ * elements.  Iff successful, nonzero is returned.
+ */
+static int
+ast_for_dictelement(struct compiling *c, const node *n, int *i,
+                    expr_ty *key, expr_ty *value)
+{
+    expr_ty expression;
+    if (TYPE(CHILD(n, *i)) == DOUBLESTAR) {
+        assert(NCH(n) - *i >= 2);
+
+        expression = ast_for_expr(c, CHILD(n, *i + 1));
+        if (!expression)
+            return 0;
+        *key = NULL;
+        *value = expression;
+
+        *i += 2;
+    }
+    else {
+        assert(NCH(n) - *i >= 3);
+
+        expression = ast_for_expr(c, CHILD(n, *i));
+        if (!expression)
+            return 0;
+        *key = expression;
+
+        REQ(CHILD(n, *i + 1), COLON);
+
+        expression = ast_for_expr(c, CHILD(n, *i + 2));
+        if (!expression)
+            return 0;
+        *value = expression;
+
+        *i += 3;
+    }
+    return 1;
+}
+
+static expr_ty
+ast_for_dictcomp(struct compiling *c, const node *n)
+{
+    expr_ty key, value;
+    asdl_seq *comps;
+    int i = 0;
+
+    if (!ast_for_dictelement(c, n, &i, &key, &value))
+        return NULL;
+    assert(key);
+    assert(NCH(n) - i >= 1);
+
+    comps = ast_for_comprehension(c, CHILD(n, i));
+    if (!comps)
+        return NULL;
+
+    return DictComp(key, value, comps, LINENO(n), n->n_col_offset, c->c_arena);
+}
+
+static expr_ty
+ast_for_dictdisplay(struct compiling *c, const node *n)
+{
+    int i;
+    int j;
+    int size;
+    asdl_seq *keys, *values;
+
+    size = (NCH(n) + 1) / 3; /* +1 in case no trailing comma */
+    keys = _Py_asdl_seq_new(size, c->c_arena);
+    if (!keys)
+        return NULL;
+
+    values = _Py_asdl_seq_new(size, c->c_arena);
+    if (!values)
+        return NULL;
+
+    j = 0;
+    for (i = 0; i < NCH(n); i++) {
+        expr_ty key, value;
+
+        if (!ast_for_dictelement(c, n, &i, &key, &value))
+            return NULL;
+        asdl_seq_SET(keys, j, key);
+        asdl_seq_SET(values, j, value);
+
+        j++;
+    }
+    keys->size = j;
+    values->size = j;
+    return Dict(keys, values, LINENO(n), n->n_col_offset, c->c_arena);
+}
+
+static expr_ty
+ast_for_genexp(struct compiling *c, const node *n)
+{
+    assert(TYPE(n) == (testlist_comp) || TYPE(n) == (argument));
+    return ast_for_itercomp(c, n, COMP_GENEXP);
+}
+
+static expr_ty
+ast_for_listcomp(struct compiling *c, const node *n)
+{
+    assert(TYPE(n) == (testlist_comp));
+    return ast_for_itercomp(c, n, COMP_LISTCOMP);
+}
+
+static expr_ty
+ast_for_setcomp(struct compiling *c, const node *n)
+{
+    assert(TYPE(n) == (dictorsetmaker));
+    return ast_for_itercomp(c, n, COMP_SETCOMP);
+}
+
+static expr_ty
+ast_for_setdisplay(struct compiling *c, const node *n)
+{
+    int i;
+    int size;
+    asdl_seq *elts;
+
+    assert(TYPE(n) == (dictorsetmaker));
+    size = (NCH(n) + 1) / 2; /* +1 in case no trailing comma */
+    elts = _Py_asdl_seq_new(size, c->c_arena);
+    if (!elts)
+        return NULL;
+    for (i = 0; i < NCH(n); i += 2) {
+        expr_ty expression;
+        expression = ast_for_expr(c, CHILD(n, i));
+        if (!expression)
+            return NULL;
+        asdl_seq_SET(elts, i / 2, expression);
+    }
+    return Set(elts, LINENO(n), n->n_col_offset, c->c_arena);
+}
+
+static expr_ty
+ast_for_atom(struct compiling *c, const node *n)
+{
+    /* atom: '(' [yield_expr|testlist_comp] ')' | '[' [testlist_comp] ']'
+       | '{' [dictmaker|testlist_comp] '}' | NAME | NUMBER | STRING+
+       | '...' | 'None' | 'True' | 'False'
+    */
+    node *ch = CHILD(n, 0);
+    int bytesmode = 0;
+
+    switch (TYPE(ch)) {
+    case NAME: {
+        PyObject *name;
+        const char *s = STR(ch);
+        size_t len = strlen(s);
+        if (len >= 4 && len <= 5) {
+            if (!strcmp(s, "None"))
+                return NameConstant(Py_None, LINENO(n), n->n_col_offset, c->c_arena);
+            if (!strcmp(s, "True"))
+                return NameConstant(Py_True, LINENO(n), n->n_col_offset, c->c_arena);
+            if (!strcmp(s, "False"))
+                return NameConstant(Py_False, LINENO(n), n->n_col_offset, c->c_arena);
+        }
+        name = new_identifier(s, c);
+        if (!name)
+            return NULL;
+        /* All names start in Load context, but may later be changed. */
+        return Name(name, Load, LINENO(n), n->n_col_offset, c->c_arena);
+    }
+    case STRING: {
+        PyObject *str = parsestrplus(c, n, &bytesmode);
+        if (!str) {
+            const char *errtype = NULL;
+            if (PyErr_ExceptionMatches(PyExc_UnicodeError))
+                errtype = "unicode error";
+            else if (PyErr_ExceptionMatches(PyExc_ValueError))
+                errtype = "value error";
+            if (errtype) {
+                char buf[128];
+                PyObject *type, *value, *tback, *errstr;
+                PyErr_Fetch(&type, &value, &tback);
+                errstr = PyObject_Str(value);
+                if (errstr) {
+                    char *s = _PyUnicode_AsString(errstr);
+                    PyOS_snprintf(buf, sizeof(buf), "(%s) %s", errtype, s);
+                    Py_DECREF(errstr);
+                } else {
+                    PyOS_snprintf(buf, sizeof(buf), "(%s) unknown error", errtype);
+                }
+                ast_error(c, n, buf);
+                Py_DECREF(type);
+                Py_XDECREF(value);
+                Py_XDECREF(tback);
+            }
+            return NULL;
+        }
+        if (PyArena_AddPyObject(c->c_arena, str) < 0) {
+            Py_DECREF(str);
+            return NULL;
+        }
+        if (bytesmode)
+            return Bytes(str, LINENO(n), n->n_col_offset, c->c_arena);
+        else
+            return Str(str, LINENO(n), n->n_col_offset, c->c_arena);
+    }
+    case NUMBER: {
+        PyObject *pynum = parsenumber(c, STR(ch));
+        if (!pynum)
+            return NULL;
+
+        if (PyArena_AddPyObject(c->c_arena, pynum) < 0) {
+            Py_DECREF(pynum);
+            return NULL;
+        }
+        return Num(pynum, LINENO(n), n->n_col_offset, c->c_arena);
+    }
+    case ELLIPSIS: /* Ellipsis */
+        return Ellipsis(LINENO(n), n->n_col_offset, c->c_arena);
+    case LPAR: /* some parenthesized expressions */
+        ch = CHILD(n, 1);
+
+        if (TYPE(ch) == RPAR)
+            return Tuple(NULL, Load, LINENO(n), n->n_col_offset, c->c_arena);
+
+        if (TYPE(ch) == yield_expr)
+            return ast_for_expr(c, ch);
+
+        /* testlist_comp: test ( comp_for | (',' test)* [','] ) */
+        if ((NCH(ch) > 1) && (TYPE(CHILD(ch, 1)) == comp_for))
+            return ast_for_genexp(c, ch);
+
+        return ast_for_testlist(c, ch);
+    case LSQB: /* list (or list comprehension) */
+        ch = CHILD(n, 1);
+
+        if (TYPE(ch) == RSQB)
+            return List(NULL, Load, LINENO(n), n->n_col_offset, c->c_arena);
+
+        REQ(ch, testlist_comp);
+        if (NCH(ch) == 1 || TYPE(CHILD(ch, 1)) == COMMA) {
+            asdl_seq *elts = seq_for_testlist(c, ch);
+            if (!elts)
+                return NULL;
+
+            return List(elts, Load, LINENO(n), n->n_col_offset, c->c_arena);
+        }
+        else
+            return ast_for_listcomp(c, ch);
+    case LBRACE: {
+        /* dictorsetmaker: ( ((test ':' test | '**' test)
+         *                    (comp_for | (',' (test ':' test | '**' test))* [','])) |
+         *                   ((test | '*' test)
+         *                    (comp_for | (',' (test | '*' test))* [','])) ) */
+        expr_ty res;
+        ch = CHILD(n, 1);
+        if (TYPE(ch) == RBRACE) {
+            /* It's an empty dict. */
+            return Dict(NULL, NULL, LINENO(n), n->n_col_offset, c->c_arena);
+        }
+        else {
+            int is_dict = (TYPE(CHILD(ch, 0)) == DOUBLESTAR);
+            if (NCH(ch) == 1 ||
+                    (NCH(ch) > 1 &&
+                     TYPE(CHILD(ch, 1)) == COMMA)) {
+                /* It's a set display. */
+                res = ast_for_setdisplay(c, ch);
+            }
+            else if (NCH(ch) > 1 &&
+                    TYPE(CHILD(ch, 1)) == comp_for) {
+                /* It's a set comprehension. */
+                res = ast_for_setcomp(c, ch);
+            }
+            else if (NCH(ch) > 3 - is_dict &&
+                    TYPE(CHILD(ch, 3 - is_dict)) == comp_for) {
+                /* It's a dictionary comprehension. */
+                if (is_dict) {
+                    ast_error(c, n, "dict unpacking cannot be used in "
+                            "dict comprehension");
+                    return NULL;
+                }
+                res = ast_for_dictcomp(c, ch);
+            }
+            else {
+                /* It's a dictionary display. */
+                res = ast_for_dictdisplay(c, ch);
+            }
+            if (res) {
+                res->lineno = LINENO(n);
+                res->col_offset = n->n_col_offset;
+            }
+            return res;
+        }
+    }
+    default:
+        PyErr_Format(PyExc_SystemError, "unhandled atom %d", TYPE(ch));
+        return NULL;
+    }
+}
+
+static slice_ty
+ast_for_slice(struct compiling *c, const node *n)
+{
+    node *ch;
+    expr_ty lower = NULL, upper = NULL, step = NULL;
+
+    REQ(n, subscript);
+
+    /*
+       subscript: test | [test] ':' [test] [sliceop]
+       sliceop: ':' [test]
+    */
+    ch = CHILD(n, 0);
+    if (NCH(n) == 1 && TYPE(ch) == test) {
+        /* 'step' variable hold no significance in terms of being used over
+           other vars */
+        step = ast_for_expr(c, ch);
+        if (!step)
+            return NULL;
+
+        return Index(step, c->c_arena);
+    }
+
+    if (TYPE(ch) == test) {
+        lower = ast_for_expr(c, ch);
+        if (!lower)
+            return NULL;
+    }
+
+    /* If there's an upper bound it's in the second or third position. */
+    if (TYPE(ch) == COLON) {
+        if (NCH(n) > 1) {
+            node *n2 = CHILD(n, 1);
+
+            if (TYPE(n2) == test) {
+                upper = ast_for_expr(c, n2);
+                if (!upper)
+                    return NULL;
+            }
+        }
+    } else if (NCH(n) > 2) {
+        node *n2 = CHILD(n, 2);
+
+        if (TYPE(n2) == test) {
+            upper = ast_for_expr(c, n2);
+            if (!upper)
+                return NULL;
+        }
+    }
+
+    ch = CHILD(n, NCH(n) - 1);
+    if (TYPE(ch) == sliceop) {
+        if (NCH(ch) != 1) {
+            ch = CHILD(ch, 1);
+            if (TYPE(ch) == test) {
+                step = ast_for_expr(c, ch);
+                if (!step)
+                    return NULL;
+            }
+        }
+    }
+
+    return Slice(lower, upper, step, c->c_arena);
+}
+
+static expr_ty
+ast_for_binop(struct compiling *c, const node *n)
+{
+    /* Must account for a sequence of expressions.
+       How should A op B op C by represented?
+       BinOp(BinOp(A, op, B), op, C).
+    */
+
+    int i, nops;
+    expr_ty expr1, expr2, result;
+    operator_ty newoperator;
+
+    expr1 = ast_for_expr(c, CHILD(n, 0));
+    if (!expr1)
+        return NULL;
+
+    expr2 = ast_for_expr(c, CHILD(n, 2));
+    if (!expr2)
+        return NULL;
+
+    newoperator = get_operator(CHILD(n, 1));
+    if (!newoperator)
+        return NULL;
+
+    result = BinOp(expr1, newoperator, expr2, LINENO(n), n->n_col_offset,
+                   c->c_arena);
+    if (!result)
+        return NULL;
+
+    nops = (NCH(n) - 1) / 2;
+    for (i = 1; i < nops; i++) {
+        expr_ty tmp_result, tmp;
+        const node* next_oper = CHILD(n, i * 2 + 1);
+
+        newoperator = get_operator(next_oper);
+        if (!newoperator)
+            return NULL;
+
+        tmp = ast_for_expr(c, CHILD(n, i * 2 + 2));
+        if (!tmp)
+            return NULL;
+
+        tmp_result = BinOp(result, newoperator, tmp,
+                           LINENO(next_oper), next_oper->n_col_offset,
+                           c->c_arena);
+        if (!tmp_result)
+            return NULL;
+        result = tmp_result;
+    }
+    return result;
+}
+
+static expr_ty
+ast_for_trailer(struct compiling *c, const node *n, expr_ty left_expr)
+{
+    /* trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME
+       subscriptlist: subscript (',' subscript)* [',']
+       subscript: '.' '.' '.' | test | [test] ':' [test] [sliceop]
+     */
+    REQ(n, trailer);
+    if (TYPE(CHILD(n, 0)) == LPAR) {
+        if (NCH(n) == 2)
+            return Call(left_expr, NULL, NULL, LINENO(n),
+                        n->n_col_offset, c->c_arena);
+        else
+            return ast_for_call(c, CHILD(n, 1), left_expr);
+    }
+    else if (TYPE(CHILD(n, 0)) == DOT) {
+        PyObject *attr_id = NEW_IDENTIFIER(CHILD(n, 1));
+        if (!attr_id)
+            return NULL;
+        return Attribute(left_expr, attr_id, Load,
+                         LINENO(n), n->n_col_offset, c->c_arena);
+    }
+    else {
+        REQ(CHILD(n, 0), LSQB);
+        REQ(CHILD(n, 2), RSQB);
+        n = CHILD(n, 1);
+        if (NCH(n) == 1) {
+            slice_ty slc = ast_for_slice(c, CHILD(n, 0));
+            if (!slc)
+                return NULL;
+            return Subscript(left_expr, slc, Load, LINENO(n), n->n_col_offset,
+                             c->c_arena);
+        }
+        else {
+            /* The grammar is ambiguous here. The ambiguity is resolved
+               by treating the sequence as a tuple literal if there are
+               no slice features.
+            */
+            int j;
+            slice_ty slc;
+            expr_ty e;
+            int simple = 1;
+            asdl_seq *slices, *elts;
+            slices = _Py_asdl_seq_new((NCH(n) + 1) / 2, c->c_arena);
+            if (!slices)
+                return NULL;
+            for (j = 0; j < NCH(n); j += 2) {
+                slc = ast_for_slice(c, CHILD(n, j));
+                if (!slc)
+                    return NULL;
+                if (slc->kind != Index_kind)
+                    simple = 0;
+                asdl_seq_SET(slices, j / 2, slc);
+            }
+            if (!simple) {
+                return Subscript(left_expr, ExtSlice(slices, c->c_arena),
+                                 Load, LINENO(n), n->n_col_offset, c->c_arena);
+            }
+            /* extract Index values and put them in a Tuple */
+            elts = _Py_asdl_seq_new(asdl_seq_LEN(slices), c->c_arena);
+            if (!elts)
+                return NULL;
+            for (j = 0; j < asdl_seq_LEN(slices); ++j) {
+                slc = (slice_ty)asdl_seq_GET(slices, j);
+                assert(slc->kind == Index_kind  && slc->v.Index.value);
+                asdl_seq_SET(elts, j, slc->v.Index.value);
+            }
+            e = Tuple(elts, Load, LINENO(n), n->n_col_offset, c->c_arena);
+            if (!e)
+                return NULL;
+            return Subscript(left_expr, Index(e, c->c_arena),
+                             Load, LINENO(n), n->n_col_offset, c->c_arena);
+        }
+    }
+}
+
+static expr_ty
+ast_for_factor(struct compiling *c, const node *n)
+{
+    expr_ty expression;
+
+    expression = ast_for_expr(c, CHILD(n, 1));
+    if (!expression)
+        return NULL;
+
+    switch (TYPE(CHILD(n, 0))) {
+        case PLUS:
+            return UnaryOp(UAdd, expression, LINENO(n), n->n_col_offset,
+                           c->c_arena);
+        case MINUS:
+            return UnaryOp(USub, expression, LINENO(n), n->n_col_offset,
+                           c->c_arena);
+        case TILDE:
+            return UnaryOp(Invert, expression, LINENO(n),
+                           n->n_col_offset, c->c_arena);
+    }
+    PyErr_Format(PyExc_SystemError, "unhandled factor: %d",
+                 TYPE(CHILD(n, 0)));
+    return NULL;
+}
+
+static expr_ty
+ast_for_atom_expr(struct compiling *c, const node *n)
+{
+    int i, nch, start = 0;
+    expr_ty e, tmp;
+
+    REQ(n, atom_expr);
+    nch = NCH(n);
+
+    if (TYPE(CHILD(n, 0)) == AWAIT) {
+        start = 1;
+        assert(nch > 1);
+    }
+
+    e = ast_for_atom(c, CHILD(n, start));
+    if (!e)
+        return NULL;
+    if (nch == 1)
+        return e;
+    if (start && nch == 2) {
+        return Await(e, LINENO(n), n->n_col_offset, c->c_arena);
+    }
+
+    for (i = start + 1; i < nch; i++) {
+        node *ch = CHILD(n, i);
+        if (TYPE(ch) != trailer)
+            break;
+        tmp = ast_for_trailer(c, ch, e);
+        if (!tmp)
+            return NULL;
+        tmp->lineno = e->lineno;
+        tmp->col_offset = e->col_offset;
+        e = tmp;
+    }
+
+    if (start) {
+        /* there was an AWAIT */
+        return Await(e, LINENO(n), n->n_col_offset, c->c_arena);
+    }
+    else {
+        return e;
+    }
+}
+
+static expr_ty
+ast_for_power(struct compiling *c, const node *n)
+{
+    /* power: atom trailer* ('**' factor)*
+     */
+    expr_ty e;
+    REQ(n, power);
+    e = ast_for_atom_expr(c, CHILD(n, 0));
+    if (!e)
+        return NULL;
+    if (NCH(n) == 1)
+        return e;
+    if (TYPE(CHILD(n, NCH(n) - 1)) == factor) {
+        expr_ty f = ast_for_expr(c, CHILD(n, NCH(n) - 1));
+        if (!f)
+            return NULL;
+        e = BinOp(e, Pow, f, LINENO(n), n->n_col_offset, c->c_arena);
+    }
+    return e;
+}
+
+static expr_ty
+ast_for_starred(struct compiling *c, const node *n)
+{
+    expr_ty tmp;
+    REQ(n, star_expr);
+
+    tmp = ast_for_expr(c, CHILD(n, 1));
+    if (!tmp)
+        return NULL;
+
+    /* The Load context is changed later. */
+    return Starred(tmp, Load, LINENO(n), n->n_col_offset, c->c_arena);
+}
+
+
+/* Do not name a variable 'expr'!  Will cause a compile error.
+*/
+
+static expr_ty
+ast_for_expr(struct compiling *c, const node *n)
+{
+    /* handle the full range of simple expressions
+       test: or_test ['if' or_test 'else' test] | lambdef
+       test_nocond: or_test | lambdef_nocond
+       or_test: and_test ('or' and_test)*
+       and_test: not_test ('and' not_test)*
+       not_test: 'not' not_test | comparison
+       comparison: expr (comp_op expr)*
+       expr: xor_expr ('|' xor_expr)*
+       xor_expr: and_expr ('^' and_expr)*
+       and_expr: shift_expr ('&' shift_expr)*
+       shift_expr: arith_expr (('<<'|'>>') arith_expr)*
+       arith_expr: term (('+'|'-') term)*
+       term: factor (('*'|'@'|'/'|'%'|'//') factor)*
+       factor: ('+'|'-'|'~') factor | power
+       power: atom_expr ['**' factor]
+       atom_expr: [AWAIT] atom trailer*
+       yield_expr: 'yield' [yield_arg]
+    */
+
+    asdl_seq *seq;
+    int i;
+
+ loop:
+    switch (TYPE(n)) {
+        case test:
+        case test_nocond:
+            if (TYPE(CHILD(n, 0)) == lambdef ||
+                TYPE(CHILD(n, 0)) == lambdef_nocond)
+                return ast_for_lambdef(c, CHILD(n, 0));
+            else if (NCH(n) > 1)
+                return ast_for_ifexpr(c, n);
+            /* Fallthrough */
+        case or_test:
+        case and_test:
+            if (NCH(n) == 1) {
+                n = CHILD(n, 0);
+                goto loop;
+            }
+            seq = _Py_asdl_seq_new((NCH(n) + 1) / 2, c->c_arena);
+            if (!seq)
+                return NULL;
+            for (i = 0; i < NCH(n); i += 2) {
+                expr_ty e = ast_for_expr(c, CHILD(n, i));
+                if (!e)
+                    return NULL;
+                asdl_seq_SET(seq, i / 2, e);
+            }
+            if (!strcmp(STR(CHILD(n, 1)), "and"))
+                return BoolOp(And, seq, LINENO(n), n->n_col_offset,
+                              c->c_arena);
+            assert(!strcmp(STR(CHILD(n, 1)), "or"));
+            return BoolOp(Or, seq, LINENO(n), n->n_col_offset, c->c_arena);
+        case not_test:
+            if (NCH(n) == 1) {
+                n = CHILD(n, 0);
+                goto loop;
+            }
+            else {
+                expr_ty expression = ast_for_expr(c, CHILD(n, 1));
+                if (!expression)
+                    return NULL;
+
+                return UnaryOp(Not, expression, LINENO(n), n->n_col_offset,
+                               c->c_arena);
+            }
+        case comparison:
+            if (NCH(n) == 1) {
+                n = CHILD(n, 0);
+                goto loop;
+            }
+            else {
+                expr_ty expression;
+                asdl_int_seq *ops;
+                asdl_seq *cmps;
+                ops = _Py_asdl_int_seq_new(NCH(n) / 2, c->c_arena);
+                if (!ops)
+                    return NULL;
+                cmps = _Py_asdl_seq_new(NCH(n) / 2, c->c_arena);
+                if (!cmps) {
+                    return NULL;
+                }
+                for (i = 1; i < NCH(n); i += 2) {
+                    cmpop_ty newoperator;
+
+                    newoperator = ast_for_comp_op(c, CHILD(n, i));
+                    if (!newoperator) {
+                        return NULL;
+                    }
+
+                    expression = ast_for_expr(c, CHILD(n, i + 1));
+                    if (!expression) {
+                        return NULL;
+                    }
+
+                    asdl_seq_SET(ops, i / 2, newoperator);
+                    asdl_seq_SET(cmps, i / 2, expression);
+                }
+                expression = ast_for_expr(c, CHILD(n, 0));
+                if (!expression) {
+                    return NULL;
+                }
+
+                return Compare(expression, ops, cmps, LINENO(n),
+                               n->n_col_offset, c->c_arena);
+            }
+            break;
+
+        case star_expr:
+            return ast_for_starred(c, n);
+        /* The next five cases all handle BinOps.  The main body of code
+           is the same in each case, but the switch turned inside out to
+           reuse the code for each type of operator.
+         */
+        case expr:
+        case xor_expr:
+        case and_expr:
+        case shift_expr:
+        case arith_expr:
+        case term:
+            if (NCH(n) == 1) {
+                n = CHILD(n, 0);
+                goto loop;
+            }
+            return ast_for_binop(c, n);
+        case yield_expr: {
+            node *an = NULL;
+            node *en = NULL;
+            int is_from = 0;
+            expr_ty exp = NULL;
+            if (NCH(n) > 1)
+                an = CHILD(n, 1); /* yield_arg */
+            if (an) {
+                en = CHILD(an, NCH(an) - 1);
+                if (NCH(an) == 2) {
+                    is_from = 1;
+                    exp = ast_for_expr(c, en);
+                }
+                else
+                    exp = ast_for_testlist(c, en);
+                if (!exp)
+                    return NULL;
+            }
+            if (is_from)
+                return YieldFrom(exp, LINENO(n), n->n_col_offset, c->c_arena);
+            return Yield(exp, LINENO(n), n->n_col_offset, c->c_arena);
+        }
+        case factor:
+            if (NCH(n) == 1) {
+                n = CHILD(n, 0);
+                goto loop;
+            }
+            return ast_for_factor(c, n);
+        case power:
+            return ast_for_power(c, n);
+        default:
+            PyErr_Format(PyExc_SystemError, "unhandled expr: %d", TYPE(n));
+            return NULL;
+    }
+    /* should never get here unless if error is set */
+    return NULL;
+}
+
+static expr_ty
+ast_for_call(struct compiling *c, const node *n, expr_ty func)
+{
+    /*
+      arglist: argument (',' argument)*  [',']
+      argument: ( test [comp_for] | '*' test | test '=' test | '**' test )
+    */
+
+    int i, nargs, nkeywords, ngens;
+    int ndoublestars;
+    asdl_seq *args;
+    asdl_seq *keywords;
+
+    REQ(n, arglist);
+
+    nargs = 0;
+    nkeywords = 0;
+    ngens = 0;
+    for (i = 0; i < NCH(n); i++) {
+        node *ch = CHILD(n, i);
+        if (TYPE(ch) == argument) {
+            if (NCH(ch) == 1)
+                nargs++;
+            else if (TYPE(CHILD(ch, 1)) == comp_for)
+                ngens++;
+            else if (TYPE(CHILD(ch, 0)) == STAR)
+                nargs++;
+            else
+                /* TYPE(CHILD(ch, 0)) == DOUBLESTAR or keyword argument */
+                nkeywords++;
+        }
+    }
+    if (ngens > 1 || (ngens && (nargs || nkeywords))) {
+        ast_error(c, n, "Generator expression must be parenthesized "
+                  "if not sole argument");
+        return NULL;
+    }
+
+    if (nargs + nkeywords + ngens > 255) {
+        ast_error(c, n, "more than 255 arguments");
+        return NULL;
+    }
+
+    args = _Py_asdl_seq_new(nargs + ngens, c->c_arena);
+    if (!args)
+        return NULL;
+    keywords = _Py_asdl_seq_new(nkeywords, c->c_arena);
+    if (!keywords)
+        return NULL;
+
+    nargs = 0;  /* positional arguments + iterable argument unpackings */
+    nkeywords = 0;  /* keyword arguments + keyword argument unpackings */
+    ndoublestars = 0;  /* just keyword argument unpackings */
+    for (i = 0; i < NCH(n); i++) {
+        node *ch = CHILD(n, i);
+        if (TYPE(ch) == argument) {
+            expr_ty e;
+            node *chch = CHILD(ch, 0);
+            if (NCH(ch) == 1) {
+                /* a positional argument */
+                if (nkeywords) {
+                    if (ndoublestars) {
+                        ast_error(c, chch,
+                                "positional argument follows "
+                                "keyword argument unpacking");
+                    }
+                    else {
+                        ast_error(c, chch,
+                                "positional argument follows "
+                                "keyword argument");
+                    }
+                    return NULL;
+                }
+                e = ast_for_expr(c, chch);
+                if (!e)
+                    return NULL;
+                asdl_seq_SET(args, nargs++, e);
+            }
+            else if (TYPE(chch) == STAR) {
+                /* an iterable argument unpacking */
+                expr_ty starred;
+                if (ndoublestars) {
+                    ast_error(c, chch,
+                            "iterable argument unpacking follows "
+                            "keyword argument unpacking");
+                    return NULL;
+                }
+                e = ast_for_expr(c, CHILD(ch, 1));
+                if (!e)
+                    return NULL;
+                starred = Starred(e, Load, LINENO(chch),
+                        chch->n_col_offset,
+                        c->c_arena);
+                if (!starred)
+                    return NULL;
+                asdl_seq_SET(args, nargs++, starred);
+
+            }
+            else if (TYPE(chch) == DOUBLESTAR) {
+                /* a keyword argument unpacking */
+                keyword_ty kw;
+                i++;
+                e = ast_for_expr(c, CHILD(ch, 1));
+                if (!e)
+                    return NULL;
+                kw = keyword(NULL, e, c->c_arena);
+                asdl_seq_SET(keywords, nkeywords++, kw);
+                ndoublestars++;
+            }
+            else if (TYPE(CHILD(ch, 1)) == comp_for) {
+                /* the lone generator expression */
+                e = ast_for_genexp(c, ch);
+                if (!e)
+                    return NULL;
+                asdl_seq_SET(args, nargs++, e);
+            }
+            else {
+                /* a keyword argument */
+                keyword_ty kw;
+                identifier key, tmp;
+                int k;
+
+                /* chch is test, but must be an identifier? */
+                e = ast_for_expr(c, chch);
+                if (!e)
+                    return NULL;
+                /* f(lambda x: x[0] = 3) ends up getting parsed with
+                 * LHS test = lambda x: x[0], and RHS test = 3.
+                 * SF bug 132313 points out that complaining about a keyword
+                 * then is very confusing.
+                 */
+                if (e->kind == Lambda_kind) {
+                    ast_error(c, chch,
+                            "lambda cannot contain assignment");
+                    return NULL;
+                }
+                else if (e->kind != Name_kind) {
+                    ast_error(c, chch,
+                            "keyword can't be an expression");
+                    return NULL;
+                }
+                else if (forbidden_name(c, e->v.Name.id, ch, 1)) {
+                    return NULL;
+                }
+                key = e->v.Name.id;
+                for (k = 0; k < nkeywords; k++) {
+                    tmp = ((keyword_ty)asdl_seq_GET(keywords, k))->arg;
+                    if (tmp && !PyUnicode_Compare(tmp, key)) {
+                        ast_error(c, chch,
+                                "keyword argument repeated");
+                        return NULL;
+                    }
+                }
+                e = ast_for_expr(c, CHILD(ch, 2));
+                if (!e)
+                    return NULL;
+                kw = keyword(key, e, c->c_arena);
+                if (!kw)
+                    return NULL;
+                asdl_seq_SET(keywords, nkeywords++, kw);
+            }
+        }
+    }
+
+    return Call(func, args, keywords, func->lineno, func->col_offset, c->c_arena);
+}
+
+static expr_ty
+ast_for_testlist(struct compiling *c, const node* n)
+{
+    /* testlist_comp: test (comp_for | (',' test)* [',']) */
+    /* testlist: test (',' test)* [','] */
+    assert(NCH(n) > 0);
+    if (TYPE(n) == testlist_comp) {
+        if (NCH(n) > 1)
+            assert(TYPE(CHILD(n, 1)) != comp_for);
+    }
+    else {
+        assert(TYPE(n) == testlist ||
+               TYPE(n) == testlist_star_expr);
+    }
+    if (NCH(n) == 1)
+        return ast_for_expr(c, CHILD(n, 0));
+    else {
+        asdl_seq *tmp = seq_for_testlist(c, n);
+        if (!tmp)
+            return NULL;
+        return Tuple(tmp, Load, LINENO(n), n->n_col_offset, c->c_arena);
+    }
+}
+
+static stmt_ty
+ast_for_expr_stmt(struct compiling *c, const node *n)
+{
+    REQ(n, expr_stmt);
+    /* expr_stmt: testlist_star_expr (augassign (yield_expr|testlist)
+                | ('=' (yield_expr|testlist_star_expr))* [TYPE_COMMENT])
+       testlist_star_expr: (test|star_expr) (',' test|star_expr)* [',']
+       augassign: '+=' | '-=' | '*=' | '@=' | '/=' | '%=' | '&=' | '|=' | '^='
+                | '<<=' | '>>=' | '**=' | '//='
+       test: ... here starts the operator precendence dance
+     */
+    int num = NCH(n);
+
+    if (num == 1 || (num == 2 && TYPE(CHILD(n, 1)) == TYPE_COMMENT)) {
+        expr_ty e = ast_for_testlist(c, CHILD(n, 0));
+        if (!e)
+            return NULL;
+
+        return Expr(e, LINENO(n), n->n_col_offset, c->c_arena);
+    }
+    else if (TYPE(CHILD(n, 1)) == augassign) {
+        expr_ty expr1, expr2;
+        operator_ty newoperator;
+        node *ch = CHILD(n, 0);
+
+        expr1 = ast_for_testlist(c, ch);
+        if (!expr1)
+            return NULL;
+        if(!set_context(c, expr1, Store, ch))
+            return NULL;
+        /* set_context checks that most expressions are not the left side.
+          Augmented assignments can only have a name, a subscript, or an
+          attribute on the left, though, so we have to explicitly check for
+          those. */
+        switch (expr1->kind) {
+            case Name_kind:
+            case Attribute_kind:
+            case Subscript_kind:
+                break;
+            default:
+                ast_error(c, ch, "illegal expression for augmented assignment");
+                return NULL;
+        }
+
+        ch = CHILD(n, 2);
+        if (TYPE(ch) == testlist)
+            expr2 = ast_for_testlist(c, ch);
+        else
+            expr2 = ast_for_expr(c, ch);
+        if (!expr2)
+            return NULL;
+
+        newoperator = ast_for_augassign(c, CHILD(n, 1));
+        if (!newoperator)
+            return NULL;
+
+        return AugAssign(expr1, newoperator, expr2, LINENO(n), n->n_col_offset, c->c_arena);
+    }
+    else {
+        int i, nch_minus_type, has_type_comment;
+        asdl_seq *targets;
+        node *value;
+        expr_ty expression;
+        string type_comment;
+
+        /* a normal assignment */
+        REQ(CHILD(n, 1), EQUAL);
+
+        has_type_comment = TYPE(CHILD(n, num - 1)) == TYPE_COMMENT;
+        nch_minus_type = num - has_type_comment;
+
+        targets = _Py_asdl_seq_new(nch_minus_type / 2, c->c_arena);
+        if (!targets)
+            return NULL;
+        for (i = 0; i < nch_minus_type - 2; i += 2) {
+            expr_ty e;
+            node *ch = CHILD(n, i);
+            if (TYPE(ch) == yield_expr) {
+                ast_error(c, ch, "assignment to yield expression not possible");
+                return NULL;
+            }
+            e = ast_for_testlist(c, ch);
+            if (!e)
+              return NULL;
+
+            /* set context to assign */
+            if (!set_context(c, e, Store, CHILD(n, i)))
+              return NULL;
+
+            asdl_seq_SET(targets, i / 2, e);
+        }
+        value = CHILD(n, nch_minus_type - 1);
+        if (TYPE(value) == testlist_star_expr)
+            expression = ast_for_testlist(c, value);
+        else
+            expression = ast_for_expr(c, value);
+        if (!expression)
+            return NULL;
+        if (has_type_comment)
+            type_comment = NEW_TYPE_COMMENT(CHILD(n, nch_minus_type));
+        else
+            type_comment = NULL;
+        return Assign(targets, expression, type_comment, LINENO(n), n->n_col_offset, c->c_arena);
+    }
+}
+
+
+static asdl_seq *
+ast_for_exprlist(struct compiling *c, const node *n, expr_context_ty context)
+{
+    asdl_seq *seq;
+    int i;
+    expr_ty e;
+
+    REQ(n, exprlist);
+
+    seq = _Py_asdl_seq_new((NCH(n) + 1) / 2, c->c_arena);
+    if (!seq)
+        return NULL;
+    for (i = 0; i < NCH(n); i += 2) {
+        e = ast_for_expr(c, CHILD(n, i));
+        if (!e)
+            return NULL;
+        asdl_seq_SET(seq, i / 2, e);
+        if (context && !set_context(c, e, context, CHILD(n, i)))
+            return NULL;
+    }
+    return seq;
+}
+
+static stmt_ty
+ast_for_del_stmt(struct compiling *c, const node *n)
+{
+    asdl_seq *expr_list;
+
+    /* del_stmt: 'del' exprlist */
+    REQ(n, del_stmt);
+
+    expr_list = ast_for_exprlist(c, CHILD(n, 1), Del);
+    if (!expr_list)
+        return NULL;
+    return Delete(expr_list, LINENO(n), n->n_col_offset, c->c_arena);
+}
+
+static stmt_ty
+ast_for_flow_stmt(struct compiling *c, const node *n)
+{
+    /*
+      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_expr
+      yield_expr: 'yield' testlist | 'yield' 'from' test
+      raise_stmt: 'raise' [test [',' test [',' test]]]
+    */
+    node *ch;
+
+    REQ(n, flow_stmt);
+    ch = CHILD(n, 0);
+    switch (TYPE(ch)) {
+        case break_stmt:
+            return Break(LINENO(n), n->n_col_offset, c->c_arena);
+        case continue_stmt:
+            return Continue(LINENO(n), n->n_col_offset, c->c_arena);
+        case yield_stmt: { /* will reduce to yield_expr */
+            expr_ty exp = ast_for_expr(c, CHILD(ch, 0));
+            if (!exp)
+                return NULL;
+            return Expr(exp, LINENO(n), n->n_col_offset, c->c_arena);
+        }
+        case return_stmt:
+            if (NCH(ch) == 1)
+                return Return(NULL, LINENO(n), n->n_col_offset, c->c_arena);
+            else {
+                expr_ty expression = ast_for_testlist(c, CHILD(ch, 1));
+                if (!expression)
+                    return NULL;
+                return Return(expression, LINENO(n), n->n_col_offset, c->c_arena);
+            }
+        case raise_stmt:
+            if (NCH(ch) == 1)
+                return Raise(NULL, NULL, LINENO(n), n->n_col_offset, c->c_arena);
+            else if (NCH(ch) >= 2) {
+                expr_ty cause = NULL;
+                expr_ty expression = ast_for_expr(c, CHILD(ch, 1));
+                if (!expression)
+                    return NULL;
+                if (NCH(ch) == 4) {
+                    cause = ast_for_expr(c, CHILD(ch, 3));
+                    if (!cause)
+                        return NULL;
+                }
+                return Raise(expression, cause, LINENO(n), n->n_col_offset, c->c_arena);
+            }
+        default:
+            PyErr_Format(PyExc_SystemError,
+                         "unexpected flow_stmt: %d", TYPE(ch));
+            return NULL;
+    }
+}
+
+static alias_ty
+alias_for_import_name(struct compiling *c, const node *n, int store)
+{
+    /*
+      import_as_name: NAME ['as' NAME]
+      dotted_as_name: dotted_name ['as' NAME]
+      dotted_name: NAME ('.' NAME)*
+    */
+    identifier str, name;
+
+ loop:
+    switch (TYPE(n)) {
+        case import_as_name: {
+            node *name_node = CHILD(n, 0);
+            str = NULL;
+            name = NEW_IDENTIFIER(name_node);
+            if (!name)
+                return NULL;
+            if (NCH(n) == 3) {
+                node *str_node = CHILD(n, 2);
+                str = NEW_IDENTIFIER(str_node);
+                if (!str)
+                    return NULL;
+                if (store && forbidden_name(c, str, str_node, 0))
+                    return NULL;
+            }
+            else {
+                if (forbidden_name(c, name, name_node, 0))
+                    return NULL;
+            }
+            return alias(name, str, c->c_arena);
+        }
+        case dotted_as_name:
+            if (NCH(n) == 1) {
+                n = CHILD(n, 0);
+                goto loop;
+            }
+            else {
+                node *asname_node = CHILD(n, 2);
+                alias_ty a = alias_for_import_name(c, CHILD(n, 0), 0);
+                if (!a)
+                    return NULL;
+                assert(!a->asname);
+                a->asname = NEW_IDENTIFIER(asname_node);
+                if (!a->asname)
+                    return NULL;
+                if (forbidden_name(c, a->asname, asname_node, 0))
+                    return NULL;
+                return a;
+            }
+            break;
+        case dotted_name:
+            if (NCH(n) == 1) {
+                node *name_node = CHILD(n, 0);
+                name = NEW_IDENTIFIER(name_node);
+                if (!name)
+                    return NULL;
+                if (store && forbidden_name(c, name, name_node, 0))
+                    return NULL;
+                return alias(name, NULL, c->c_arena);
+            }
+            else {
+                /* Create a string of the form "a.b.c" */
+                int i;
+                size_t len;
+                char *s;
+                PyObject *uni;
+
+                len = 0;
+                for (i = 0; i < NCH(n); i += 2)
+                    /* length of string plus one for the dot */
+                    len += strlen(STR(CHILD(n, i))) + 1;
+                len--; /* the last name doesn't have a dot */
+                str = PyBytes_FromStringAndSize(NULL, len);
+                if (!str)
+                    return NULL;
+                s = PyBytes_AS_STRING(str);
+                if (!s)
+                    return NULL;
+                for (i = 0; i < NCH(n); i += 2) {
+                    char *sch = STR(CHILD(n, i));
+                    strcpy(s, STR(CHILD(n, i)));
+                    s += strlen(sch);
+                    *s++ = '.';
+                }
+                --s;
+                *s = '\0';
+                uni = PyUnicode_DecodeUTF8(PyBytes_AS_STRING(str),
+                                           PyBytes_GET_SIZE(str),
+                                           NULL);
+                Py_DECREF(str);
+                if (!uni)
+                    return NULL;
+                str = uni;
+                PyUnicode_InternInPlace(&str);
+                if (PyArena_AddPyObject(c->c_arena, str) < 0) {
+                    Py_DECREF(str);
+                    return NULL;
+                }
+                return alias(str, NULL, c->c_arena);
+            }
+            break;
+        case STAR:
+            str = PyUnicode_InternFromString("*");
+            if (PyArena_AddPyObject(c->c_arena, str) < 0) {
+                Py_DECREF(str);
+                return NULL;
+            }
+            return alias(str, NULL, c->c_arena);
+        default:
+            PyErr_Format(PyExc_SystemError,
+                         "unexpected import name: %d", TYPE(n));
+            return NULL;
+    }
+
+    PyErr_SetString(PyExc_SystemError, "unhandled import name condition");
+    return NULL;
+}
+
+static stmt_ty
+ast_for_import_stmt(struct compiling *c, const node *n)
+{
+    /*
+      import_stmt: import_name | import_from
+      import_name: 'import' dotted_as_names
+      import_from: 'from' (('.' | '...')* dotted_name | ('.' | '...')+)
+                   'import' ('*' | '(' import_as_names ')' | import_as_names)
+    */
+    int lineno;
+    int col_offset;
+    int i;
+    asdl_seq *aliases;
+
+    REQ(n, import_stmt);
+    lineno = LINENO(n);
+    col_offset = n->n_col_offset;
+    n = CHILD(n, 0);
+    if (TYPE(n) == import_name) {
+        n = CHILD(n, 1);
+        REQ(n, dotted_as_names);
+        aliases = _Py_asdl_seq_new((NCH(n) + 1) / 2, c->c_arena);
+        if (!aliases)
+                return NULL;
+        for (i = 0; i < NCH(n); i += 2) {
+            alias_ty import_alias = alias_for_import_name(c, CHILD(n, i), 1);
+            if (!import_alias)
+                return NULL;
+            asdl_seq_SET(aliases, i / 2, import_alias);
+        }
+        return Import(aliases, lineno, col_offset, c->c_arena);
+    }
+    else if (TYPE(n) == import_from) {
+        int n_children;
+        int idx, ndots = 0;
+        alias_ty mod = NULL;
+        identifier modname = NULL;
+
+       /* Count the number of dots (for relative imports) and check for the
+          optional module name */
+        for (idx = 1; idx < NCH(n); idx++) {
+            if (TYPE(CHILD(n, idx)) == dotted_name) {
+                mod = alias_for_import_name(c, CHILD(n, idx), 0);
+                if (!mod)
+                    return NULL;
+                idx++;
+                break;
+            } else if (TYPE(CHILD(n, idx)) == ELLIPSIS) {
+                /* three consecutive dots are tokenized as one ELLIPSIS */
+                ndots += 3;
+                continue;
+            } else if (TYPE(CHILD(n, idx)) != DOT) {
+                break;
+            }
+            ndots++;
+        }
+        idx++; /* skip over the 'import' keyword */
+        switch (TYPE(CHILD(n, idx))) {
+        case STAR:
+            /* from ... import * */
+            n = CHILD(n, idx);
+            n_children = 1;
+            break;
+        case LPAR:
+            /* from ... import (x, y, z) */
+            n = CHILD(n, idx + 1);
+            n_children = NCH(n);
+            break;
+        case import_as_names:
+            /* from ... import x, y, z */
+            n = CHILD(n, idx);
+            n_children = NCH(n);
+            if (n_children % 2 == 0) {
+                ast_error(c, n, "trailing comma not allowed without"
+                             " surrounding parentheses");
+                return NULL;
+            }
+            break;
+        default:
+            ast_error(c, n, "Unexpected node-type in from-import");
+            return NULL;
+        }
+
+        aliases = _Py_asdl_seq_new((n_children + 1) / 2, c->c_arena);
+        if (!aliases)
+            return NULL;
+
+        /* handle "from ... import *" special b/c there's no children */
+        if (TYPE(n) == STAR) {
+            alias_ty import_alias = alias_for_import_name(c, n, 1);
+            if (!import_alias)
+                return NULL;
+                asdl_seq_SET(aliases, 0, import_alias);
+        }
+        else {
+            for (i = 0; i < NCH(n); i += 2) {
+                alias_ty import_alias = alias_for_import_name(c, CHILD(n, i), 1);
+                if (!import_alias)
+                    return NULL;
+                    asdl_seq_SET(aliases, i / 2, import_alias);
+            }
+        }
+        if (mod != NULL)
+            modname = mod->name;
+        return ImportFrom(modname, aliases, ndots, lineno, col_offset,
+                          c->c_arena);
+    }
+    PyErr_Format(PyExc_SystemError,
+                 "unknown import statement: starts with command '%s'",
+                 STR(CHILD(n, 0)));
+    return NULL;
+}
+
+static stmt_ty
+ast_for_global_stmt(struct compiling *c, const node *n)
+{
+    /* global_stmt: 'global' NAME (',' NAME)* */
+    identifier name;
+    asdl_seq *s;
+    int i;
+
+    REQ(n, global_stmt);
+    s = _Py_asdl_seq_new(NCH(n) / 2, c->c_arena);
+    if (!s)
+        return NULL;
+    for (i = 1; i < NCH(n); i += 2) {
+        name = NEW_IDENTIFIER(CHILD(n, i));
+        if (!name)
+            return NULL;
+        asdl_seq_SET(s, i / 2, name);
+    }
+    return Global(s, LINENO(n), n->n_col_offset, c->c_arena);
+}
+
+static stmt_ty
+ast_for_nonlocal_stmt(struct compiling *c, const node *n)
+{
+    /* nonlocal_stmt: 'nonlocal' NAME (',' NAME)* */
+    identifier name;
+    asdl_seq *s;
+    int i;
+
+    REQ(n, nonlocal_stmt);
+    s = _Py_asdl_seq_new(NCH(n) / 2, c->c_arena);
+    if (!s)
+        return NULL;
+    for (i = 1; i < NCH(n); i += 2) {
+        name = NEW_IDENTIFIER(CHILD(n, i));
+        if (!name)
+            return NULL;
+        asdl_seq_SET(s, i / 2, name);
+    }
+    return Nonlocal(s, LINENO(n), n->n_col_offset, c->c_arena);
+}
+
+static stmt_ty
+ast_for_assert_stmt(struct compiling *c, const node *n)
+{
+    /* assert_stmt: 'assert' test [',' test] */
+    REQ(n, assert_stmt);
+    if (NCH(n) == 2) {
+        expr_ty expression = ast_for_expr(c, CHILD(n, 1));
+        if (!expression)
+            return NULL;
+        return Assert(expression, NULL, LINENO(n), n->n_col_offset, c->c_arena);
+    }
+    else if (NCH(n) == 4) {
+        expr_ty expr1, expr2;
+
+        expr1 = ast_for_expr(c, CHILD(n, 1));
+        if (!expr1)
+            return NULL;
+        expr2 = ast_for_expr(c, CHILD(n, 3));
+        if (!expr2)
+            return NULL;
+
+        return Assert(expr1, expr2, LINENO(n), n->n_col_offset, c->c_arena);
+    }
+    PyErr_Format(PyExc_SystemError,
+                 "improper number of parts to 'assert' statement: %d",
+                 NCH(n));
+    return NULL;
+}
+
+static asdl_seq *
+ast_for_suite(struct compiling *c, const node *n)
+{
+    /* suite: simple_stmt | NEWLINE [TYPE_COMMENT NEWLINE] INDENT stmt+ DEDENT */
+    asdl_seq *seq;
+    stmt_ty s;
+    int i, total, num, end, pos = 0;
+    node *ch;
+
+    REQ(n, suite);
+
+    total = num_stmts(n);
+    seq = _Py_asdl_seq_new(total, c->c_arena);
+    if (!seq)
+        return NULL;
+    if (TYPE(CHILD(n, 0)) == simple_stmt) {
+        n = CHILD(n, 0);
+        /* simple_stmt always ends with a NEWLINE,
+           and may have a trailing SEMI
+        */
+        end = NCH(n) - 1;
+        if (TYPE(CHILD(n, end - 1)) == SEMI)
+            end--;
+        /* loop by 2 to skip semi-colons */
+        for (i = 0; i < end; i += 2) {
+            ch = CHILD(n, i);
+            s = ast_for_stmt(c, ch);
+            if (!s)
+                return NULL;
+            asdl_seq_SET(seq, pos++, s);
+        }
+    }
+    else {
+        i = 2;
+        if (TYPE(CHILD(n, 1)) == TYPE_COMMENT)
+            i += 2;
+
+        for (; i < (NCH(n) - 1); i++) {
+            ch = CHILD(n, i);
+            REQ(ch, stmt);
+            num = num_stmts(ch);
+            if (num == 1) {
+                /* small_stmt or compound_stmt with only one child */
+                s = ast_for_stmt(c, ch);
+                if (!s)
+                    return NULL;
+                asdl_seq_SET(seq, pos++, s);
+            }
+            else {
+                int j;
+                ch = CHILD(ch, 0);
+                REQ(ch, simple_stmt);
+                for (j = 0; j < NCH(ch); j += 2) {
+                    /* statement terminates with a semi-colon ';' */
+                    if (NCH(CHILD(ch, j)) == 0) {
+                        assert((j + 1) == NCH(ch));
+                        break;
+                    }
+                    s = ast_for_stmt(c, CHILD(ch, j));
+                    if (!s)
+                        return NULL;
+                    asdl_seq_SET(seq, pos++, s);
+                }
+            }
+        }
+    }
+    assert(pos == seq->size);
+    return seq;
+}
+
+static stmt_ty
+ast_for_if_stmt(struct compiling *c, const node *n)
+{
+    /* if_stmt: 'if' test ':' suite ('elif' test ':' suite)*
+       ['else' ':' suite]
+    */
+    char *s;
+
+    REQ(n, if_stmt);
+
+    if (NCH(n) == 4) {
+        expr_ty expression;
+        asdl_seq *suite_seq;
+
+        expression = ast_for_expr(c, CHILD(n, 1));
+        if (!expression)
+            return NULL;
+        suite_seq = ast_for_suite(c, CHILD(n, 3));
+        if (!suite_seq)
+            return NULL;
+
+        return If(expression, suite_seq, NULL, LINENO(n), n->n_col_offset,
+                  c->c_arena);
+    }
+
+    s = STR(CHILD(n, 4));
+    /* s[2], the third character in the string, will be
+       's' for el_s_e, or
+       'i' for el_i_f
+    */
+    if (s[2] == 's') {
+        expr_ty expression;
+        asdl_seq *seq1, *seq2;
+
+        expression = ast_for_expr(c, CHILD(n, 1));
+        if (!expression)
+            return NULL;
+        seq1 = ast_for_suite(c, CHILD(n, 3));
+        if (!seq1)
+            return NULL;
+        seq2 = ast_for_suite(c, CHILD(n, 6));
+        if (!seq2)
+            return NULL;
+
+        return If(expression, seq1, seq2, LINENO(n), n->n_col_offset,
+                  c->c_arena);
+    }
+    else if (s[2] == 'i') {
+        int i, n_elif, has_else = 0;
+        expr_ty expression;
+        asdl_seq *suite_seq;
+        asdl_seq *orelse = NULL;
+        n_elif = NCH(n) - 4;
+        /* must reference the child n_elif+1 since 'else' token is third,
+           not fourth, child from the end. */
+        if (TYPE(CHILD(n, (n_elif + 1))) == NAME
+            && STR(CHILD(n, (n_elif + 1)))[2] == 's') {
+            has_else = 1;
+            n_elif -= 3;
+        }
+        n_elif /= 4;
+
+        if (has_else) {
+            asdl_seq *suite_seq2;
+
+            orelse = _Py_asdl_seq_new(1, c->c_arena);
+            if (!orelse)
+                return NULL;
+            expression = ast_for_expr(c, CHILD(n, NCH(n) - 6));
+            if (!expression)
+                return NULL;
+            suite_seq = ast_for_suite(c, CHILD(n, NCH(n) - 4));
+            if (!suite_seq)
+                return NULL;
+            suite_seq2 = ast_for_suite(c, CHILD(n, NCH(n) - 1));
+            if (!suite_seq2)
+                return NULL;
+
+            asdl_seq_SET(orelse, 0,
+                         If(expression, suite_seq, suite_seq2,
+                            LINENO(CHILD(n, NCH(n) - 6)),
+                            CHILD(n, NCH(n) - 6)->n_col_offset,
+                            c->c_arena));
+            /* the just-created orelse handled the last elif */
+            n_elif--;
+        }
+
+        for (i = 0; i < n_elif; i++) {
+            int off = 5 + (n_elif - i - 1) * 4;
+            asdl_seq *newobj = _Py_asdl_seq_new(1, c->c_arena);
+            if (!newobj)
+                return NULL;
+            expression = ast_for_expr(c, CHILD(n, off));
+            if (!expression)
+                return NULL;
+            suite_seq = ast_for_suite(c, CHILD(n, off + 2));
+            if (!suite_seq)
+                return NULL;
+
+            asdl_seq_SET(newobj, 0,
+                         If(expression, suite_seq, orelse,
+                            LINENO(CHILD(n, off)),
+                            CHILD(n, off)->n_col_offset, c->c_arena));
+            orelse = newobj;
+        }
+        expression = ast_for_expr(c, CHILD(n, 1));
+        if (!expression)
+            return NULL;
+        suite_seq = ast_for_suite(c, CHILD(n, 3));
+        if (!suite_seq)
+            return NULL;
+        return If(expression, suite_seq, orelse,
+                  LINENO(n), n->n_col_offset, c->c_arena);
+    }
+
+    PyErr_Format(PyExc_SystemError,
+                 "unexpected token in 'if' statement: %s", s);
+    return NULL;
+}
+
+static stmt_ty
+ast_for_while_stmt(struct compiling *c, const node *n)
+{
+    /* while_stmt: 'while' test ':' suite ['else' ':' suite] */
+    REQ(n, while_stmt);
+
+    if (NCH(n) == 4) {
+        expr_ty expression;
+        asdl_seq *suite_seq;
+
+        expression = ast_for_expr(c, CHILD(n, 1));
+        if (!expression)
+            return NULL;
+        suite_seq = ast_for_suite(c, CHILD(n, 3));
+        if (!suite_seq)
+            return NULL;
+        return While(expression, suite_seq, NULL, LINENO(n), n->n_col_offset, c->c_arena);
+    }
+    else if (NCH(n) == 7) {
+        expr_ty expression;
+        asdl_seq *seq1, *seq2;
+
+        expression = ast_for_expr(c, CHILD(n, 1));
+        if (!expression)
+            return NULL;
+        seq1 = ast_for_suite(c, CHILD(n, 3));
+        if (!seq1)
+            return NULL;
+        seq2 = ast_for_suite(c, CHILD(n, 6));
+        if (!seq2)
+            return NULL;
+
+        return While(expression, seq1, seq2, LINENO(n), n->n_col_offset, c->c_arena);
+    }
+
+    PyErr_Format(PyExc_SystemError,
+                 "wrong number of tokens for 'while' statement: %d",
+                 NCH(n));
+    return NULL;
+}
+
+static stmt_ty
+ast_for_for_stmt(struct compiling *c, const node *n, int is_async)
+{
+    asdl_seq *_target, *seq = NULL, *suite_seq;
+    expr_ty expression;
+    expr_ty target, first;
+    const node *node_target;
+    int has_type_comment;
+    string type_comment;
+    /* for_stmt: 'for' exprlist 'in' testlist ':' [TYPE_COMMENT] suite ['else' ':' suite] */
+    REQ(n, for_stmt);
+
+    has_type_comment = TYPE(CHILD(n, 5)) == TYPE_COMMENT;
+
+    if (NCH(n) == 9 + has_type_comment) {
+        seq = ast_for_suite(c, CHILD(n, 8 + has_type_comment));
+        if (!seq)
+            return NULL;
+    }
+
+    node_target = CHILD(n, 1);
+    _target = ast_for_exprlist(c, node_target, Store);
+    if (!_target)
+        return NULL;
+    /* Check the # of children rather than the length of _target, since
+       for x, in ... has 1 element in _target, but still requires a Tuple. */
+    first = (expr_ty)asdl_seq_GET(_target, 0);
+    if (NCH(node_target) == 1)
+        target = first;
+    else
+        target = Tuple(_target, Store, first->lineno, first->col_offset, c->c_arena);
+
+    expression = ast_for_testlist(c, CHILD(n, 3));
+    if (!expression)
+        return NULL;
+    suite_seq = ast_for_suite(c, CHILD(n, 5 + has_type_comment));
+    if (!suite_seq)
+        return NULL;
+
+    if (has_type_comment)
+        type_comment = NEW_TYPE_COMMENT(CHILD(n, 5));
+    else
+        type_comment = NULL;
+
+    if (is_async)
+        return AsyncFor(target, expression, suite_seq, seq,
+                        LINENO(n), n->n_col_offset,
+                        c->c_arena);
+    else
+        return For(target, expression, suite_seq, seq,
+                   type_comment, LINENO(n), n->n_col_offset,
+                   c->c_arena);
+}
+
+static excepthandler_ty
+ast_for_except_clause(struct compiling *c, const node *exc, node *body)
+{
+    /* except_clause: 'except' [test ['as' test]] */
+    REQ(exc, except_clause);
+    REQ(body, suite);
+
+    if (NCH(exc) == 1) {
+        asdl_seq *suite_seq = ast_for_suite(c, body);
+        if (!suite_seq)
+            return NULL;
+
+        return ExceptHandler(NULL, NULL, suite_seq, LINENO(exc),
+                             exc->n_col_offset, c->c_arena);
+    }
+    else if (NCH(exc) == 2) {
+        expr_ty expression;
+        asdl_seq *suite_seq;
+
+        expression = ast_for_expr(c, CHILD(exc, 1));
+        if (!expression)
+            return NULL;
+        suite_seq = ast_for_suite(c, body);
+        if (!suite_seq)
+            return NULL;
+
+        return ExceptHandler(expression, NULL, suite_seq, LINENO(exc),
+                             exc->n_col_offset, c->c_arena);
+    }
+    else if (NCH(exc) == 4) {
+        asdl_seq *suite_seq;
+        expr_ty expression;
+        identifier e = NEW_IDENTIFIER(CHILD(exc, 3));
+        if (!e)
+            return NULL;
+        if (forbidden_name(c, e, CHILD(exc, 3), 0))
+            return NULL;
+        expression = ast_for_expr(c, CHILD(exc, 1));
+        if (!expression)
+            return NULL;
+        suite_seq = ast_for_suite(c, body);
+        if (!suite_seq)
+            return NULL;
+
+        return ExceptHandler(expression, e, suite_seq, LINENO(exc),
+                             exc->n_col_offset, c->c_arena);
+    }
+
+    PyErr_Format(PyExc_SystemError,
+                 "wrong number of children for 'except' clause: %d",
+                 NCH(exc));
+    return NULL;
+}
+
+static stmt_ty
+ast_for_try_stmt(struct compiling *c, const node *n)
+{
+    const int nch = NCH(n);
+    int n_except = (nch - 3)/3;
+    asdl_seq *body, *handlers = NULL, *orelse = NULL, *finally = NULL;
+
+    REQ(n, try_stmt);
+
+    body = ast_for_suite(c, CHILD(n, 2));
+    if (body == NULL)
+        return NULL;
+
+    if (TYPE(CHILD(n, nch - 3)) == NAME) {
+        if (strcmp(STR(CHILD(n, nch - 3)), "finally") == 0) {
+            if (nch >= 9 && TYPE(CHILD(n, nch - 6)) == NAME) {
+                /* we can assume it's an "else",
+                   because nch >= 9 for try-else-finally and
+                   it would otherwise have a type of except_clause */
+                orelse = ast_for_suite(c, CHILD(n, nch - 4));
+                if (orelse == NULL)
+                    return NULL;
+                n_except--;
+            }
+
+            finally = ast_for_suite(c, CHILD(n, nch - 1));
+            if (finally == NULL)
+                return NULL;
+            n_except--;
+        }
+        else {
+            /* we can assume it's an "else",
+               otherwise it would have a type of except_clause */
+            orelse = ast_for_suite(c, CHILD(n, nch - 1));
+            if (orelse == NULL)
+                return NULL;
+            n_except--;
+        }
+    }
+    else if (TYPE(CHILD(n, nch - 3)) != except_clause) {
+        ast_error(c, n, "malformed 'try' statement");
+        return NULL;
+    }
+
+    if (n_except > 0) {
+        int i;
+        /* process except statements to create a try ... except */
+        handlers = _Py_asdl_seq_new(n_except, c->c_arena);
+        if (handlers == NULL)
+            return NULL;
+
+        for (i = 0; i < n_except; i++) {
+            excepthandler_ty e = ast_for_except_clause(c, CHILD(n, 3 + i * 3),
+                                                       CHILD(n, 5 + i * 3));
+            if (!e)
+                return NULL;
+            asdl_seq_SET(handlers, i, e);
+        }
+    }
+
+    assert(finally != NULL || asdl_seq_LEN(handlers));
+    return Try(body, handlers, orelse, finally, LINENO(n), n->n_col_offset, c->c_arena);
+}
+
+/* with_item: test ['as' expr] */
+static withitem_ty
+ast_for_with_item(struct compiling *c, const node *n)
+{
+    expr_ty context_expr, optional_vars = NULL;
+
+    REQ(n, with_item);
+    context_expr = ast_for_expr(c, CHILD(n, 0));
+    if (!context_expr)
+        return NULL;
+    if (NCH(n) == 3) {
+        optional_vars = ast_for_expr(c, CHILD(n, 2));
+
+        if (!optional_vars) {
+            return NULL;
+        }
+        if (!set_context(c, optional_vars, Store, n)) {
+            return NULL;
+        }
+    }
+
+    return withitem(context_expr, optional_vars, c->c_arena);
+}
+
+/* with_stmt: 'with' with_item (',' with_item)*  ':' [TYPE_COMMENT] suite */
+static stmt_ty
+ast_for_with_stmt(struct compiling *c, const node *n, int is_async)
+{
+    int i, n_items, nch_minus_type, has_type_comment;
+    asdl_seq *items, *body;
+    string type_comment;
+
+    REQ(n, with_stmt);
+
+    has_type_comment = TYPE(CHILD(n, NCH(n) - 2)) == TYPE_COMMENT;
+    nch_minus_type = NCH(n) - has_type_comment;
+
+    n_items = (nch_minus_type - 2) / 2;
+    items = _Py_asdl_seq_new(n_items, c->c_arena);
+    if (!items)
+        return NULL;
+    for (i = 1; i < nch_minus_type - 2; i += 2) {
+        withitem_ty item = ast_for_with_item(c, CHILD(n, i));
+        if (!item)
+            return NULL;
+        asdl_seq_SET(items, (i - 1) / 2, item);
+    }
+
+    body = ast_for_suite(c, CHILD(n, NCH(n) - 1));
+    if (!body)
+        return NULL;
+
+    if (has_type_comment)
+        type_comment = NEW_TYPE_COMMENT(CHILD(n, NCH(n) - 2));
+    else
+        type_comment = NULL;
+
+    if (is_async)
+        return AsyncWith(items, body, LINENO(n), n->n_col_offset, c->c_arena);
+    else
+        return With(items, body, type_comment, LINENO(n), n->n_col_offset, c->c_arena);
+}
+
+static stmt_ty
+ast_for_classdef(struct compiling *c, const node *n, asdl_seq *decorator_seq)
+{
+    /* classdef: 'class' NAME ['(' arglist ')'] ':' suite */
+    PyObject *classname;
+    asdl_seq *s;
+    expr_ty call;
+
+    REQ(n, classdef);
+
+    if (NCH(n) == 4) { /* class NAME ':' suite */
+        s = ast_for_suite(c, CHILD(n, 3));
+        if (!s)
+            return NULL;
+        classname = NEW_IDENTIFIER(CHILD(n, 1));
+        if (!classname)
+            return NULL;
+        if (forbidden_name(c, classname, CHILD(n, 3), 0))
+            return NULL;
+        return ClassDef(classname, NULL, NULL, s, decorator_seq, LINENO(n),
+                        n->n_col_offset, c->c_arena);
+    }
+
+    if (TYPE(CHILD(n, 3)) == RPAR) { /* class NAME '(' ')' ':' suite */
+        s = ast_for_suite(c, CHILD(n,5));
+        if (!s)
+            return NULL;
+        classname = NEW_IDENTIFIER(CHILD(n, 1));
+        if (!classname)
+            return NULL;
+        if (forbidden_name(c, classname, CHILD(n, 3), 0))
+            return NULL;
+        return ClassDef(classname, NULL, NULL, s, decorator_seq, LINENO(n),
+                        n->n_col_offset, c->c_arena);
+    }
+
+    /* class NAME '(' arglist ')' ':' suite */
+    /* build up a fake Call node so we can extract its pieces */
+    {
+        PyObject *dummy_name;
+        expr_ty dummy;
+        dummy_name = NEW_IDENTIFIER(CHILD(n, 1));
+        if (!dummy_name)
+            return NULL;
+        dummy = Name(dummy_name, Load, LINENO(n), n->n_col_offset, c->c_arena);
+        call = ast_for_call(c, CHILD(n, 3), dummy);
+        if (!call)
+            return NULL;
+    }
+    s = ast_for_suite(c, CHILD(n, 6));
+    if (!s)
+        return NULL;
+    classname = NEW_IDENTIFIER(CHILD(n, 1));
+    if (!classname)
+        return NULL;
+    if (forbidden_name(c, classname, CHILD(n, 1), 0))
+        return NULL;
+
+    return ClassDef(classname, call->v.Call.args, call->v.Call.keywords, s,
+                    decorator_seq, LINENO(n), n->n_col_offset, c->c_arena);
+}
+
+static stmt_ty
+ast_for_stmt(struct compiling *c, const node *n)
+{
+    if (TYPE(n) == stmt) {
+        assert(NCH(n) == 1);
+        n = CHILD(n, 0);
+    }
+    if (TYPE(n) == simple_stmt) {
+        assert(num_stmts(n) == 1);
+        n = CHILD(n, 0);
+    }
+    if (TYPE(n) == small_stmt) {
+        n = CHILD(n, 0);
+        /* small_stmt: expr_stmt | del_stmt | pass_stmt | flow_stmt
+                  | import_stmt | global_stmt | nonlocal_stmt | assert_stmt
+        */
+        switch (TYPE(n)) {
+            case expr_stmt:
+                return ast_for_expr_stmt(c, n);
+            case del_stmt:
+                return ast_for_del_stmt(c, n);
+            case pass_stmt:
+                return Pass(LINENO(n), n->n_col_offset, c->c_arena);
+            case flow_stmt:
+                return ast_for_flow_stmt(c, n);
+            case import_stmt:
+                return ast_for_import_stmt(c, n);
+            case global_stmt:
+                return ast_for_global_stmt(c, n);
+            case nonlocal_stmt:
+                return ast_for_nonlocal_stmt(c, n);
+            case assert_stmt:
+                return ast_for_assert_stmt(c, n);
+            default:
+                PyErr_Format(PyExc_SystemError,
+                             "unhandled small_stmt: TYPE=%d NCH=%d\n",
+                             TYPE(n), NCH(n));
+                return NULL;
+        }
+    }
+    else {
+        /* compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt
+                        | funcdef | classdef | decorated | async_stmt
+        */
+        node *ch = CHILD(n, 0);
+        REQ(n, compound_stmt);
+        switch (TYPE(ch)) {
+            case if_stmt:
+                return ast_for_if_stmt(c, ch);
+            case while_stmt:
+                return ast_for_while_stmt(c, ch);
+            case for_stmt:
+                return ast_for_for_stmt(c, ch, 0);
+            case try_stmt:
+                return ast_for_try_stmt(c, ch);
+            case with_stmt:
+                return ast_for_with_stmt(c, ch, 0);
+            case funcdef:
+                return ast_for_funcdef(c, ch, NULL);
+            case classdef:
+                return ast_for_classdef(c, ch, NULL);
+            case decorated:
+                return ast_for_decorated(c, ch);
+            case async_stmt:
+                return ast_for_async_stmt(c, ch);
+            default:
+                PyErr_Format(PyExc_SystemError,
+                             "unhandled small_stmt: TYPE=%d NCH=%d\n",
+                             TYPE(n), NCH(n));
+                return NULL;
+        }
+    }
+}
+
+static PyObject *
+parsenumber(struct compiling *c, const char *s)
+{
+    const char *end;
+    long x;
+    double dx;
+    Py_complex compl;
+    int imflag;
+
+    assert(s != NULL);
+    errno = 0;
+    end = s + strlen(s) - 1;
+    imflag = *end == 'j' || *end == 'J';
+    if (s[0] == '0') {
+        x = (long) PyOS_strtoul(s, (char **)&end, 0);
+        if (x < 0 && errno == 0) {
+            return PyLong_FromString(s, (char **)0, 0);
+        }
+    }
+    else
+        x = PyOS_strtol(s, (char **)&end, 0);
+    if (*end == '\0') {
+        if (errno != 0)
+            return PyLong_FromString(s, (char **)0, 0);
+        return PyLong_FromLong(x);
+    }
+    /* XXX Huge floats may silently fail */
+    if (imflag) {
+        compl.real = 0.;
+        compl.imag = PyOS_string_to_double(s, (char **)&end, NULL);
+        if (compl.imag == -1.0 && PyErr_Occurred())
+            return NULL;
+        return PyComplex_FromCComplex(compl);
+    }
+    else
+    {
+        dx = PyOS_string_to_double(s, NULL, NULL);
+        if (dx == -1.0 && PyErr_Occurred())
+            return NULL;
+        return PyFloat_FromDouble(dx);
+    }
+}
+
+static PyObject *
+decode_utf8(struct compiling *c, const char **sPtr, const char *end)
+{
+    const char *s, *t;
+    t = s = *sPtr;
+    /* while (s < end && *s != '\\') s++; */ /* inefficient for u".." */
+    while (s < end && (*s & 0x80)) s++;
+    *sPtr = s;
+    return PyUnicode_DecodeUTF8(t, s - t, NULL);
+}
+
+static PyObject *
+decode_unicode(struct compiling *c, const char *s, size_t len, int rawmode, const char *encoding)
+{
+    PyObject *v, *u;
+    char *buf;
+    char *p;
+    const char *end;
+
+    if (encoding == NULL) {
+        u = NULL;
+    } else {
+        /* check for integer overflow */
+        if (len > PY_SIZE_MAX / 6)
+            return NULL;
+        /* "ä" (2 bytes) may become "\U000000E4" (10 bytes), or 1:5
+           "\ä" (3 bytes) may become "\u005c\U000000E4" (16 bytes), or ~1:6 */
+        u = PyBytes_FromStringAndSize((char *)NULL, len * 6);
+        if (u == NULL)
+            return NULL;
+        p = buf = PyBytes_AsString(u);
+        end = s + len;
+        while (s < end) {
+            if (*s == '\\') {
+                *p++ = *s++;
+                if (*s & 0x80) {
+                    strcpy(p, "u005c");
+                    p += 5;
+                }
+            }
+            if (*s & 0x80) { /* XXX inefficient */
+                PyObject *w;
+                int kind;
+                void *data;
+                Py_ssize_t len, i;
+                w = decode_utf8(c, &s, end);
+                if (w == NULL) {
+                    Py_DECREF(u);
+                    return NULL;
+                }
+                kind = PyUnicode_KIND(w);
+                data = PyUnicode_DATA(w);
+                len = PyUnicode_GET_LENGTH(w);
+                for (i = 0; i < len; i++) {
+                    Py_UCS4 chr = PyUnicode_READ(kind, data, i);
+                    sprintf(p, "\\U%08x", chr);
+                    p += 10;
+                }
+                /* Should be impossible to overflow */
+                assert(p - buf <= Py_SIZE(u));
+                Py_DECREF(w);
+            } else {
+                *p++ = *s++;
+            }
+        }
+        len = p - buf;
+        s = buf;
+    }
+    if (rawmode)
+        v = PyUnicode_DecodeRawUnicodeEscape(s, len, NULL);
+    else
+        v = PyUnicode_DecodeUnicodeEscape(s, len, NULL);
+    Py_XDECREF(u);
+    return v;
+}
+
+/* s is a Python string literal, including the bracketing quote characters,
+ * and r &/or b prefixes (if any), and embedded escape sequences (if any).
+ * parsestr parses it, and returns the decoded Python string object.
+ */
+static PyObject *
+parsestr(struct compiling *c, const node *n, int *bytesmode)
+{
+    size_t len;
+    const char *s = STR(n);
+    int quote = Py_CHARMASK(*s);
+    int rawmode = 0;
+    int need_encoding;
+    if (Py_ISALPHA(quote)) {
+        while (!*bytesmode || !rawmode) {
+            if (quote == 'b' || quote == 'B') {
+                quote = *++s;
+                *bytesmode = 1;
+            }
+            else if (quote == 'u' || quote == 'U') {
+                quote = *++s;
+            }
+            else if (quote == 'r' || quote == 'R') {
+                quote = *++s;
+                rawmode = 1;
+            }
+            else {
+                break;
+            }
+        }
+    }
+    if (quote != '\'' && quote != '\"') {
+        PyErr_BadInternalCall();
+        return NULL;
+    }
+    s++;
+    len = strlen(s);
+    if (len > INT_MAX) {
+        PyErr_SetString(PyExc_OverflowError,
+                        "string to parse is too long");
+        return NULL;
+    }
+    if (s[--len] != quote) {
+        PyErr_BadInternalCall();
+        return NULL;
+    }
+    if (len >= 4 && s[0] == quote && s[1] == quote) {
+        s += 2;
+        len -= 2;
+        if (s[--len] != quote || s[--len] != quote) {
+            PyErr_BadInternalCall();
+            return NULL;
+        }
+    }
+    if (!*bytesmode && !rawmode) {
+        return decode_unicode(c, s, len, rawmode, c->c_encoding);
+    }
+    if (*bytesmode) {
+        /* Disallow non-ascii characters (but not escapes) */
+        const char *ch;
+        for (ch = s; *ch; ch++) {
+            if (Py_CHARMASK(*ch) >= 0x80) {
+                ast_error(c, n, "bytes can only contain ASCII "
+                          "literal characters.");
+                return NULL;
+            }
+        }
+    }
+    need_encoding = (!*bytesmode && c->c_encoding != NULL &&
+                     strcmp(c->c_encoding, "utf-8") != 0);
+    if (rawmode || strchr(s, '\\') == NULL) {
+        if (need_encoding) {
+            PyObject *v, *u = PyUnicode_DecodeUTF8(s, len, NULL);
+            if (u == NULL || !*bytesmode)
+                return u;
+            v = PyUnicode_AsEncodedString(u, c->c_encoding, NULL);
+            Py_DECREF(u);
+            return v;
+        } else if (*bytesmode) {
+            return PyBytes_FromStringAndSize(s, len);
+        } else if (strcmp(c->c_encoding, "utf-8") == 0) {
+            return PyUnicode_FromStringAndSize(s, len);
+        } else {
+            return PyUnicode_DecodeLatin1(s, len, NULL);
+        }
+    }
+    return PyBytes_DecodeEscape(s, len, NULL, 1,
+                                 need_encoding ? c->c_encoding : NULL);
+}
+
+/* Build a Python string object out of a STRING+ atom.  This takes care of
+ * compile-time literal catenation, calling parsestr() on each piece, and
+ * pasting the intermediate results together.
+ */
+static PyObject *
+parsestrplus(struct compiling *c, const node *n, int *bytesmode)
+{
+    PyObject *v;
+    int i;
+    REQ(CHILD(n, 0), STRING);
+    v = parsestr(c, CHILD(n, 0), bytesmode);
+    if (v != NULL) {
+        /* String literal concatenation */
+        for (i = 1; i < NCH(n); i++) {
+            PyObject *s;
+            int subbm = 0;
+            s = parsestr(c, CHILD(n, i), &subbm);
+            if (s == NULL)
+                goto onError;
+            if (*bytesmode != subbm) {
+                ast_error(c, n, "cannot mix bytes and nonbytes literals");
+                Py_DECREF(s);
+                goto onError;
+            }
+            if (PyBytes_Check(v) && PyBytes_Check(s)) {
+                PyBytes_ConcatAndDel(&v, s);
+                if (v == NULL)
+                    goto onError;
+            }
+            else {
+                PyObject *temp = PyUnicode_Concat(v, s);
+                Py_DECREF(s);
+                Py_DECREF(v);
+                v = temp;
+                if (v == NULL)
+                    goto onError;
+            }
+        }
+    }
+    return v;
+
+  onError:
+    Py_XDECREF(v);
+    return NULL;
+}
diff --git a/ast35/Python/graminit.c b/ast35/Python/graminit.c
new file mode 100644
index 0000000..2997200
--- /dev/null
+++ b/ast35/Python/graminit.c
@@ -0,0 +1,2390 @@
+/* Generated by Parser/pgen */
+
+#include "pgenheaders.h"
+#include "grammar.h"
+PyAPI_DATA(grammar) _Ta35Parser_Grammar;
+static arc arcs_0_0[3] = {
+    {2, 1},
+    {3, 1},
+    {4, 2},
+};
+static arc arcs_0_1[1] = {
+    {0, 1},
+};
+static arc arcs_0_2[1] = {
+    {2, 1},
+};
+static state states_0[3] = {
+    {3, arcs_0_0},
+    {1, arcs_0_1},
+    {1, arcs_0_2},
+};
+static arc arcs_1_0[3] = {
+    {2, 0},
+    {6, 0},
+    {7, 1},
+};
+static arc arcs_1_1[1] = {
+    {0, 1},
+};
+static state states_1[2] = {
+    {3, arcs_1_0},
+    {1, arcs_1_1},
+};
+static arc arcs_2_0[1] = {
+    {9, 1},
+};
+static arc arcs_2_1[2] = {
+    {2, 1},
+    {7, 2},
+};
+static arc arcs_2_2[1] = {
+    {0, 2},
+};
+static state states_2[3] = {
+    {1, arcs_2_0},
+    {2, arcs_2_1},
+    {1, arcs_2_2},
+};
+static arc arcs_3_0[1] = {
+    {11, 1},
+};
+static arc arcs_3_1[1] = {
+    {12, 2},
+};
+static arc arcs_3_2[2] = {
+    {13, 3},
+    {2, 4},
+};
+static arc arcs_3_3[2] = {
+    {14, 5},
+    {15, 6},
+};
+static arc arcs_3_4[1] = {
+    {0, 4},
+};
+static arc arcs_3_5[1] = {
+    {15, 6},
+};
+static arc arcs_3_6[1] = {
+    {2, 4},
+};
+static state states_3[7] = {
+    {1, arcs_3_0},
+    {1, arcs_3_1},
+    {2, arcs_3_2},
+    {2, arcs_3_3},
+    {1, arcs_3_4},
+    {1, arcs_3_5},
+    {1, arcs_3_6},
+};
+static arc arcs_4_0[1] = {
+    {10, 1},
+};
+static arc arcs_4_1[2] = {
+    {10, 1},
+    {0, 1},
+};
+static state states_4[2] = {
+    {1, arcs_4_0},
+    {2, arcs_4_1},
+};
+static arc arcs_5_0[1] = {
+    {16, 1},
+};
+static arc arcs_5_1[3] = {
+    {18, 2},
+    {19, 2},
+    {20, 2},
+};
+static arc arcs_5_2[1] = {
+    {0, 2},
+};
+static state states_5[3] = {
+    {1, arcs_5_0},
+    {3, arcs_5_1},
+    {1, arcs_5_2},
+};
+static arc arcs_6_0[1] = {
+    {21, 1},
+};
+static arc arcs_6_1[1] = {
+    {19, 2},
+};
+static arc arcs_6_2[1] = {
+    {0, 2},
+};
+static state states_6[3] = {
+    {1, arcs_6_0},
+    {1, arcs_6_1},
+    {1, arcs_6_2},
+};
+static arc arcs_7_0[1] = {
+    {22, 1},
+};
+static arc arcs_7_1[1] = {
+    {23, 2},
+};
+static arc arcs_7_2[1] = {
+    {24, 3},
+};
+static arc arcs_7_3[2] = {
+    {25, 4},
+    {27, 5},
+};
+static arc arcs_7_4[1] = {
+    {26, 6},
+};
+static arc arcs_7_5[2] = {
+    {28, 7},
+    {29, 8},
+};
+static arc arcs_7_6[1] = {
+    {27, 5},
+};
+static arc arcs_7_7[1] = {
+    {29, 8},
+};
+static arc arcs_7_8[1] = {
+    {0, 8},
+};
+static state states_7[9] = {
+    {1, arcs_7_0},
+    {1, arcs_7_1},
+    {1, arcs_7_2},
+    {2, arcs_7_3},
+    {1, arcs_7_4},
+    {2, arcs_7_5},
+    {1, arcs_7_6},
+    {1, arcs_7_7},
+    {1, arcs_7_8},
+};
+static arc arcs_8_0[1] = {
+    {13, 1},
+};
+static arc arcs_8_1[2] = {
+    {30, 2},
+    {15, 3},
+};
+static arc arcs_8_2[1] = {
+    {15, 3},
+};
+static arc arcs_8_3[1] = {
+    {0, 3},
+};
+static state states_8[4] = {
+    {1, arcs_8_0},
+    {2, arcs_8_1},
+    {1, arcs_8_2},
+    {1, arcs_8_3},
+};
+static arc arcs_9_0[3] = {
+    {31, 1},
+    {34, 2},
+    {35, 3},
+};
+static arc arcs_9_1[4] = {
+    {32, 4},
+    {33, 5},
+    {28, 6},
+    {0, 1},
+};
+static arc arcs_9_2[4] = {
+    {31, 7},
+    {33, 8},
+    {28, 6},
+    {0, 2},
+};
+static arc arcs_9_3[1] = {
+    {31, 9},
+};
+static arc arcs_9_4[1] = {
+    {26, 10},
+};
+static arc arcs_9_5[5] = {
+    {28, 11},
+    {31, 12},
+    {34, 13},
+    {35, 3},
+    {0, 5},
+};
+static arc arcs_9_6[1] = {
+    {0, 6},
+};
+static arc arcs_9_7[3] = {
+    {33, 8},
+    {28, 6},
+    {0, 7},
+};
+static arc arcs_9_8[3] = {
+    {28, 14},
+    {31, 15},
+    {35, 3},
+};
+static arc arcs_9_9[2] = {
+    {28, 6},
+    {0, 9},
+};
+static arc arcs_9_10[3] = {
+    {33, 5},
+    {28, 6},
+    {0, 10},
+};
+static arc arcs_9_11[5] = {
+    {31, 12},
+    {34, 13},
+    {35, 3},
+    {28, 6},
+    {0, 11},
+};
+static arc arcs_9_12[4] = {
+    {33, 5},
+    {32, 4},
+    {28, 6},
+    {0, 12},
+};
+static arc arcs_9_13[4] = {
+    {31, 16},
+    {33, 17},
+    {28, 6},
+    {0, 13},
+};
+static arc arcs_9_14[2] = {
+    {31, 15},
+    {35, 3},
+};
+static arc arcs_9_15[4] = {
+    {33, 8},
+    {32, 18},
+    {28, 6},
+    {0, 15},
+};
+static arc arcs_9_16[3] = {
+    {33, 17},
+    {28, 6},
+    {0, 16},
+};
+static arc arcs_9_17[3] = {
+    {28, 19},
+    {31, 20},
+    {35, 3},
+};
+static arc arcs_9_18[1] = {
+    {26, 7},
+};
+static arc arcs_9_19[2] = {
+    {31, 20},
+    {35, 3},
+};
+static arc arcs_9_20[4] = {
+    {33, 17},
+    {32, 21},
+    {28, 6},
+    {0, 20},
+};
+static arc arcs_9_21[1] = {
+    {26, 16},
+};
+static state states_9[22] = {
+    {3, arcs_9_0},
+    {4, arcs_9_1},
+    {4, arcs_9_2},
+    {1, arcs_9_3},
+    {1, arcs_9_4},
+    {5, arcs_9_5},
+    {1, arcs_9_6},
+    {3, arcs_9_7},
+    {3, arcs_9_8},
+    {2, arcs_9_9},
+    {3, arcs_9_10},
+    {5, arcs_9_11},
+    {4, arcs_9_12},
+    {4, arcs_9_13},
+    {2, arcs_9_14},
+    {4, arcs_9_15},
+    {3, arcs_9_16},
+    {3, arcs_9_17},
+    {1, arcs_9_18},
+    {2, arcs_9_19},
+    {4, arcs_9_20},
+    {1, arcs_9_21},
+};
+static arc arcs_10_0[1] = {
+    {23, 1},
+};
+static arc arcs_10_1[2] = {
+    {27, 2},
+    {0, 1},
+};
+static arc arcs_10_2[1] = {
+    {26, 3},
+};
+static arc arcs_10_3[1] = {
+    {0, 3},
+};
+static state states_10[4] = {
+    {1, arcs_10_0},
+    {2, arcs_10_1},
+    {1, arcs_10_2},
+    {1, arcs_10_3},
+};
+static arc arcs_11_0[3] = {
+    {37, 1},
+    {34, 2},
+    {35, 3},
+};
+static arc arcs_11_1[3] = {
+    {32, 4},
+    {33, 5},
+    {0, 1},
+};
+static arc arcs_11_2[3] = {
+    {37, 6},
+    {33, 7},
+    {0, 2},
+};
+static arc arcs_11_3[1] = {
+    {37, 8},
+};
+static arc arcs_11_4[1] = {
+    {26, 9},
+};
+static arc arcs_11_5[4] = {
+    {37, 10},
+    {34, 11},
+    {35, 3},
+    {0, 5},
+};
+static arc arcs_11_6[2] = {
+    {33, 7},
+    {0, 6},
+};
+static arc arcs_11_7[2] = {
+    {37, 12},
+    {35, 3},
+};
+static arc arcs_11_8[1] = {
+    {0, 8},
+};
+static arc arcs_11_9[2] = {
+    {33, 5},
+    {0, 9},
+};
+static arc arcs_11_10[3] = {
+    {33, 5},
+    {32, 4},
+    {0, 10},
+};
+static arc arcs_11_11[3] = {
+    {37, 13},
+    {33, 14},
+    {0, 11},
+};
+static arc arcs_11_12[3] = {
+    {33, 7},
+    {32, 15},
+    {0, 12},
+};
+static arc arcs_11_13[2] = {
+    {33, 14},
+    {0, 13},
+};
+static arc arcs_11_14[2] = {
+    {37, 16},
+    {35, 3},
+};
+static arc arcs_11_15[1] = {
+    {26, 6},
+};
+static arc arcs_11_16[3] = {
+    {33, 14},
+    {32, 17},
+    {0, 16},
+};
+static arc arcs_11_17[1] = {
+    {26, 13},
+};
+static state states_11[18] = {
+    {3, arcs_11_0},
+    {3, arcs_11_1},
+    {3, arcs_11_2},
+    {1, arcs_11_3},
+    {1, arcs_11_4},
+    {4, arcs_11_5},
+    {2, arcs_11_6},
+    {2, arcs_11_7},
+    {1, arcs_11_8},
+    {2, arcs_11_9},
+    {3, arcs_11_10},
+    {3, arcs_11_11},
+    {3, arcs_11_12},
+    {2, arcs_11_13},
+    {2, arcs_11_14},
+    {1, arcs_11_15},
+    {3, arcs_11_16},
+    {1, arcs_11_17},
+};
+static arc arcs_12_0[1] = {
+    {23, 1},
+};
+static arc arcs_12_1[1] = {
+    {0, 1},
+};
+static state states_12[2] = {
+    {1, arcs_12_0},
+    {1, arcs_12_1},
+};
+static arc arcs_13_0[2] = {
+    {3, 1},
+    {4, 1},
+};
+static arc arcs_13_1[1] = {
+    {0, 1},
+};
+static state states_13[2] = {
+    {2, arcs_13_0},
+    {1, arcs_13_1},
+};
+static arc arcs_14_0[1] = {
+    {38, 1},
+};
+static arc arcs_14_1[2] = {
+    {39, 2},
+    {2, 3},
+};
+static arc arcs_14_2[2] = {
+    {38, 1},
+    {2, 3},
+};
+static arc arcs_14_3[1] = {
+    {0, 3},
+};
+static state states_14[4] = {
+    {1, arcs_14_0},
+    {2, arcs_14_1},
+    {2, arcs_14_2},
+    {1, arcs_14_3},
+};
+static arc arcs_15_0[8] = {
+    {40, 1},
+    {41, 1},
+    {42, 1},
+    {43, 1},
+    {44, 1},
+    {45, 1},
+    {46, 1},
+    {47, 1},
+};
+static arc arcs_15_1[1] = {
+    {0, 1},
+};
+static state states_15[2] = {
+    {8, arcs_15_0},
+    {1, arcs_15_1},
+};
+static arc arcs_16_0[1] = {
+    {48, 1},
+};
+static arc arcs_16_1[4] = {
+    {49, 2},
+    {32, 3},
+    {28, 4},
+    {0, 1},
+};
+static arc arcs_16_2[2] = {
+    {50, 4},
+    {9, 4},
+};
+static arc arcs_16_3[2] = {
+    {50, 5},
+    {48, 5},
+};
+static arc arcs_16_4[1] = {
+    {0, 4},
+};
+static arc arcs_16_5[3] = {
+    {32, 3},
+    {28, 4},
+    {0, 5},
+};
+static state states_16[6] = {
+    {1, arcs_16_0},
+    {4, arcs_16_1},
+    {2, arcs_16_2},
+    {2, arcs_16_3},
+    {1, arcs_16_4},
+    {3, arcs_16_5},
+};
+static arc arcs_17_0[2] = {
+    {26, 1},
+    {51, 1},
+};
+static arc arcs_17_1[2] = {
+    {33, 2},
+    {0, 1},
+};
+static arc arcs_17_2[3] = {
+    {26, 1},
+    {51, 1},
+    {0, 2},
+};
+static state states_17[3] = {
+    {2, arcs_17_0},
+    {2, arcs_17_1},
+    {3, arcs_17_2},
+};
+static arc arcs_18_0[13] = {
+    {52, 1},
+    {53, 1},
+    {54, 1},
+    {55, 1},
+    {56, 1},
+    {57, 1},
+    {58, 1},
+    {59, 1},
+    {60, 1},
+    {61, 1},
+    {62, 1},
+    {63, 1},
+    {64, 1},
+};
+static arc arcs_18_1[1] = {
+    {0, 1},
+};
+static state states_18[2] = {
+    {13, arcs_18_0},
+    {1, arcs_18_1},
+};
+static arc arcs_19_0[1] = {
+    {65, 1},
+};
+static arc arcs_19_1[1] = {
+    {66, 2},
+};
+static arc arcs_19_2[1] = {
+    {0, 2},
+};
+static state states_19[3] = {
+    {1, arcs_19_0},
+    {1, arcs_19_1},
+    {1, arcs_19_2},
+};
+static arc arcs_20_0[1] = {
+    {67, 1},
+};
+static arc arcs_20_1[1] = {
+    {0, 1},
+};
+static state states_20[2] = {
+    {1, arcs_20_0},
+    {1, arcs_20_1},
+};
+static arc arcs_21_0[5] = {
+    {68, 1},
+    {69, 1},
+    {70, 1},
+    {71, 1},
+    {72, 1},
+};
+static arc arcs_21_1[1] = {
+    {0, 1},
+};
+static state states_21[2] = {
+    {5, arcs_21_0},
+    {1, arcs_21_1},
+};
+static arc arcs_22_0[1] = {
+    {73, 1},
+};
+static arc arcs_22_1[1] = {
+    {0, 1},
+};
+static state states_22[2] = {
+    {1, arcs_22_0},
+    {1, arcs_22_1},
+};
+static arc arcs_23_0[1] = {
+    {74, 1},
+};
+static arc arcs_23_1[1] = {
+    {0, 1},
+};
+static state states_23[2] = {
+    {1, arcs_23_0},
+    {1, arcs_23_1},
+};
+static arc arcs_24_0[1] = {
+    {75, 1},
+};
+static arc arcs_24_1[2] = {
+    {9, 2},
+    {0, 1},
+};
+static arc arcs_24_2[1] = {
+    {0, 2},
+};
+static state states_24[3] = {
+    {1, arcs_24_0},
+    {2, arcs_24_1},
+    {1, arcs_24_2},
+};
+static arc arcs_25_0[1] = {
+    {50, 1},
+};
+static arc arcs_25_1[1] = {
+    {0, 1},
+};
+static state states_25[2] = {
+    {1, arcs_25_0},
+    {1, arcs_25_1},
+};
+static arc arcs_26_0[1] = {
+    {76, 1},
+};
+static arc arcs_26_1[2] = {
+    {26, 2},
+    {0, 1},
+};
+static arc arcs_26_2[2] = {
+    {77, 3},
+    {0, 2},
+};
+static arc arcs_26_3[1] = {
+    {26, 4},
+};
+static arc arcs_26_4[1] = {
+    {0, 4},
+};
+static state states_26[5] = {
+    {1, arcs_26_0},
+    {2, arcs_26_1},
+    {2, arcs_26_2},
+    {1, arcs_26_3},
+    {1, arcs_26_4},
+};
+static arc arcs_27_0[2] = {
+    {78, 1},
+    {79, 1},
+};
+static arc arcs_27_1[1] = {
+    {0, 1},
+};
+static state states_27[2] = {
+    {2, arcs_27_0},
+    {1, arcs_27_1},
+};
+static arc arcs_28_0[1] = {
+    {80, 1},
+};
+static arc arcs_28_1[1] = {
+    {81, 2},
+};
+static arc arcs_28_2[1] = {
+    {0, 2},
+};
+static state states_28[3] = {
+    {1, arcs_28_0},
+    {1, arcs_28_1},
+    {1, arcs_28_2},
+};
+static arc arcs_29_0[1] = {
+    {77, 1},
+};
+static arc arcs_29_1[3] = {
+    {82, 2},
+    {83, 2},
+    {12, 3},
+};
+static arc arcs_29_2[4] = {
+    {82, 2},
+    {83, 2},
+    {12, 3},
+    {80, 4},
+};
+static arc arcs_29_3[1] = {
+    {80, 4},
+};
+static arc arcs_29_4[3] = {
+    {34, 5},
+    {13, 6},
+    {84, 5},
+};
+static arc arcs_29_5[1] = {
+    {0, 5},
+};
+static arc arcs_29_6[1] = {
+    {84, 7},
+};
+static arc arcs_29_7[1] = {
+    {15, 5},
+};
+static state states_29[8] = {
+    {1, arcs_29_0},
+    {3, arcs_29_1},
+    {4, arcs_29_2},
+    {1, arcs_29_3},
+    {3, arcs_29_4},
+    {1, arcs_29_5},
+    {1, arcs_29_6},
+    {1, arcs_29_7},
+};
+static arc arcs_30_0[1] = {
+    {23, 1},
+};
+static arc arcs_30_1[2] = {
+    {86, 2},
+    {0, 1},
+};
+static arc arcs_30_2[1] = {
+    {23, 3},
+};
+static arc arcs_30_3[1] = {
+    {0, 3},
+};
+static state states_30[4] = {
+    {1, arcs_30_0},
+    {2, arcs_30_1},
+    {1, arcs_30_2},
+    {1, arcs_30_3},
+};
+static arc arcs_31_0[1] = {
+    {12, 1},
+};
+static arc arcs_31_1[2] = {
+    {86, 2},
+    {0, 1},
+};
+static arc arcs_31_2[1] = {
+    {23, 3},
+};
+static arc arcs_31_3[1] = {
+    {0, 3},
+};
+static state states_31[4] = {
+    {1, arcs_31_0},
+    {2, arcs_31_1},
+    {1, arcs_31_2},
+    {1, arcs_31_3},
+};
+static arc arcs_32_0[1] = {
+    {85, 1},
+};
+static arc arcs_32_1[2] = {
+    {33, 2},
+    {0, 1},
+};
+static arc arcs_32_2[2] = {
+    {85, 1},
+    {0, 2},
+};
+static state states_32[3] = {
+    {1, arcs_32_0},
+    {2, arcs_32_1},
+    {2, arcs_32_2},
+};
+static arc arcs_33_0[1] = {
+    {87, 1},
+};
+static arc arcs_33_1[2] = {
+    {33, 0},
+    {0, 1},
+};
+static state states_33[2] = {
+    {1, arcs_33_0},
+    {2, arcs_33_1},
+};
+static arc arcs_34_0[1] = {
+    {23, 1},
+};
+static arc arcs_34_1[2] = {
+    {82, 0},
+    {0, 1},
+};
+static state states_34[2] = {
+    {1, arcs_34_0},
+    {2, arcs_34_1},
+};
+static arc arcs_35_0[1] = {
+    {88, 1},
+};
+static arc arcs_35_1[1] = {
+    {23, 2},
+};
+static arc arcs_35_2[2] = {
+    {33, 1},
+    {0, 2},
+};
+static state states_35[3] = {
+    {1, arcs_35_0},
+    {1, arcs_35_1},
+    {2, arcs_35_2},
+};
+static arc arcs_36_0[1] = {
+    {89, 1},
+};
+static arc arcs_36_1[1] = {
+    {23, 2},
+};
+static arc arcs_36_2[2] = {
+    {33, 1},
+    {0, 2},
+};
+static state states_36[3] = {
+    {1, arcs_36_0},
+    {1, arcs_36_1},
+    {2, arcs_36_2},
+};
+static arc arcs_37_0[1] = {
+    {90, 1},
+};
+static arc arcs_37_1[1] = {
+    {26, 2},
+};
+static arc arcs_37_2[2] = {
+    {33, 3},
+    {0, 2},
+};
+static arc arcs_37_3[1] = {
+    {26, 4},
+};
+static arc arcs_37_4[1] = {
+    {0, 4},
+};
+static state states_37[5] = {
+    {1, arcs_37_0},
+    {1, arcs_37_1},
+    {2, arcs_37_2},
+    {1, arcs_37_3},
+    {1, arcs_37_4},
+};
+static arc arcs_38_0[9] = {
+    {91, 1},
+    {92, 1},
+    {93, 1},
+    {94, 1},
+    {95, 1},
+    {19, 1},
+    {18, 1},
+    {17, 1},
+    {96, 1},
+};
+static arc arcs_38_1[1] = {
+    {0, 1},
+};
+static state states_38[2] = {
+    {9, arcs_38_0},
+    {1, arcs_38_1},
+};
+static arc arcs_39_0[1] = {
+    {21, 1},
+};
+static arc arcs_39_1[3] = {
+    {19, 2},
+    {95, 2},
+    {93, 2},
+};
+static arc arcs_39_2[1] = {
+    {0, 2},
+};
+static state states_39[3] = {
+    {1, arcs_39_0},
+    {3, arcs_39_1},
+    {1, arcs_39_2},
+};
+static arc arcs_40_0[1] = {
+    {97, 1},
+};
+static arc arcs_40_1[1] = {
+    {26, 2},
+};
+static arc arcs_40_2[1] = {
+    {27, 3},
+};
+static arc arcs_40_3[1] = {
+    {29, 4},
+};
+static arc arcs_40_4[3] = {
+    {98, 1},
+    {99, 5},
+    {0, 4},
+};
+static arc arcs_40_5[1] = {
+    {27, 6},
+};
+static arc arcs_40_6[1] = {
+    {29, 7},
+};
+static arc arcs_40_7[1] = {
+    {0, 7},
+};
+static state states_40[8] = {
+    {1, arcs_40_0},
+    {1, arcs_40_1},
+    {1, arcs_40_2},
+    {1, arcs_40_3},
+    {3, arcs_40_4},
+    {1, arcs_40_5},
+    {1, arcs_40_6},
+    {1, arcs_40_7},
+};
+static arc arcs_41_0[1] = {
+    {100, 1},
+};
+static arc arcs_41_1[1] = {
+    {26, 2},
+};
+static arc arcs_41_2[1] = {
+    {27, 3},
+};
+static arc arcs_41_3[1] = {
+    {29, 4},
+};
+static arc arcs_41_4[2] = {
+    {99, 5},
+    {0, 4},
+};
+static arc arcs_41_5[1] = {
+    {27, 6},
+};
+static arc arcs_41_6[1] = {
+    {29, 7},
+};
+static arc arcs_41_7[1] = {
+    {0, 7},
+};
+static state states_41[8] = {
+    {1, arcs_41_0},
+    {1, arcs_41_1},
+    {1, arcs_41_2},
+    {1, arcs_41_3},
+    {2, arcs_41_4},
+    {1, arcs_41_5},
+    {1, arcs_41_6},
+    {1, arcs_41_7},
+};
+static arc arcs_42_0[1] = {
+    {101, 1},
+};
+static arc arcs_42_1[1] = {
+    {66, 2},
+};
+static arc arcs_42_2[1] = {
+    {102, 3},
+};
+static arc arcs_42_3[1] = {
+    {9, 4},
+};
+static arc arcs_42_4[1] = {
+    {27, 5},
+};
+static arc arcs_42_5[2] = {
+    {28, 6},
+    {29, 7},
+};
+static arc arcs_42_6[1] = {
+    {29, 7},
+};
+static arc arcs_42_7[2] = {
+    {99, 8},
+    {0, 7},
+};
+static arc arcs_42_8[1] = {
+    {27, 9},
+};
+static arc arcs_42_9[1] = {
+    {29, 10},
+};
+static arc arcs_42_10[1] = {
+    {0, 10},
+};
+static state states_42[11] = {
+    {1, arcs_42_0},
+    {1, arcs_42_1},
+    {1, arcs_42_2},
+    {1, arcs_42_3},
+    {1, arcs_42_4},
+    {2, arcs_42_5},
+    {1, arcs_42_6},
+    {2, arcs_42_7},
+    {1, arcs_42_8},
+    {1, arcs_42_9},
+    {1, arcs_42_10},
+};
+static arc arcs_43_0[1] = {
+    {103, 1},
+};
+static arc arcs_43_1[1] = {
+    {27, 2},
+};
+static arc arcs_43_2[1] = {
+    {29, 3},
+};
+static arc arcs_43_3[2] = {
+    {104, 4},
+    {105, 5},
+};
+static arc arcs_43_4[1] = {
+    {27, 6},
+};
+static arc arcs_43_5[1] = {
+    {27, 7},
+};
+static arc arcs_43_6[1] = {
+    {29, 8},
+};
+static arc arcs_43_7[1] = {
+    {29, 9},
+};
+static arc arcs_43_8[4] = {
+    {104, 4},
+    {99, 10},
+    {105, 5},
+    {0, 8},
+};
+static arc arcs_43_9[1] = {
+    {0, 9},
+};
+static arc arcs_43_10[1] = {
+    {27, 11},
+};
+static arc arcs_43_11[1] = {
+    {29, 12},
+};
+static arc arcs_43_12[2] = {
+    {105, 5},
+    {0, 12},
+};
+static state states_43[13] = {
+    {1, arcs_43_0},
+    {1, arcs_43_1},
+    {1, arcs_43_2},
+    {2, arcs_43_3},
+    {1, arcs_43_4},
+    {1, arcs_43_5},
+    {1, arcs_43_6},
+    {1, arcs_43_7},
+    {4, arcs_43_8},
+    {1, arcs_43_9},
+    {1, arcs_43_10},
+    {1, arcs_43_11},
+    {2, arcs_43_12},
+};
+static arc arcs_44_0[1] = {
+    {106, 1},
+};
+static arc arcs_44_1[1] = {
+    {107, 2},
+};
+static arc arcs_44_2[2] = {
+    {33, 1},
+    {27, 3},
+};
+static arc arcs_44_3[2] = {
+    {28, 4},
+    {29, 5},
+};
+static arc arcs_44_4[1] = {
+    {29, 5},
+};
+static arc arcs_44_5[1] = {
+    {0, 5},
+};
+static state states_44[6] = {
+    {1, arcs_44_0},
+    {1, arcs_44_1},
+    {2, arcs_44_2},
+    {2, arcs_44_3},
+    {1, arcs_44_4},
+    {1, arcs_44_5},
+};
+static arc arcs_45_0[1] = {
+    {26, 1},
+};
+static arc arcs_45_1[2] = {
+    {86, 2},
+    {0, 1},
+};
+static arc arcs_45_2[1] = {
+    {108, 3},
+};
+static arc arcs_45_3[1] = {
+    {0, 3},
+};
+static state states_45[4] = {
+    {1, arcs_45_0},
+    {2, arcs_45_1},
+    {1, arcs_45_2},
+    {1, arcs_45_3},
+};
+static arc arcs_46_0[1] = {
+    {109, 1},
+};
+static arc arcs_46_1[2] = {
+    {26, 2},
+    {0, 1},
+};
+static arc arcs_46_2[2] = {
+    {86, 3},
+    {0, 2},
+};
+static arc arcs_46_3[1] = {
+    {23, 4},
+};
+static arc arcs_46_4[1] = {
+    {0, 4},
+};
+static state states_46[5] = {
+    {1, arcs_46_0},
+    {2, arcs_46_1},
+    {2, arcs_46_2},
+    {1, arcs_46_3},
+    {1, arcs_46_4},
+};
+static arc arcs_47_0[2] = {
+    {3, 1},
+    {2, 2},
+};
+static arc arcs_47_1[1] = {
+    {0, 1},
+};
+static arc arcs_47_2[2] = {
+    {28, 3},
+    {110, 4},
+};
+static arc arcs_47_3[1] = {
+    {2, 5},
+};
+static arc arcs_47_4[1] = {
+    {6, 6},
+};
+static arc arcs_47_5[1] = {
+    {110, 4},
+};
+static arc arcs_47_6[2] = {
+    {6, 6},
+    {111, 1},
+};
+static state states_47[7] = {
+    {2, arcs_47_0},
+    {1, arcs_47_1},
+    {2, arcs_47_2},
+    {1, arcs_47_3},
+    {1, arcs_47_4},
+    {1, arcs_47_5},
+    {2, arcs_47_6},
+};
+static arc arcs_48_0[2] = {
+    {112, 1},
+    {113, 2},
+};
+static arc arcs_48_1[2] = {
+    {97, 3},
+    {0, 1},
+};
+static arc arcs_48_2[1] = {
+    {0, 2},
+};
+static arc arcs_48_3[1] = {
+    {112, 4},
+};
+static arc arcs_48_4[1] = {
+    {99, 5},
+};
+static arc arcs_48_5[1] = {
+    {26, 2},
+};
+static state states_48[6] = {
+    {2, arcs_48_0},
+    {2, arcs_48_1},
+    {1, arcs_48_2},
+    {1, arcs_48_3},
+    {1, arcs_48_4},
+    {1, arcs_48_5},
+};
+static arc arcs_49_0[2] = {
+    {112, 1},
+    {115, 1},
+};
+static arc arcs_49_1[1] = {
+    {0, 1},
+};
+static state states_49[2] = {
+    {2, arcs_49_0},
+    {1, arcs_49_1},
+};
+static arc arcs_50_0[1] = {
+    {116, 1},
+};
+static arc arcs_50_1[2] = {
+    {36, 2},
+    {27, 3},
+};
+static arc arcs_50_2[1] = {
+    {27, 3},
+};
+static arc arcs_50_3[1] = {
+    {26, 4},
+};
+static arc arcs_50_4[1] = {
+    {0, 4},
+};
+static state states_50[5] = {
+    {1, arcs_50_0},
+    {2, arcs_50_1},
+    {1, arcs_50_2},
+    {1, arcs_50_3},
+    {1, arcs_50_4},
+};
+static arc arcs_51_0[1] = {
+    {116, 1},
+};
+static arc arcs_51_1[2] = {
+    {36, 2},
+    {27, 3},
+};
+static arc arcs_51_2[1] = {
+    {27, 3},
+};
+static arc arcs_51_3[1] = {
+    {114, 4},
+};
+static arc arcs_51_4[1] = {
+    {0, 4},
+};
+static state states_51[5] = {
+    {1, arcs_51_0},
+    {2, arcs_51_1},
+    {1, arcs_51_2},
+    {1, arcs_51_3},
+    {1, arcs_51_4},
+};
+static arc arcs_52_0[1] = {
+    {117, 1},
+};
+static arc arcs_52_1[2] = {
+    {118, 0},
+    {0, 1},
+};
+static state states_52[2] = {
+    {1, arcs_52_0},
+    {2, arcs_52_1},
+};
+static arc arcs_53_0[1] = {
+    {119, 1},
+};
+static arc arcs_53_1[2] = {
+    {120, 0},
+    {0, 1},
+};
+static state states_53[2] = {
+    {1, arcs_53_0},
+    {2, arcs_53_1},
+};
+static arc arcs_54_0[2] = {
+    {121, 1},
+    {122, 2},
+};
+static arc arcs_54_1[1] = {
+    {119, 2},
+};
+static arc arcs_54_2[1] = {
+    {0, 2},
+};
+static state states_54[3] = {
+    {2, arcs_54_0},
+    {1, arcs_54_1},
+    {1, arcs_54_2},
+};
+static arc arcs_55_0[1] = {
+    {108, 1},
+};
+static arc arcs_55_1[2] = {
+    {123, 0},
+    {0, 1},
+};
+static state states_55[2] = {
+    {1, arcs_55_0},
+    {2, arcs_55_1},
+};
+static arc arcs_56_0[10] = {
+    {124, 1},
+    {125, 1},
+    {126, 1},
+    {127, 1},
+    {128, 1},
+    {129, 1},
+    {130, 1},
+    {102, 1},
+    {121, 2},
+    {131, 3},
+};
+static arc arcs_56_1[1] = {
+    {0, 1},
+};
+static arc arcs_56_2[1] = {
+    {102, 1},
+};
+static arc arcs_56_3[2] = {
+    {121, 1},
+    {0, 3},
+};
+static state states_56[4] = {
+    {10, arcs_56_0},
+    {1, arcs_56_1},
+    {1, arcs_56_2},
+    {2, arcs_56_3},
+};
+static arc arcs_57_0[1] = {
+    {34, 1},
+};
+static arc arcs_57_1[1] = {
+    {108, 2},
+};
+static arc arcs_57_2[1] = {
+    {0, 2},
+};
+static state states_57[3] = {
+    {1, arcs_57_0},
+    {1, arcs_57_1},
+    {1, arcs_57_2},
+};
+static arc arcs_58_0[1] = {
+    {132, 1},
+};
+static arc arcs_58_1[2] = {
+    {133, 0},
+    {0, 1},
+};
+static state states_58[2] = {
+    {1, arcs_58_0},
+    {2, arcs_58_1},
+};
+static arc arcs_59_0[1] = {
+    {134, 1},
+};
+static arc arcs_59_1[2] = {
+    {135, 0},
+    {0, 1},
+};
+static state states_59[2] = {
+    {1, arcs_59_0},
+    {2, arcs_59_1},
+};
+static arc arcs_60_0[1] = {
+    {136, 1},
+};
+static arc arcs_60_1[2] = {
+    {137, 0},
+    {0, 1},
+};
+static state states_60[2] = {
+    {1, arcs_60_0},
+    {2, arcs_60_1},
+};
+static arc arcs_61_0[1] = {
+    {138, 1},
+};
+static arc arcs_61_1[3] = {
+    {139, 0},
+    {140, 0},
+    {0, 1},
+};
+static state states_61[2] = {
+    {1, arcs_61_0},
+    {3, arcs_61_1},
+};
+static arc arcs_62_0[1] = {
+    {141, 1},
+};
+static arc arcs_62_1[3] = {
+    {142, 0},
+    {143, 0},
+    {0, 1},
+};
+static state states_62[2] = {
+    {1, arcs_62_0},
+    {3, arcs_62_1},
+};
+static arc arcs_63_0[1] = {
+    {144, 1},
+};
+static arc arcs_63_1[6] = {
+    {34, 0},
+    {11, 0},
+    {145, 0},
+    {146, 0},
+    {147, 0},
+    {0, 1},
+};
+static state states_63[2] = {
+    {1, arcs_63_0},
+    {6, arcs_63_1},
+};
+static arc arcs_64_0[4] = {
+    {142, 1},
+    {143, 1},
+    {148, 1},
+    {149, 2},
+};
+static arc arcs_64_1[1] = {
+    {144, 2},
+};
+static arc arcs_64_2[1] = {
+    {0, 2},
+};
+static state states_64[3] = {
+    {4, arcs_64_0},
+    {1, arcs_64_1},
+    {1, arcs_64_2},
+};
+static arc arcs_65_0[1] = {
+    {150, 1},
+};
+static arc arcs_65_1[2] = {
+    {35, 2},
+    {0, 1},
+};
+static arc arcs_65_2[1] = {
+    {144, 3},
+};
+static arc arcs_65_3[1] = {
+    {0, 3},
+};
+static state states_65[4] = {
+    {1, arcs_65_0},
+    {2, arcs_65_1},
+    {1, arcs_65_2},
+    {1, arcs_65_3},
+};
+static arc arcs_66_0[2] = {
+    {151, 1},
+    {152, 2},
+};
+static arc arcs_66_1[1] = {
+    {152, 2},
+};
+static arc arcs_66_2[2] = {
+    {153, 2},
+    {0, 2},
+};
+static state states_66[3] = {
+    {2, arcs_66_0},
+    {1, arcs_66_1},
+    {2, arcs_66_2},
+};
+static arc arcs_67_0[10] = {
+    {13, 1},
+    {155, 2},
+    {157, 3},
+    {23, 4},
+    {160, 4},
+    {161, 5},
+    {83, 4},
+    {162, 4},
+    {163, 4},
+    {164, 4},
+};
+static arc arcs_67_1[3] = {
+    {50, 6},
+    {154, 6},
+    {15, 4},
+};
+static arc arcs_67_2[2] = {
+    {154, 7},
+    {156, 4},
+};
+static arc arcs_67_3[2] = {
+    {158, 8},
+    {159, 4},
+};
+static arc arcs_67_4[1] = {
+    {0, 4},
+};
+static arc arcs_67_5[2] = {
+    {161, 5},
+    {0, 5},
+};
+static arc arcs_67_6[1] = {
+    {15, 4},
+};
+static arc arcs_67_7[1] = {
+    {156, 4},
+};
+static arc arcs_67_8[1] = {
+    {159, 4},
+};
+static state states_67[9] = {
+    {10, arcs_67_0},
+    {3, arcs_67_1},
+    {2, arcs_67_2},
+    {2, arcs_67_3},
+    {1, arcs_67_4},
+    {2, arcs_67_5},
+    {1, arcs_67_6},
+    {1, arcs_67_7},
+    {1, arcs_67_8},
+};
+static arc arcs_68_0[2] = {
+    {26, 1},
+    {51, 1},
+};
+static arc arcs_68_1[3] = {
+    {165, 2},
+    {33, 3},
+    {0, 1},
+};
+static arc arcs_68_2[1] = {
+    {0, 2},
+};
+static arc arcs_68_3[3] = {
+    {26, 4},
+    {51, 4},
+    {0, 3},
+};
+static arc arcs_68_4[2] = {
+    {33, 3},
+    {0, 4},
+};
+static state states_68[5] = {
+    {2, arcs_68_0},
+    {3, arcs_68_1},
+    {1, arcs_68_2},
+    {3, arcs_68_3},
+    {2, arcs_68_4},
+};
+static arc arcs_69_0[3] = {
+    {13, 1},
+    {155, 2},
+    {82, 3},
+};
+static arc arcs_69_1[2] = {
+    {14, 4},
+    {15, 5},
+};
+static arc arcs_69_2[1] = {
+    {166, 6},
+};
+static arc arcs_69_3[1] = {
+    {23, 5},
+};
+static arc arcs_69_4[1] = {
+    {15, 5},
+};
+static arc arcs_69_5[1] = {
+    {0, 5},
+};
+static arc arcs_69_6[1] = {
+    {156, 5},
+};
+static state states_69[7] = {
+    {3, arcs_69_0},
+    {2, arcs_69_1},
+    {1, arcs_69_2},
+    {1, arcs_69_3},
+    {1, arcs_69_4},
+    {1, arcs_69_5},
+    {1, arcs_69_6},
+};
+static arc arcs_70_0[1] = {
+    {167, 1},
+};
+static arc arcs_70_1[2] = {
+    {33, 2},
+    {0, 1},
+};
+static arc arcs_70_2[2] = {
+    {167, 1},
+    {0, 2},
+};
+static state states_70[3] = {
+    {1, arcs_70_0},
+    {2, arcs_70_1},
+    {2, arcs_70_2},
+};
+static arc arcs_71_0[2] = {
+    {26, 1},
+    {27, 2},
+};
+static arc arcs_71_1[2] = {
+    {27, 2},
+    {0, 1},
+};
+static arc arcs_71_2[3] = {
+    {26, 3},
+    {168, 4},
+    {0, 2},
+};
+static arc arcs_71_3[2] = {
+    {168, 4},
+    {0, 3},
+};
+static arc arcs_71_4[1] = {
+    {0, 4},
+};
+static state states_71[5] = {
+    {2, arcs_71_0},
+    {2, arcs_71_1},
+    {3, arcs_71_2},
+    {2, arcs_71_3},
+    {1, arcs_71_4},
+};
+static arc arcs_72_0[1] = {
+    {27, 1},
+};
+static arc arcs_72_1[2] = {
+    {26, 2},
+    {0, 1},
+};
+static arc arcs_72_2[1] = {
+    {0, 2},
+};
+static state states_72[3] = {
+    {1, arcs_72_0},
+    {2, arcs_72_1},
+    {1, arcs_72_2},
+};
+static arc arcs_73_0[2] = {
+    {108, 1},
+    {51, 1},
+};
+static arc arcs_73_1[2] = {
+    {33, 2},
+    {0, 1},
+};
+static arc arcs_73_2[3] = {
+    {108, 1},
+    {51, 1},
+    {0, 2},
+};
+static state states_73[3] = {
+    {2, arcs_73_0},
+    {2, arcs_73_1},
+    {3, arcs_73_2},
+};
+static arc arcs_74_0[1] = {
+    {26, 1},
+};
+static arc arcs_74_1[2] = {
+    {33, 2},
+    {0, 1},
+};
+static arc arcs_74_2[2] = {
+    {26, 1},
+    {0, 2},
+};
+static state states_74[3] = {
+    {1, arcs_74_0},
+    {2, arcs_74_1},
+    {2, arcs_74_2},
+};
+static arc arcs_75_0[3] = {
+    {26, 1},
+    {35, 2},
+    {51, 3},
+};
+static arc arcs_75_1[4] = {
+    {27, 4},
+    {165, 5},
+    {33, 6},
+    {0, 1},
+};
+static arc arcs_75_2[1] = {
+    {108, 7},
+};
+static arc arcs_75_3[3] = {
+    {165, 5},
+    {33, 6},
+    {0, 3},
+};
+static arc arcs_75_4[1] = {
+    {26, 7},
+};
+static arc arcs_75_5[1] = {
+    {0, 5},
+};
+static arc arcs_75_6[3] = {
+    {26, 8},
+    {51, 8},
+    {0, 6},
+};
+static arc arcs_75_7[3] = {
+    {165, 5},
+    {33, 9},
+    {0, 7},
+};
+static arc arcs_75_8[2] = {
+    {33, 6},
+    {0, 8},
+};
+static arc arcs_75_9[3] = {
+    {26, 10},
+    {35, 11},
+    {0, 9},
+};
+static arc arcs_75_10[1] = {
+    {27, 12},
+};
+static arc arcs_75_11[1] = {
+    {108, 13},
+};
+static arc arcs_75_12[1] = {
+    {26, 13},
+};
+static arc arcs_75_13[2] = {
+    {33, 9},
+    {0, 13},
+};
+static state states_75[14] = {
+    {3, arcs_75_0},
+    {4, arcs_75_1},
+    {1, arcs_75_2},
+    {3, arcs_75_3},
+    {1, arcs_75_4},
+    {1, arcs_75_5},
+    {3, arcs_75_6},
+    {3, arcs_75_7},
+    {2, arcs_75_8},
+    {3, arcs_75_9},
+    {1, arcs_75_10},
+    {1, arcs_75_11},
+    {1, arcs_75_12},
+    {2, arcs_75_13},
+};
+static arc arcs_76_0[1] = {
+    {169, 1},
+};
+static arc arcs_76_1[1] = {
+    {23, 2},
+};
+static arc arcs_76_2[2] = {
+    {13, 3},
+    {27, 4},
+};
+static arc arcs_76_3[2] = {
+    {14, 5},
+    {15, 6},
+};
+static arc arcs_76_4[1] = {
+    {29, 7},
+};
+static arc arcs_76_5[1] = {
+    {15, 6},
+};
+static arc arcs_76_6[1] = {
+    {27, 4},
+};
+static arc arcs_76_7[1] = {
+    {0, 7},
+};
+static state states_76[8] = {
+    {1, arcs_76_0},
+    {1, arcs_76_1},
+    {2, arcs_76_2},
+    {2, arcs_76_3},
+    {1, arcs_76_4},
+    {1, arcs_76_5},
+    {1, arcs_76_6},
+    {1, arcs_76_7},
+};
+static arc arcs_77_0[1] = {
+    {170, 1},
+};
+static arc arcs_77_1[2] = {
+    {33, 2},
+    {0, 1},
+};
+static arc arcs_77_2[2] = {
+    {170, 1},
+    {0, 2},
+};
+static state states_77[3] = {
+    {1, arcs_77_0},
+    {2, arcs_77_1},
+    {2, arcs_77_2},
+};
+static arc arcs_78_0[3] = {
+    {26, 1},
+    {35, 2},
+    {34, 2},
+};
+static arc arcs_78_1[3] = {
+    {165, 3},
+    {32, 2},
+    {0, 1},
+};
+static arc arcs_78_2[1] = {
+    {26, 3},
+};
+static arc arcs_78_3[1] = {
+    {0, 3},
+};
+static state states_78[4] = {
+    {3, arcs_78_0},
+    {3, arcs_78_1},
+    {1, arcs_78_2},
+    {1, arcs_78_3},
+};
+static arc arcs_79_0[2] = {
+    {165, 1},
+    {172, 1},
+};
+static arc arcs_79_1[1] = {
+    {0, 1},
+};
+static state states_79[2] = {
+    {2, arcs_79_0},
+    {1, arcs_79_1},
+};
+static arc arcs_80_0[1] = {
+    {101, 1},
+};
+static arc arcs_80_1[1] = {
+    {66, 2},
+};
+static arc arcs_80_2[1] = {
+    {102, 3},
+};
+static arc arcs_80_3[1] = {
+    {112, 4},
+};
+static arc arcs_80_4[2] = {
+    {171, 5},
+    {0, 4},
+};
+static arc arcs_80_5[1] = {
+    {0, 5},
+};
+static state states_80[6] = {
+    {1, arcs_80_0},
+    {1, arcs_80_1},
+    {1, arcs_80_2},
+    {1, arcs_80_3},
+    {2, arcs_80_4},
+    {1, arcs_80_5},
+};
+static arc arcs_81_0[1] = {
+    {97, 1},
+};
+static arc arcs_81_1[1] = {
+    {114, 2},
+};
+static arc arcs_81_2[2] = {
+    {171, 3},
+    {0, 2},
+};
+static arc arcs_81_3[1] = {
+    {0, 3},
+};
+static state states_81[4] = {
+    {1, arcs_81_0},
+    {1, arcs_81_1},
+    {2, arcs_81_2},
+    {1, arcs_81_3},
+};
+static arc arcs_82_0[1] = {
+    {23, 1},
+};
+static arc arcs_82_1[1] = {
+    {0, 1},
+};
+static state states_82[2] = {
+    {1, arcs_82_0},
+    {1, arcs_82_1},
+};
+static arc arcs_83_0[1] = {
+    {174, 1},
+};
+static arc arcs_83_1[2] = {
+    {175, 2},
+    {0, 1},
+};
+static arc arcs_83_2[1] = {
+    {0, 2},
+};
+static state states_83[3] = {
+    {1, arcs_83_0},
+    {2, arcs_83_1},
+    {1, arcs_83_2},
+};
+static arc arcs_84_0[2] = {
+    {77, 1},
+    {9, 2},
+};
+static arc arcs_84_1[1] = {
+    {26, 2},
+};
+static arc arcs_84_2[1] = {
+    {0, 2},
+};
+static state states_84[3] = {
+    {2, arcs_84_0},
+    {1, arcs_84_1},
+    {1, arcs_84_2},
+};
+static arc arcs_85_0[1] = {
+    {177, 1},
+};
+static arc arcs_85_1[2] = {
+    {2, 1},
+    {7, 2},
+};
+static arc arcs_85_2[1] = {
+    {0, 2},
+};
+static state states_85[3] = {
+    {1, arcs_85_0},
+    {2, arcs_85_1},
+    {1, arcs_85_2},
+};
+static arc arcs_86_0[1] = {
+    {13, 1},
+};
+static arc arcs_86_1[2] = {
+    {178, 2},
+    {15, 3},
+};
+static arc arcs_86_2[1] = {
+    {15, 3},
+};
+static arc arcs_86_3[1] = {
+    {25, 4},
+};
+static arc arcs_86_4[1] = {
+    {26, 5},
+};
+static arc arcs_86_5[1] = {
+    {0, 5},
+};
+static state states_86[6] = {
+    {1, arcs_86_0},
+    {2, arcs_86_1},
+    {1, arcs_86_2},
+    {1, arcs_86_3},
+    {1, arcs_86_4},
+    {1, arcs_86_5},
+};
+static arc arcs_87_0[3] = {
+    {26, 1},
+    {34, 2},
+    {35, 3},
+};
+static arc arcs_87_1[2] = {
+    {33, 4},
+    {0, 1},
+};
+static arc arcs_87_2[3] = {
+    {26, 5},
+    {33, 6},
+    {0, 2},
+};
+static arc arcs_87_3[1] = {
+    {26, 7},
+};
+static arc arcs_87_4[4] = {
+    {26, 1},
+    {34, 8},
+    {35, 3},
+    {0, 4},
+};
+static arc arcs_87_5[2] = {
+    {33, 6},
+    {0, 5},
+};
+static arc arcs_87_6[2] = {
+    {26, 5},
+    {35, 3},
+};
+static arc arcs_87_7[1] = {
+    {0, 7},
+};
+static arc arcs_87_8[3] = {
+    {26, 9},
+    {33, 10},
+    {0, 8},
+};
+static arc arcs_87_9[2] = {
+    {33, 10},
+    {0, 9},
+};
+static arc arcs_87_10[2] = {
+    {26, 9},
+    {35, 3},
+};
+static state states_87[11] = {
+    {3, arcs_87_0},
+    {2, arcs_87_1},
+    {3, arcs_87_2},
+    {1, arcs_87_3},
+    {4, arcs_87_4},
+    {2, arcs_87_5},
+    {2, arcs_87_6},
+    {1, arcs_87_7},
+    {3, arcs_87_8},
+    {2, arcs_87_9},
+    {2, arcs_87_10},
+};
+static dfa dfas[88] = {
+    {256, "single_input", 0, 3, states_0,
+     "\004\050\340\000\004\000\000\000\012\076\011\007\262\004\020\002\000\300\220\050\037\102\000"},
+    {257, "file_input", 0, 2, states_1,
+     "\204\050\340\000\004\000\000\000\012\076\011\007\262\004\020\002\000\300\220\050\037\102\000"},
+    {258, "eval_input", 0, 3, states_2,
+     "\000\040\200\000\000\000\000\000\000\000\010\000\000\000\020\002\000\300\220\050\037\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\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\000\000"},
+    {261, "decorated", 0, 3, states_5,
+     "\000\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
+    {262, "async_funcdef", 0, 3, states_6,
+     "\000\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
+    {263, "funcdef", 0, 9, states_7,
+     "\000\000\100\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
+    {264, "parameters", 0, 4, states_8,
+     "\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
+    {265, "typedargslist", 0, 22, states_9,
+     "\000\000\200\000\014\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
+    {266, "tfpdef", 0, 4, states_10,
+     "\000\000\200\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
+    {267, "varargslist", 0, 18, states_11,
+     "\000\000\200\000\014\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
+    {268, "vfpdef", 0, 2, states_12,
+     "\000\000\200\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
+    {269, "stmt", 0, 2, states_13,
+     "\000\050\340\000\004\000\000\000\012\076\011\007\262\004\020\002\000\300\220\050\037\102\000"},
+    {270, "simple_stmt", 0, 4, states_14,
+     "\000\040\200\000\004\000\000\000\012\076\011\007\000\000\020\002\000\300\220\050\037\100\000"},
+    {271, "small_stmt", 0, 2, states_15,
+     "\000\040\200\000\004\000\000\000\012\076\011\007\000\000\020\002\000\300\220\050\037\100\000"},
+    {272, "expr_stmt", 0, 6, states_16,
+     "\000\040\200\000\004\000\000\000\000\000\010\000\000\000\020\002\000\300\220\050\037\000\000"},
+    {273, "testlist_star_expr", 0, 3, states_17,
+     "\000\040\200\000\004\000\000\000\000\000\010\000\000\000\020\002\000\300\220\050\037\000\000"},
+    {274, "augassign", 0, 2, states_18,
+     "\000\000\000\000\000\000\360\377\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
+    {275, "del_stmt", 0, 3, 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"},
+    {276, "pass_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\000\000"},
+    {277, "flow_stmt", 0, 2, states_21,
+     "\000\000\000\000\000\000\000\000\000\036\000\000\000\000\000\000\000\000\000\000\000\100\000"},
+    {278, "break_stmt", 0, 2, states_22,
+     "\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000"},
+    {279, "continue_stmt", 0, 2, states_23,
+     "\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000"},
+    {280, "return_stmt", 0, 3, states_24,
+     "\000\000\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\000\000\000\000\000\000"},
+    {281, "yield_stmt", 0, 2, states_25,
+     "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\100\000"},
+    {282, "raise_stmt", 0, 5, states_26,
+     "\000\000\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\000\000\000\000\000\000"},
+    {283, "import_stmt", 0, 2, states_27,
+     "\000\000\000\000\000\000\000\000\000\040\001\000\000\000\000\000\000\000\000\000\000\000\000"},
+    {284, "import_name", 0, 3, states_28,
+     "\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000"},
+    {285, "import_from", 0, 8, states_29,
+     "\000\000\000\000\000\000\000\000\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000"},
+    {286, "import_as_name", 0, 4, states_30,
+     "\000\000\200\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
+    {287, "dotted_as_name", 0, 4, states_31,
+     "\000\000\200\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
+    {288, "import_as_names", 0, 3, states_32,
+     "\000\000\200\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
+    {289, "dotted_as_names", 0, 2, states_33,
+     "\000\000\200\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
+    {290, "dotted_name", 0, 2, states_34,
+     "\000\000\200\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
+    {291, "global_stmt", 0, 3, states_35,
+     "\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000"},
+    {292, "nonlocal_stmt", 0, 3, 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"},
+    {293, "assert_stmt", 0, 5, states_37,
+     "\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000"},
+    {294, "compound_stmt", 0, 2, states_38,
+     "\000\010\140\000\000\000\000\000\000\000\000\000\262\004\000\000\000\000\000\000\000\002\000"},
+    {295, "async_stmt", 0, 3, states_39,
+     "\000\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
+    {296, "if_stmt", 0, 8, 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"},
+    {297, "while_stmt", 0, 8, states_41,
+     "\000\000\000\000\000\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\000\000\000"},
+    {298, "for_stmt", 0, 11, states_42,
+     "\000\000\000\000\000\000\000\000\000\000\000\000\040\000\000\000\000\000\000\000\000\000\000"},
+    {299, "try_stmt", 0, 13, states_43,
+     "\000\000\000\000\000\000\000\000\000\000\000\000\200\000\000\000\000\000\000\000\000\000\000"},
+    {300, "with_stmt", 0, 6, states_44,
+     "\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000"},
+    {301, "with_item", 0, 4, states_45,
+     "\000\040\200\000\000\000\000\000\000\000\010\000\000\000\020\002\000\300\220\050\037\000\000"},
+    {302, "except_clause", 0, 5, states_46,
+     "\000\000\000\000\000\000\000\000\000\000\000\000\000\040\000\000\000\000\000\000\000\000\000"},
+    {303, "suite", 0, 7, states_47,
+     "\004\040\200\000\004\000\000\000\012\076\011\007\000\000\020\002\000\300\220\050\037\100\000"},
+    {304, "test", 0, 6, states_48,
+     "\000\040\200\000\000\000\000\000\000\000\010\000\000\000\020\002\000\300\220\050\037\000\000"},
+    {305, "test_nocond", 0, 2, states_49,
+     "\000\040\200\000\000\000\000\000\000\000\010\000\000\000\020\002\000\300\220\050\037\000\000"},
+    {306, "lambdef", 0, 5, states_50,
+     "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\000"},
+    {307, "lambdef_nocond", 0, 5, states_51,
+     "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\000"},
+    {308, "or_test", 0, 2, states_52,
+     "\000\040\200\000\000\000\000\000\000\000\010\000\000\000\000\002\000\300\220\050\037\000\000"},
+    {309, "and_test", 0, 2, states_53,
+     "\000\040\200\000\000\000\000\000\000\000\010\000\000\000\000\002\000\300\220\050\037\000\000"},
+    {310, "not_test", 0, 3, states_54,
+     "\000\040\200\000\000\000\000\000\000\000\010\000\000\000\000\002\000\300\220\050\037\000\000"},
+    {311, "comparison", 0, 2, states_55,
+     "\000\040\200\000\000\000\000\000\000\000\010\000\000\000\000\000\000\300\220\050\037\000\000"},
+    {312, "comp_op", 0, 4, states_56,
+     "\000\000\000\000\000\000\000\000\000\000\000\000\100\000\000\362\017\000\000\000\000\000\000"},
+    {313, "star_expr", 0, 3, states_57,
+     "\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
+    {314, "expr", 0, 2, states_58,
+     "\000\040\200\000\000\000\000\000\000\000\010\000\000\000\000\000\000\300\220\050\037\000\000"},
+    {315, "xor_expr", 0, 2, states_59,
+     "\000\040\200\000\000\000\000\000\000\000\010\000\000\000\000\000\000\300\220\050\037\000\000"},
+    {316, "and_expr", 0, 2, states_60,
+     "\000\040\200\000\000\000\000\000\000\000\010\000\000\000\000\000\000\300\220\050\037\000\000"},
+    {317, "shift_expr", 0, 2, states_61,
+     "\000\040\200\000\000\000\000\000\000\000\010\000\000\000\000\000\000\300\220\050\037\000\000"},
+    {318, "arith_expr", 0, 2, states_62,
+     "\000\040\200\000\000\000\000\000\000\000\010\000\000\000\000\000\000\300\220\050\037\000\000"},
+    {319, "term", 0, 2, states_63,
+     "\000\040\200\000\000\000\000\000\000\000\010\000\000\000\000\000\000\300\220\050\037\000\000"},
+    {320, "factor", 0, 3, states_64,
+     "\000\040\200\000\000\000\000\000\000\000\010\000\000\000\000\000\000\300\220\050\037\000\000"},
+    {321, "power", 0, 4, states_65,
+     "\000\040\200\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\200\050\037\000\000"},
+    {322, "atom_expr", 0, 3, states_66,
+     "\000\040\200\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\200\050\037\000\000"},
+    {323, "atom", 0, 9, states_67,
+     "\000\040\200\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\000\050\037\000\000"},
+    {324, "testlist_comp", 0, 5, states_68,
+     "\000\040\200\000\004\000\000\000\000\000\010\000\000\000\020\002\000\300\220\050\037\000\000"},
+    {325, "trailer", 0, 7, states_69,
+     "\000\040\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\010\000\000\000"},
+    {326, "subscriptlist", 0, 3, states_70,
+     "\000\040\200\010\000\000\000\000\000\000\010\000\000\000\020\002\000\300\220\050\037\000\000"},
+    {327, "subscript", 0, 5, states_71,
+     "\000\040\200\010\000\000\000\000\000\000\010\000\000\000\020\002\000\300\220\050\037\000\000"},
+    {328, "sliceop", 0, 3, states_72,
+     "\000\000\000\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
+    {329, "exprlist", 0, 3, states_73,
+     "\000\040\200\000\004\000\000\000\000\000\010\000\000\000\000\000\000\300\220\050\037\000\000"},
+    {330, "testlist", 0, 3, states_74,
+     "\000\040\200\000\000\000\000\000\000\000\010\000\000\000\020\002\000\300\220\050\037\000\000"},
+    {331, "dictorsetmaker", 0, 14, states_75,
+     "\000\040\200\000\014\000\000\000\000\000\010\000\000\000\020\002\000\300\220\050\037\000\000"},
+    {332, "classdef", 0, 8, states_76,
+     "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000"},
+    {333, "arglist", 0, 3, states_77,
+     "\000\040\200\000\014\000\000\000\000\000\010\000\000\000\020\002\000\300\220\050\037\000\000"},
+    {334, "argument", 0, 4, states_78,
+     "\000\040\200\000\014\000\000\000\000\000\010\000\000\000\020\002\000\300\220\050\037\000\000"},
+    {335, "comp_iter", 0, 2, states_79,
+     "\000\000\000\000\000\000\000\000\000\000\000\000\042\000\000\000\000\000\000\000\000\000\000"},
+    {336, "comp_for", 0, 6, states_80,
+     "\000\000\000\000\000\000\000\000\000\000\000\000\040\000\000\000\000\000\000\000\000\000\000"},
+    {337, "comp_if", 0, 4, states_81,
+     "\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000"},
+    {338, "encoding_decl", 0, 2, states_82,
+     "\000\000\200\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
+    {339, "yield_expr", 0, 3, states_83,
+     "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\100\000"},
+    {340, "yield_arg", 0, 3, states_84,
+     "\000\040\200\000\000\000\000\000\000\040\010\000\000\000\020\002\000\300\220\050\037\000\000"},
+    {341, "func_type_input", 0, 3, states_85,
+     "\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
+    {342, "func_type", 0, 6, states_86,
+     "\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
+    {343, "typelist", 0, 11, states_87,
+     "\000\040\200\000\014\000\000\000\000\000\010\000\000\000\020\002\000\300\220\050\037\000\000"},
+};
+static label labels[179] = {
+    {0, "EMPTY"},
+    {256, 0},
+    {4, 0},
+    {270, 0},
+    {294, 0},
+    {257, 0},
+    {269, 0},
+    {0, 0},
+    {258, 0},
+    {330, 0},
+    {259, 0},
+    {49, 0},
+    {290, 0},
+    {7, 0},
+    {333, 0},
+    {8, 0},
+    {260, 0},
+    {261, 0},
+    {332, 0},
+    {263, 0},
+    {262, 0},
+    {55, 0},
+    {1, "def"},
+    {1, 0},
+    {264, 0},
+    {51, 0},
+    {304, 0},
+    {11, 0},
+    {57, 0},
+    {303, 0},
+    {265, 0},
+    {266, 0},
+    {22, 0},
+    {12, 0},
+    {16, 0},
+    {35, 0},
+    {267, 0},
+    {268, 0},
+    {271, 0},
+    {13, 0},
+    {272, 0},
+    {275, 0},
+    {276, 0},
+    {277, 0},
+    {283, 0},
+    {291, 0},
+    {292, 0},
+    {293, 0},
+    {273, 0},
+    {274, 0},
+    {339, 0},
+    {313, 0},
+    {36, 0},
+    {37, 0},
+    {38, 0},
+    {50, 0},
+    {39, 0},
+    {40, 0},
+    {41, 0},
+    {42, 0},
+    {43, 0},
+    {44, 0},
+    {45, 0},
+    {46, 0},
+    {48, 0},
+    {1, "del"},
+    {329, 0},
+    {1, "pass"},
+    {278, 0},
+    {279, 0},
+    {280, 0},
+    {282, 0},
+    {281, 0},
+    {1, "break"},
+    {1, "continue"},
+    {1, "return"},
+    {1, "raise"},
+    {1, "from"},
+    {284, 0},
+    {285, 0},
+    {1, "import"},
+    {289, 0},
+    {23, 0},
+    {52, 0},
+    {288, 0},
+    {286, 0},
+    {1, "as"},
+    {287, 0},
+    {1, "global"},
+    {1, "nonlocal"},
+    {1, "assert"},
+    {296, 0},
+    {297, 0},
+    {298, 0},
+    {299, 0},
+    {300, 0},
+    {295, 0},
+    {1, "if"},
+    {1, "elif"},
+    {1, "else"},
+    {1, "while"},
+    {1, "for"},
+    {1, "in"},
+    {1, "try"},
+    {302, 0},
+    {1, "finally"},
+    {1, "with"},
+    {301, 0},
+    {314, 0},
+    {1, "except"},
+    {5, 0},
+    {6, 0},
+    {308, 0},
+    {306, 0},
+    {305, 0},
+    {307, 0},
+    {1, "lambda"},
+    {309, 0},
+    {1, "or"},
+    {310, 0},
+    {1, "and"},
+    {1, "not"},
+    {311, 0},
+    {312, 0},
+    {20, 0},
+    {21, 0},
+    {27, 0},
+    {30, 0},
+    {29, 0},
+    {28, 0},
+    {28, 0},
+    {1, "is"},
+    {315, 0},
+    {18, 0},
+    {316, 0},
+    {32, 0},
+    {317, 0},
+    {19, 0},
+    {318, 0},
+    {33, 0},
+    {34, 0},
+    {319, 0},
+    {14, 0},
+    {15, 0},
+    {320, 0},
+    {17, 0},
+    {24, 0},
+    {47, 0},
+    {31, 0},
+    {321, 0},
+    {322, 0},
+    {54, 0},
+    {323, 0},
+    {325, 0},
+    {324, 0},
+    {9, 0},
+    {10, 0},
+    {25, 0},
+    {331, 0},
+    {26, 0},
+    {2, 0},
+    {3, 0},
+    {1, "None"},
+    {1, "True"},
+    {1, "False"},
+    {336, 0},
+    {326, 0},
+    {327, 0},
+    {328, 0},
+    {1, "class"},
+    {334, 0},
+    {335, 0},
+    {337, 0},
+    {338, 0},
+    {1, "yield"},
+    {340, 0},
+    {341, 0},
+    {342, 0},
+    {343, 0},
+};
+grammar _Ta35Parser_Grammar = {
+    88,
+    dfas,
+    {179, labels},
+    256
+};
diff --git a/build.cmd b/build.cmd
new file mode 100644
index 0000000..243dc9a
--- /dev/null
+++ b/build.cmd
@@ -0,0 +1,21 @@
+ at echo off
+:: To build extensions for 64 bit Python 3, we need to configure environment
+:: variables to use the MSVC 2010 C++ compilers from GRMSDKX_EN_DVD.iso of:
+:: MS Windows SDK for Windows 7 and .NET Framework 4
+::
+:: More details at:
+:: https://github.com/cython/cython/wiki/64BitCythonExtensionsOnWindows
+
+IF "%DISTUTILS_USE_SDK%"=="1" (
+    ECHO Configuring environment to build with MSVC on a 64bit architecture
+    ECHO Using Windows SDK 7.1
+    "C:\Program Files\Microsoft SDKs\Windows\v7.1\Setup\WindowsSdkVer.exe" -q -version:v7.1
+    CALL "C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\SetEnv.cmd" /x64 /release
+    SET MSSdk=1
+    REM Need the following to allow tox to see the SDK compiler
+    SET TOX_TESTENV_PASSENV=DISTUTILS_USE_SDK MSSdk INCLUDE LIB
+) ELSE (
+    ECHO Using default MSVC build environment
+)
+
+CALL %*
diff --git a/setup.py b/setup.py
new file mode 100644
index 0000000..907cda5
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,100 @@
+try:
+    from setuptools import setup, Extension
+except ImportError:
+    from distutils.core import setup, Extension
+
+_ast27 = Extension(
+    '_ast27',
+    include_dirs = ['ast27/Include'],
+    sources = [
+        'ast27/Parser/acceler.c',
+        'ast27/Parser/bitset.c',
+        'ast27/Parser/grammar.c',
+        'ast27/Parser/grammar1.c',
+        'ast27/Parser/node.c',
+        'ast27/Parser/parser.c',
+        'ast27/Parser/parsetok.c',
+        'ast27/Parser/tokenizer.c',
+        'ast27/Python/ast.c',
+        'ast27/Python/graminit.c',
+        'ast27/Python/mystrtoul.c',
+        'ast27/Python/Python-ast.c',
+        'ast27/Custom/typed_ast.c',
+    ],
+    depends = [
+        'ast27/Include/asdl.h',
+        'ast27/Include/ast.h',
+        'ast27/Include/bitset.h',
+        'ast27/Include/compile.h',
+        'ast27/Include/errcode.h',
+        'ast27/Include/graminit.h',
+        'ast27/Include/grammar.h',
+        'ast27/Include/node.h',
+        'ast27/Include/parsetok.h',
+        'ast27/Include/Python-ast.h',
+        'ast27/Include/token.h',
+        'ast27/Parser/parser.h',
+        'ast27/Parser/tokenizer.h',
+    ])
+
+
+_ast35 = Extension(
+    '_ast35',
+    include_dirs = ['ast35/Include'],
+    sources = [
+        'ast35/Parser/acceler.c',
+        'ast35/Parser/bitset.c',
+        'ast35/Parser/grammar.c',
+        'ast35/Parser/grammar1.c',
+        'ast35/Parser/node.c',
+        'ast35/Parser/parser.c',
+        'ast35/Parser/parsetok.c',
+        'ast35/Parser/tokenizer.c',
+        'ast35/Python/ast.c',
+        'ast35/Python/graminit.c',
+        'ast35/Python/Python-ast.c',
+        'ast35/Custom/typed_ast.c',
+    ],
+    depends = [
+        'ast35/Include/asdl.h',
+        'ast35/Include/ast.h',
+        'ast35/Include/bitset.h',
+        'ast35/Include/compile.h',
+        'ast35/Include/errcode.h',
+        'ast35/Include/graminit.h',
+        'ast35/Include/grammar.h',
+        'ast35/Include/node.h',
+        'ast35/Include/parsetok.h',
+        'ast35/Include/Python-ast.h',
+        'ast35/Include/token.h',
+        'ast35/Parser/parser.h',
+        'ast35/Parser/tokenizer.h',
+    ])
+
+long_description = """
+This package is a fork of the CPython 2.7 and 3.5 `ast` modules with the
+ability to parse PEP 484 (https://www.python.org/dev/peps/pep-0484/) type
+comments.  The primary goals of this package are correctness and speed.
+""".strip()
+
+setup (name = 'typed-ast',
+       version = '0.5.5',
+       description = 'fork of Python 2 and 3 ast modules with type comment support',
+       long_description = long_description,
+       author = 'David Fisher',
+       author_email = 'ddfisher at dropbox.com',
+       url = 'https://github.com/dropbox/typed_ast',
+       license='Apache License 2.0',
+       platforms = ['POSIX'],
+       classifiers = [
+           'Development Status :: 3 - Alpha',
+           'Environment :: Console',
+           'Intended Audience :: Developers',
+           'Operating System :: POSIX',
+           'Programming Language :: Python :: 3.3',
+           'Programming Language :: Python :: 3.4',
+           'Programming Language :: Python :: 3.5',
+           'Topic :: Software Development',
+       ],
+       packages = ['typed_ast'],
+       ext_modules = [_ast27, _ast35])
diff --git a/tools/find_exported_symbols b/tools/find_exported_symbols
new file mode 100755
index 0000000..2fcb6ad
--- /dev/null
+++ b/tools/find_exported_symbols
@@ -0,0 +1,8 @@
+#!/bin/bash
+PROJ_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )/.."
+
+gobjdump -t $PROJ_DIR/build/lib*/_ast${1}.*.so | grep ' g ' | grep -v UND > "exported_symbols${1}.txt"
+echo "Symbols written to exported_symbols${1}.txt.  You should edit this file to "
+echo "remove any symbols you still want to export (like PyInit functions) "
+echo "and to make each line contain only a function name you want updated "
+echo "(and none of the other output) before running update_exported_symbols."
diff --git a/tools/update_exported_symbols b/tools/update_exported_symbols
new file mode 100755
index 0000000..e346b39
--- /dev/null
+++ b/tools/update_exported_symbols
@@ -0,0 +1,13 @@
+#!/bin/bash
+PROJ_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )/.."
+
+for CHANGE in $( cat "$PROJ_DIR/exported_symbols${1}.txt" ); do
+  if [[ ${CHANGE:0:1} == "_" ]] ; then
+    NEW="_Ta${1}${CHANGE:3}"
+  else
+    NEW="Ta${1}${CHANGE:2}"
+  fi
+  find "$PROJ_DIR/ast${1}" -type f -name '*.h' -or -name '*.c' | xargs -n 1 sed -i '' "s/$CHANGE/$NEW/"
+done
+
+echo "Symbols updated.  Remember to also update autogeneration code like Parser/asdl_c.py."
diff --git a/tools/update_header_guards b/tools/update_header_guards
new file mode 100755
index 0000000..24d6c0e
--- /dev/null
+++ b/tools/update_header_guards
@@ -0,0 +1,12 @@
+#!/bin/bash -eux
+
+# usage: ./update_header_guards VERSION_NUMBER
+
+PROJ_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )/.."
+
+# only works on OS X due to silly sed incompatibility
+FOLDER="ast$1"
+PATTERN='s/Py\([A-Z_]*_H\( \*\/\)\{0,1\}\)$/'
+PATTERN+="Ta$1"
+PATTERN+='\1/'
+find "$FOLDER" -type f -name '*.h' | xargs -n 1 sed -i '' "$PATTERN"
diff --git a/typed_ast/__init__.py b/typed_ast/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/typed_ast/ast27.py b/typed_ast/ast27.py
new file mode 100644
index 0000000..a1a15f8
--- /dev/null
+++ b/typed_ast/ast27.py
@@ -0,0 +1,311 @@
+# -*- coding: utf-8 -*-
+"""
+    ast
+    ~~~
+
+    The `ast` module helps Python applications to process trees of the Python
+    abstract syntax grammar.  The abstract syntax itself might change with
+    each Python release; this module helps to find out programmatically what
+    the current grammar looks like and allows modifications of it.
+
+    An abstract syntax tree can be generated by passing `ast.PyCF_ONLY_AST` as
+    a flag to the `compile()` builtin function or by using the `parse()`
+    function from this module.  The result will be a tree of objects whose
+    classes all inherit from `ast.AST`.
+
+    A modified abstract syntax tree can be compiled into a Python code object
+    using the built-in `compile()` function.
+
+    Additionally various helper functions are provided that make working with
+    the trees simpler.  The main intention of the helper functions and this
+    module in general is to provide an easy to use interface for libraries
+    that work tightly with the python syntax (template engines for example).
+
+
+    :copyright: Copyright 2008 by Armin Ronacher.
+    :license: Python License.
+"""
+import _ast27
+from _ast27 import *
+
+
+def parse(source, filename='<unknown>', mode='exec'):
+    """
+    Parse the source into an AST node.
+    Equivalent to compile(source, filename, mode, PyCF_ONLY_AST).
+    """
+    return _ast27.parse(source, filename, mode)
+
+
+def literal_eval(node_or_string):
+    """
+    Safely evaluate an expression node or a string containing a Python
+    expression.  The string or node provided may only consist of the following
+    Python literal structures: strings, numbers, tuples, lists, dicts, booleans,
+    and None.
+    """
+    _safe_names = {'None': None, 'True': True, 'False': False}
+    if isinstance(node_or_string, basestring):
+        node_or_string = parse(node_or_string, mode='eval')
+    if isinstance(node_or_string, Expression):
+        node_or_string = node_or_string.body
+    def _convert(node):
+        if isinstance(node, Str):
+            return node.s
+        elif isinstance(node, Num):
+            return node.n
+        elif isinstance(node, Tuple):
+            return tuple(map(_convert, node.elts))
+        elif isinstance(node, List):
+            return list(map(_convert, node.elts))
+        elif isinstance(node, Dict):
+            return dict((_convert(k), _convert(v)) for k, v
+                        in zip(node.keys, node.values))
+        elif isinstance(node, Name):
+            if node.id in _safe_names:
+                return _safe_names[node.id]
+        elif isinstance(node, BinOp) and \
+             isinstance(node.op, (Add, Sub)) and \
+             isinstance(node.right, Num) and \
+             isinstance(node.right.n, complex) and \
+             isinstance(node.left, Num) and \
+             isinstance(node.left.n, (int, long, float)):
+            left = node.left.n
+            right = node.right.n
+            if isinstance(node.op, Add):
+                return left + right
+            else:
+                return left - right
+        raise ValueError('malformed string')
+    return _convert(node_or_string)
+
+
+def dump(node, annotate_fields=True, include_attributes=False):
+    """
+    Return a formatted dump of the tree in *node*.  This is mainly useful for
+    debugging purposes.  The returned string will show the names and the values
+    for fields.  This makes the code impossible to evaluate, so if evaluation is
+    wanted *annotate_fields* must be set to False.  Attributes such as line
+    numbers and column offsets are not dumped by default.  If this is wanted,
+    *include_attributes* can be set to True.
+    """
+    def _format(node):
+        if isinstance(node, AST):
+            fields = [(a, _format(b)) for a, b in iter_fields(node)]
+            rv = '%s(%s' % (node.__class__.__name__, ', '.join(
+                ('%s=%s' % field for field in fields)
+                if annotate_fields else
+                (b for a, b in fields)
+            ))
+            if include_attributes and node._attributes:
+                rv += fields and ', ' or ' '
+                rv += ', '.join('%s=%s' % (a, _format(getattr(node, a)))
+                                for a in node._attributes)
+            return rv + ')'
+        elif isinstance(node, list):
+            return '[%s]' % ', '.join(_format(x) for x in node)
+        return repr(node)
+    if not isinstance(node, AST):
+        raise TypeError('expected AST, got %r' % node.__class__.__name__)
+    return _format(node)
+
+
+def copy_location(new_node, old_node):
+    """
+    Copy source location (`lineno` and `col_offset` attributes) from
+    *old_node* to *new_node* if possible, and return *new_node*.
+    """
+    for attr in 'lineno', 'col_offset':
+        if attr in old_node._attributes and attr in new_node._attributes \
+           and hasattr(old_node, attr):
+            setattr(new_node, attr, getattr(old_node, attr))
+    return new_node
+
+
+def fix_missing_locations(node):
+    """
+    When you compile a node tree with compile(), the compiler expects lineno and
+    col_offset attributes for every node that supports them.  This is rather
+    tedious to fill in for generated nodes, so this helper adds these attributes
+    recursively where not already set, by setting them to the values of the
+    parent node.  It works recursively starting at *node*.
+    """
+    def _fix(node, lineno, col_offset):
+        if 'lineno' in node._attributes:
+            if not hasattr(node, 'lineno'):
+                node.lineno = lineno
+            else:
+                lineno = node.lineno
+        if 'col_offset' in node._attributes:
+            if not hasattr(node, 'col_offset'):
+                node.col_offset = col_offset
+            else:
+                col_offset = node.col_offset
+        for child in iter_child_nodes(node):
+            _fix(child, lineno, col_offset)
+    _fix(node, 1, 0)
+    return node
+
+
+def increment_lineno(node, n=1):
+    """
+    Increment the line number of each node in the tree starting at *node* by *n*.
+    This is useful to "move code" to a different location in a file.
+    """
+    for child in walk(node):
+        if 'lineno' in child._attributes:
+            child.lineno = getattr(child, 'lineno', 0) + n
+    return node
+
+
+def iter_fields(node):
+    """
+    Yield a tuple of ``(fieldname, value)`` for each field in ``node._fields``
+    that is present on *node*.
+    """
+    for field in node._fields:
+        try:
+            yield field, getattr(node, field)
+        except AttributeError:
+            pass
+
+
+def iter_child_nodes(node):
+    """
+    Yield all direct child nodes of *node*, that is, all fields that are nodes
+    and all items of fields that are lists of nodes.
+    """
+    for name, field in iter_fields(node):
+        if isinstance(field, AST):
+            yield field
+        elif isinstance(field, list):
+            for item in field:
+                if isinstance(item, AST):
+                    yield item
+
+
+def get_docstring(node, clean=True):
+    """
+    Return the docstring for the given node or None if no docstring can
+    be found.  If the node provided does not have docstrings a TypeError
+    will be raised.
+    """
+    if not isinstance(node, (FunctionDef, ClassDef, Module)):
+        raise TypeError("%r can't have docstrings" % node.__class__.__name__)
+    if node.body and isinstance(node.body[0], Expr) and \
+       isinstance(node.body[0].value, Str):
+        if clean:
+            import inspect
+            return inspect.cleandoc(node.body[0].value.s)
+        return node.body[0].value.s
+
+
+def walk(node):
+    """
+    Recursively yield all descendant nodes in the tree starting at *node*
+    (including *node* itself), in no specified order.  This is useful if you
+    only want to modify nodes in place and don't care about the context.
+    """
+    from collections import deque
+    todo = deque([node])
+    while todo:
+        node = todo.popleft()
+        todo.extend(iter_child_nodes(node))
+        yield node
+
+
+class NodeVisitor(object):
+    """
+    A node visitor base class that walks the abstract syntax tree and calls a
+    visitor function for every node found.  This function may return a value
+    which is forwarded by the `visit` method.
+
+    This class is meant to be subclassed, with the subclass adding visitor
+    methods.
+
+    Per default the visitor functions for the nodes are ``'visit_'`` +
+    class name of the node.  So a `TryFinally` node visit function would
+    be `visit_TryFinally`.  This behavior can be changed by overriding
+    the `visit` method.  If no visitor function exists for a node
+    (return value `None`) the `generic_visit` visitor is used instead.
+
+    Don't use the `NodeVisitor` if you want to apply changes to nodes during
+    traversing.  For this a special visitor exists (`NodeTransformer`) that
+    allows modifications.
+    """
+
+    def visit(self, node):
+        """Visit a node."""
+        method = 'visit_' + node.__class__.__name__
+        visitor = getattr(self, method, self.generic_visit)
+        return visitor(node)
+
+    def generic_visit(self, node):
+        """Called if no explicit visitor function exists for a node."""
+        for field, value in iter_fields(node):
+            if isinstance(value, list):
+                for item in value:
+                    if isinstance(item, AST):
+                        self.visit(item)
+            elif isinstance(value, AST):
+                self.visit(value)
+
+
+class NodeTransformer(NodeVisitor):
+    """
+    A :class:`NodeVisitor` subclass that walks the abstract syntax tree and
+    allows modification of nodes.
+
+    The `NodeTransformer` will walk the AST and use the return value of the
+    visitor methods to replace or remove the old node.  If the return value of
+    the visitor method is ``None``, the node will be removed from its location,
+    otherwise it is replaced with the return value.  The return value may be the
+    original node in which case no replacement takes place.
+
+    Here is an example transformer that rewrites all occurrences of name lookups
+    (``foo``) to ``data['foo']``::
+
+       class RewriteName(NodeTransformer):
+
+           def visit_Name(self, node):
+               return copy_location(Subscript(
+                   value=Name(id='data', ctx=Load()),
+                   slice=Index(value=Str(s=node.id)),
+                   ctx=node.ctx
+               ), node)
+
+    Keep in mind that if the node you're operating on has child nodes you must
+    either transform the child nodes yourself or call the :meth:`generic_visit`
+    method for the node first.
+
+    For nodes that were part of a collection of statements (that applies to all
+    statement nodes), the visitor may also return a list of nodes rather than
+    just a single node.
+
+    Usually you use the transformer like this::
+
+       node = YourTransformer().visit(node)
+    """
+
+    def generic_visit(self, node):
+        for field, old_value in iter_fields(node):
+            old_value = getattr(node, field, None)
+            if isinstance(old_value, list):
+                new_values = []
+                for value in old_value:
+                    if isinstance(value, AST):
+                        value = self.visit(value)
+                        if value is None:
+                            continue
+                        elif not isinstance(value, AST):
+                            new_values.extend(value)
+                            continue
+                    new_values.append(value)
+                old_value[:] = new_values
+            elif isinstance(old_value, AST):
+                new_node = self.visit(old_value)
+                if new_node is None:
+                    delattr(node, field)
+                else:
+                    setattr(node, field, new_node)
+        return node
diff --git a/typed_ast/ast35.py b/typed_ast/ast35.py
new file mode 100644
index 0000000..0865a2d
--- /dev/null
+++ b/typed_ast/ast35.py
@@ -0,0 +1,325 @@
+"""
+    typed_ast.ast35
+    ~~~
+
+    The `ast35` module helps Python applications to process trees of the
+    Python abstract syntax grammar.  The abstract syntax itself might change
+    with each Python release; this module helps to find out programmatically
+    what the current grammar looks like and allows modifications of it.  The
+    difference between the `ast35` module and the builtin `ast` module is
+    that `ast35` provides PEP 484 type comment information as part of the
+    AST.
+
+    In particular:
+    - The `FunctionDef`, `Assign`, `For`, and `With` classes all have a
+      `type_comment` field which contains a `str` with the text of the type
+      comment.
+    - Per-argument function comments are put into the annotation field of each
+      argument.
+    - `parse` has been augmented so it can parse function signature types when
+      called with `mode=func_type`.
+    - `Module` has a `type_ignores` field which contains a list of
+      lines which have been `# type: ignore`d.
+
+    An abstract syntax tree can be generated by using the `parse()`
+    function from this module.  The result will be a tree of objects whose
+    classes all inherit from `ast35.AST`.
+
+    Additionally various helper functions are provided that make working with
+    the trees simpler.  The main intention of the helper functions and this
+    module in general is to provide an easy to use interface for libraries
+    that work tightly with the python syntax (template engines for example).
+
+
+    :copyright: Copyright 2008 by Armin Ronacher.
+    :license: Python License.
+"""
+import _ast35
+from _ast35 import *
+
+
+def parse(source, filename='<unknown>', mode='exec'):
+    """
+    Parse the source into an AST node including type comment information.
+    Similar to compile(source, filename, mode, PyCF_ONLY_AST).
+    """
+    return _ast35._parse(source, filename, mode)
+
+
+def literal_eval(node_or_string):
+    """
+    Safely evaluate an expression node or a string containing a Python
+    expression.  The string or node provided may only consist of the following
+    Python literal structures: strings, bytes, numbers, tuples, lists, dicts,
+    sets, booleans, and None.
+    """
+    if isinstance(node_or_string, str):
+        node_or_string = parse(node_or_string, mode='eval')
+    if isinstance(node_or_string, Expression):
+        node_or_string = node_or_string.body
+    def _convert(node):
+        if isinstance(node, (Str, Bytes)):
+            return node.s
+        elif isinstance(node, Num):
+            return node.n
+        elif isinstance(node, Tuple):
+            return tuple(map(_convert, node.elts))
+        elif isinstance(node, List):
+            return list(map(_convert, node.elts))
+        elif isinstance(node, Set):
+            return set(map(_convert, node.elts))
+        elif isinstance(node, Dict):
+            return dict((_convert(k), _convert(v)) for k, v
+                        in zip(node.keys, node.values))
+        elif isinstance(node, NameConstant):
+            return node.value
+        elif isinstance(node, UnaryOp) and \
+             isinstance(node.op, (UAdd, USub)) and \
+             isinstance(node.operand, (Num, UnaryOp, BinOp)):
+            operand = _convert(node.operand)
+            if isinstance(node.op, UAdd):
+                return + operand
+            else:
+                return - operand
+        elif isinstance(node, BinOp) and \
+             isinstance(node.op, (Add, Sub)) and \
+             isinstance(node.right, (Num, UnaryOp, BinOp)) and \
+             isinstance(node.left, (Num, UnaryOp, BinOp)):
+            left = _convert(node.left)
+            right = _convert(node.right)
+            if isinstance(node.op, Add):
+                return left + right
+            else:
+                return left - right
+        raise ValueError('malformed node or string: ' + repr(node))
+    return _convert(node_or_string)
+
+
+def dump(node, annotate_fields=True, include_attributes=False):
+    """
+    Return a formatted dump of the tree in *node*.  This is mainly useful for
+    debugging purposes.  The returned string will show the names and the values
+    for fields.  This makes the code impossible to evaluate, so if evaluation is
+    wanted *annotate_fields* must be set to False.  Attributes such as line
+    numbers and column offsets are not dumped by default.  If this is wanted,
+    *include_attributes* can be set to True.
+    """
+    def _format(node):
+        if isinstance(node, AST):
+            fields = [(a, _format(b)) for a, b in iter_fields(node)]
+            rv = '%s(%s' % (node.__class__.__name__, ', '.join(
+                ('%s=%s' % field for field in fields)
+                if annotate_fields else
+                (b for a, b in fields)
+            ))
+            if include_attributes and node._attributes:
+                rv += fields and ', ' or ' '
+                rv += ', '.join('%s=%s' % (a, _format(getattr(node, a)))
+                                for a in node._attributes)
+            return rv + ')'
+        elif isinstance(node, list):
+            return '[%s]' % ', '.join(_format(x) for x in node)
+        return repr(node)
+    if not isinstance(node, AST):
+        raise TypeError('expected AST, got %r' % node.__class__.__name__)
+    return _format(node)
+
+
+def copy_location(new_node, old_node):
+    """
+    Copy source location (`lineno` and `col_offset` attributes) from
+    *old_node* to *new_node* if possible, and return *new_node*.
+    """
+    for attr in 'lineno', 'col_offset':
+        if attr in old_node._attributes and attr in new_node._attributes \
+           and hasattr(old_node, attr):
+            setattr(new_node, attr, getattr(old_node, attr))
+    return new_node
+
+
+def fix_missing_locations(node):
+    """
+    When you compile a node tree with compile(), the compiler expects lineno and
+    col_offset attributes for every node that supports them.  This is rather
+    tedious to fill in for generated nodes, so this helper adds these attributes
+    recursively where not already set, by setting them to the values of the
+    parent node.  It works recursively starting at *node*.
+    """
+    def _fix(node, lineno, col_offset):
+        if 'lineno' in node._attributes:
+            if not hasattr(node, 'lineno'):
+                node.lineno = lineno
+            else:
+                lineno = node.lineno
+        if 'col_offset' in node._attributes:
+            if not hasattr(node, 'col_offset'):
+                node.col_offset = col_offset
+            else:
+                col_offset = node.col_offset
+        for child in iter_child_nodes(node):
+            _fix(child, lineno, col_offset)
+    _fix(node, 1, 0)
+    return node
+
+
+def increment_lineno(node, n=1):
+    """
+    Increment the line number of each node in the tree starting at *node* by *n*.
+    This is useful to "move code" to a different location in a file.
+    """
+    for child in walk(node):
+        if 'lineno' in child._attributes:
+            child.lineno = getattr(child, 'lineno', 0) + n
+    return node
+
+
+def iter_fields(node):
+    """
+    Yield a tuple of ``(fieldname, value)`` for each field in ``node._fields``
+    that is present on *node*.
+    """
+    for field in node._fields:
+        try:
+            yield field, getattr(node, field)
+        except AttributeError:
+            pass
+
+
+def iter_child_nodes(node):
+    """
+    Yield all direct child nodes of *node*, that is, all fields that are nodes
+    and all items of fields that are lists of nodes.
+    """
+    for name, field in iter_fields(node):
+        if isinstance(field, AST):
+            yield field
+        elif isinstance(field, list):
+            for item in field:
+                if isinstance(item, AST):
+                    yield item
+
+
+def get_docstring(node, clean=True):
+    """
+    Return the docstring for the given node or None if no docstring can
+    be found.  If the node provided does not have docstrings a TypeError
+    will be raised.
+    """
+    if not isinstance(node, (AsyncFunctionDef, FunctionDef, ClassDef, Module)):
+        raise TypeError("%r can't have docstrings" % node.__class__.__name__)
+    if node.body and isinstance(node.body[0], Expr) and \
+       isinstance(node.body[0].value, Str):
+        if clean:
+            import inspect
+            return inspect.cleandoc(node.body[0].value.s)
+        return node.body[0].value.s
+
+
+def walk(node):
+    """
+    Recursively yield all descendant nodes in the tree starting at *node*
+    (including *node* itself), in no specified order.  This is useful if you
+    only want to modify nodes in place and don't care about the context.
+    """
+    from collections import deque
+    todo = deque([node])
+    while todo:
+        node = todo.popleft()
+        todo.extend(iter_child_nodes(node))
+        yield node
+
+
+class NodeVisitor(object):
+    """
+    A node visitor base class that walks the abstract syntax tree and calls a
+    visitor function for every node found.  This function may return a value
+    which is forwarded by the `visit` method.
+
+    This class is meant to be subclassed, with the subclass adding visitor
+    methods.
+
+    Per default the visitor functions for the nodes are ``'visit_'`` +
+    class name of the node.  So a `TryFinally` node visit function would
+    be `visit_TryFinally`.  This behavior can be changed by overriding
+    the `visit` method.  If no visitor function exists for a node
+    (return value `None`) the `generic_visit` visitor is used instead.
+
+    Don't use the `NodeVisitor` if you want to apply changes to nodes during
+    traversing.  For this a special visitor exists (`NodeTransformer`) that
+    allows modifications.
+    """
+
+    def visit(self, node):
+        """Visit a node."""
+        method = 'visit_' + node.__class__.__name__
+        visitor = getattr(self, method, self.generic_visit)
+        return visitor(node)
+
+    def generic_visit(self, node):
+        """Called if no explicit visitor function exists for a node."""
+        for field, value in iter_fields(node):
+            if isinstance(value, list):
+                for item in value:
+                    if isinstance(item, AST):
+                        self.visit(item)
+            elif isinstance(value, AST):
+                self.visit(value)
+
+
+class NodeTransformer(NodeVisitor):
+    """
+    A :class:`NodeVisitor` subclass that walks the abstract syntax tree and
+    allows modification of nodes.
+
+    The `NodeTransformer` will walk the AST and use the return value of the
+    visitor methods to replace or remove the old node.  If the return value of
+    the visitor method is ``None``, the node will be removed from its location,
+    otherwise it is replaced with the return value.  The return value may be the
+    original node in which case no replacement takes place.
+
+    Here is an example transformer that rewrites all occurrences of name lookups
+    (``foo``) to ``data['foo']``::
+
+       class RewriteName(NodeTransformer):
+
+           def visit_Name(self, node):
+               return copy_location(Subscript(
+                   value=Name(id='data', ctx=Load()),
+                   slice=Index(value=Str(s=node.id)),
+                   ctx=node.ctx
+               ), node)
+
+    Keep in mind that if the node you're operating on has child nodes you must
+    either transform the child nodes yourself or call the :meth:`generic_visit`
+    method for the node first.
+
+    For nodes that were part of a collection of statements (that applies to all
+    statement nodes), the visitor may also return a list of nodes rather than
+    just a single node.
+
+    Usually you use the transformer like this::
+
+       node = YourTransformer().visit(node)
+    """
+
+    def generic_visit(self, node):
+        for field, old_value in iter_fields(node):
+            if isinstance(old_value, list):
+                new_values = []
+                for value in old_value:
+                    if isinstance(value, AST):
+                        value = self.visit(value)
+                        if value is None:
+                            continue
+                        elif not isinstance(value, AST):
+                            new_values.extend(value)
+                            continue
+                    new_values.append(value)
+                old_value[:] = new_values
+            elif isinstance(old_value, AST):
+                new_node = self.visit(old_value)
+                if new_node is None:
+                    delattr(node, field)
+                else:
+                    setattr(node, field, new_node)
+        return node
diff --git a/typed_ast/conversions.py b/typed_ast/conversions.py
new file mode 100644
index 0000000..953133a
--- /dev/null
+++ b/typed_ast/conversions.py
@@ -0,0 +1,214 @@
+from typed_ast import ast27
+from typed_ast import ast35
+
+def py2to3(ast):
+    """Converts a typed Python 2.7 ast to a typed Python 3.5 ast.  The returned
+        ast is a valid Python 3 ast with two exceptions:
+
+        - `arg` objects may contain Tuple objects instead of just identifiers
+           in the case of Python 2 function definitions/lambdas that use the tuple
+           unpacking syntax.
+        - `Raise` objects will have a `traceback` attribute added if the 3
+           argument version of the Python 2 raise is used.
+
+
+    Strange and Rare Uncovered Edge Cases:
+        - Raise: if the second argument to a raise statement is a tuple, its
+          contents are unpacked as arguments to the exception constructor.  This
+          case is handled correctly if it's a literal tuple, but not if it's any
+          other sort of tuple expression.
+    """
+    return _AST2To3().visit(ast)
+
+def _copy_attributes(new_value, old_value):
+    attrs = getattr(old_value, '_attributes', None)
+    if attrs is not None:
+        for attr in attrs:
+            setattr(new_value, attr, getattr(old_value, attr))
+    return new_value
+
+class _AST2To3(ast27.NodeTransformer):
+    # note: None, True, and False are *not* translated into NameConstants.
+    # note: Negative numeric literals are not converted to use unary -
+
+    def __init__(self):
+        pass
+
+    def visit(self, node):
+        """Visit a node."""
+        method = 'visit_' + node.__class__.__name__
+        visitor = getattr(self, method, self.generic_visit)
+        ret = _copy_attributes(visitor(node), node)
+        return ret
+
+    def maybe_visit(self, node):
+        if node is not None:
+            return self.visit(node)
+        else:
+            return None
+
+    def generic_visit(self, node):
+        class_name = node.__class__.__name__
+        converted_class = getattr(ast35, class_name)
+        new_node = converted_class()
+        for field, old_value in ast27.iter_fields(node):
+            if isinstance(old_value, (ast27.AST, list)):
+                setattr(new_node, field, self.visit(old_value))
+            else:
+                setattr(new_node, field, old_value)
+        return new_node
+
+
+    def visit_list(self, l):
+        return [self.visit(e) if isinstance(e, (ast27.AST, list)) else e for e in l]
+
+    def visit_FunctionDef(self, n):
+        new = self.generic_visit(n)
+        new.returns = None
+        return new
+
+    def visit_ClassDef(self, n):
+        new = self.generic_visit(n)
+        new.keywords = []
+        return new
+
+    def visit_TryExcept(self, n):
+        return ast35.Try(self.visit(n.body),
+                         self.visit(n.handlers),
+                         self.visit(n.orelse),
+                         [])
+
+    def visit_TryFinally(self, n):
+        if len(n.body) == 1 and isinstance(n.body[0], ast27.TryExcept):
+            new = self.visit(n.body[0])
+            new.finalbody = self.visit(n.finalbody)
+            return new
+        else:
+            return ast35.Try(self.visit(n.body),
+                             [],
+                             [],
+                             self.visit(n.finalbody))
+
+
+    def visit_ExceptHandler(self, n):
+        if n.name is None:
+            name = None
+        elif isinstance(n.name, ast27.Name):
+            name = n.name.id
+        else:
+            raise RuntimeError("'{}' has non-Name name.".format(ast27.dump(n)))
+
+        return ast35.ExceptHandler(self.maybe_visit(n.type),
+                                   name,
+                                   self.visit(n.body))
+
+    def visit_Print(self, n):
+        keywords = []
+        if n.dest is not None:
+            keywords.append(ast35.keyword("file", self.visit(n.dest)))
+
+        if not n.nl:
+            keywords.append(ast35.keyword("end", ast35.Str(" ", lineno=n.lineno, col_offset=-1)))
+
+        return ast35.Expr(ast35.Call(ast35.Name("print", ast35.Load(), lineno=n.lineno, col_offset=-1),
+                                     self.visit(n.values),
+                                     keywords,
+                                     lineno=n.lineno, col_offset=-1))
+
+    def visit_Raise(self, n):
+        e = None
+        if n.type is not None:
+            e = self.visit(n.type)
+
+            if n.inst is not None and not (isinstance(n.inst, ast27.Name) and n.inst.id == "None"):
+                inst = self.visit(n.inst)
+                if isinstance(inst, ast35.Tuple):
+                    args = inst.elts
+                else:
+                    args = [inst]
+                e = ast35.Call(e, args, [], lineno=e.lineno, col_offset=-1)
+
+        ret = ast35.Raise(e, None)
+        if n.tback is not None:
+            ret.traceback = self.visit(n.tback)
+        return ret
+
+    def visit_Exec(self, n):
+        return ast35.Expr(ast35.Call(ast35.Name("exec", ast35.Load(), lineno=n.lineno, col_offset=-1),
+                                     [self.visit(n.body), self.maybe_visit(n.globals), self.maybe_visit(n.locals)],
+                                     [],
+                                     lineno=n.lineno, col_offset=-1))
+
+    # TODO(ddfisher): the name repr could be used locally as something else; disambiguate
+    def visit_Repr(self, n):
+        return ast35.Call(ast35.Name("repr", ast35.Load(), lineno=n.lineno, col_offset=-1),
+                          [self.visit(n.value)],
+                          [])
+
+    # TODO(ddfisher): this will cause strange behavior on multi-item with statements with type comments
+    def visit_With(self, n):
+        return ast35.With([ast35.withitem(self.visit(n.context_expr), self.maybe_visit(n.optional_vars))],
+                          self.visit(n.body),
+                          n.type_comment)
+
+    def visit_Call(self, n):
+        args = self.visit(n.args)
+        if n.starargs is not None:
+            args.append(ast35.Starred(self.visit(n.starargs), ast35.Load(), lineno=n.starargs.lineno, col_offset=n.starargs.col_offset))
+
+        keywords = self.visit(n.keywords)
+        if n.kwargs is not None:
+            keywords.append(ast35.keyword(None, self.visit(n.kwargs)))
+
+        return ast35.Call(self.visit(n.func),
+                          args,
+                          keywords)
+
+    # TODO(ddfisher): find better attributes to give Ellipses
+    def visit_Ellipsis(self, n):
+        # ellipses in Python 2 only exist as a slice index
+        return ast35.Index(ast35.Ellipsis(lineno=-1, col_offset=-1))
+
+    def visit_arguments(self, n):
+        def convert_arg(arg, annotation):
+            if isinstance(arg, ast27.Name):
+                v = arg.id
+            elif isinstance(arg, ast27.Tuple):
+                v = self.visit(arg)
+            else:
+                raise RuntimeError("'{}' is not a valid argument.".format(ast27.dump(arg)))
+            return ast35.arg(v, annotation, lineno=arg.lineno, col_offset=arg.col_offset)
+
+        def get_type_comment(i):
+            if i < len(n.type_comments) and n.type_comments[i] is not None:
+                return ast35.Str(n.type_comments[i])
+            return None
+
+        args = [convert_arg(arg, get_type_comment(i)) for i, arg in enumerate(n.args)]
+
+        vararg = None
+        if n.vararg is not None:
+            vararg = ast35.arg(n.vararg,
+                               get_type_comment(len(args)),
+                               lineno=-1, col_offset=-1)
+
+        kwarg = None
+        if n.kwarg is not None:
+            kwarg = ast35.arg(n.kwarg,
+                              get_type_comment(len(args) + (0 if n.vararg is None else 1)),
+                              lineno=-1, col_offset=-1)
+
+        defaults = self.visit(n.defaults)
+
+        return ast35.arguments(args,
+                               vararg,
+                               [],
+                               [],
+                               kwarg,
+                               defaults)
+
+    def visit_Str(self, s):
+        if isinstance(s.s, bytes):
+            return ast35.Bytes(s.s)
+        else:
+            return ast35.Str(s.s)

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-med/python3-typed-ast.git



More information about the debian-med-commit mailing list