diff options
author | Pablo Galindo <Pablogsal@gmail.com> | 2020-04-22 22:29:27 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-04-22 22:29:27 (GMT) |
commit | c5fc15685202cda73f7c3f5c6f299b0945f58508 (patch) | |
tree | 7624ae45b95f2812e801c5879bdbdcb796f570a6 /Modules | |
parent | a81849b0315277bb3937271174aaaa5059c0b445 (diff) | |
download | cpython-c5fc15685202cda73f7c3f5c6f299b0945f58508.zip cpython-c5fc15685202cda73f7c3f5c6f299b0945f58508.tar.gz cpython-c5fc15685202cda73f7c3f5c6f299b0945f58508.tar.bz2 |
bpo-40334: PEP 617 implementation: New PEG parser for CPython (GH-19503)
Co-authored-by: Guido van Rossum <guido@python.org>
Co-authored-by: Lysandros Nikolaou <lisandrosnik@gmail.com>
Diffstat (limited to 'Modules')
-rw-r--r-- | Modules/Setup | 3 | ||||
-rw-r--r-- | Modules/_peg_parser.c | 107 |
2 files changed, 110 insertions, 0 deletions
diff --git a/Modules/Setup b/Modules/Setup index 6f0374a..6bf1424 100644 --- a/Modules/Setup +++ b/Modules/Setup @@ -134,6 +134,9 @@ faulthandler faulthandler.c # can call _PyTraceMalloc_NewReference(). _tracemalloc _tracemalloc.c hashtable.c +# PEG-based parser module -- slated to be *the* parser +_peg_parser _peg_parser.c + # The rest of the modules listed in this file are all commented out by # default. Usually they can be detected and built as dynamically # loaded modules by the new setup.py script added in Python 2.1. If diff --git a/Modules/_peg_parser.c b/Modules/_peg_parser.c new file mode 100644 index 0000000..0a84edc --- /dev/null +++ b/Modules/_peg_parser.c @@ -0,0 +1,107 @@ +#include <Python.h> +#include <pegen_interface.h> + +PyObject * +_Py_parse_file(PyObject *self, PyObject *args, PyObject *kwds) +{ + static char *keywords[] = {"file", "mode", NULL}; + char *filename; + char *mode_str = "exec"; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|s", keywords, &filename, &mode_str)) { + return NULL; + } + + int mode; + if (strcmp(mode_str, "exec") == 0) { + mode = Py_file_input; + } + else if (strcmp(mode_str, "single") == 0) { + mode = Py_single_input; + } + else { + return PyErr_Format(PyExc_ValueError, "mode must be either 'exec' or 'single'"); + } + + PyArena *arena = PyArena_New(); + if (arena == NULL) { + return NULL; + } + + PyObject *result = NULL; + + mod_ty res = PyPegen_ASTFromFile(filename, mode, arena); + if (res == NULL) { + goto error; + } + result = PyAST_mod2obj(res); + +error: + PyArena_Free(arena); + return result; +} + +PyObject * +_Py_parse_string(PyObject *self, PyObject *args, PyObject *kwds) +{ + static char *keywords[] = {"string", "mode", NULL}; + char *the_string; + char *mode_str = "exec"; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|s", keywords, &the_string, &mode_str)) { + return NULL; + } + + int mode; + if (strcmp(mode_str, "exec") == 0) { + mode = Py_file_input; + } + else if (strcmp(mode_str, "eval") == 0) { + mode = Py_eval_input; + } + else if (strcmp(mode_str, "single") == 0) { + mode = Py_single_input; + } + else { + return PyErr_Format(PyExc_ValueError, "mode must be either 'exec' or 'eval' or 'single'"); + } + + PyArena *arena = PyArena_New(); + if (arena == NULL) { + return NULL; + } + + PyObject *result = NULL; + + PyCompilerFlags flags = _PyCompilerFlags_INIT; + flags.cf_flags = PyCF_IGNORE_COOKIE; + + mod_ty res = PyPegen_ASTFromString(the_string, mode, &flags, arena); + if (res == NULL) { + goto error; + } + result = PyAST_mod2obj(res); + +error: + PyArena_Free(arena); + return result; +} + +static PyMethodDef ParseMethods[] = { + {"parse_file", (PyCFunction)(void (*)(void))_Py_parse_file, METH_VARARGS|METH_KEYWORDS, "Parse a file."}, + {"parse_string", (PyCFunction)(void (*)(void))_Py_parse_string, METH_VARARGS|METH_KEYWORDS,"Parse a string."}, + {NULL, NULL, 0, NULL} /* Sentinel */ +}; + +static struct PyModuleDef parsemodule = { + PyModuleDef_HEAD_INIT, + .m_name = "peg_parser", + .m_doc = "A parser.", + .m_methods = ParseMethods, +}; + +PyMODINIT_FUNC +PyInit__peg_parser(void) +{ + return PyModule_Create(&parsemodule); +} |