summaryrefslogtreecommitdiffstats
path: root/Tools/peg_generator/peg_extension
diff options
context:
space:
mode:
authorPablo Galindo <Pablogsal@gmail.com>2020-04-22 22:29:27 (GMT)
committerGitHub <noreply@github.com>2020-04-22 22:29:27 (GMT)
commitc5fc15685202cda73f7c3f5c6f299b0945f58508 (patch)
tree7624ae45b95f2812e801c5879bdbdcb796f570a6 /Tools/peg_generator/peg_extension
parenta81849b0315277bb3937271174aaaa5059c0b445 (diff)
downloadcpython-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 'Tools/peg_generator/peg_extension')
-rw-r--r--Tools/peg_generator/peg_extension/peg_extension.c153
1 files changed, 153 insertions, 0 deletions
diff --git a/Tools/peg_generator/peg_extension/peg_extension.c b/Tools/peg_generator/peg_extension/peg_extension.c
new file mode 100644
index 0000000..d8d36a0
--- /dev/null
+++ b/Tools/peg_generator/peg_extension/peg_extension.c
@@ -0,0 +1,153 @@
+#include "pegen.h"
+
+PyObject *
+_build_return_object(mod_ty module, int mode, PyObject *filename_ob, PyArena *arena)
+{
+ PyObject *result = NULL;
+
+ if (mode == 2) {
+ result = (PyObject *)PyAST_CompileObject(module, filename_ob, NULL, -1, arena);
+ } else if (mode == 1) {
+ result = PyAST_mod2obj(module);
+ } else {
+ result = Py_None;
+ Py_INCREF(result);
+
+ }
+
+ return result;
+}
+
+static PyObject *
+parse_file(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ static char *keywords[] = {"file", "mode", NULL};
+ const char *filename;
+ int mode = 2;
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|i", keywords, &filename, &mode)) {
+ return NULL;
+ }
+ if (mode < 0 || mode > 2) {
+ return PyErr_Format(PyExc_ValueError, "Bad mode, must be 0 <= mode <= 2");
+ }
+
+ PyArena *arena = PyArena_New();
+ if (arena == NULL) {
+ return NULL;
+ }
+
+ PyObject *result = NULL;
+
+ PyObject *filename_ob = PyUnicode_FromString(filename);
+ if (filename_ob == NULL) {
+ goto error;
+ }
+
+ mod_ty res = _PyPegen_run_parser_from_file(filename, Py_file_input, filename_ob, arena);
+ if (res == NULL) {
+ goto error;
+ }
+
+ result = _build_return_object(res, mode, filename_ob, arena);
+
+error:
+ Py_XDECREF(filename_ob);
+ PyArena_Free(arena);
+ return result;
+}
+
+static PyObject *
+parse_string(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ static char *keywords[] = {"str", "mode", NULL};
+ const char *the_string;
+ int mode = 2;
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|i", keywords, &the_string, &mode)) {
+ return NULL;
+ }
+ if (mode < 0 || mode > 2) {
+ return PyErr_Format(PyExc_ValueError, "Bad mode, must be 0 <= mode <= 2");
+ }
+
+ PyArena *arena = PyArena_New();
+ if (arena == NULL) {
+ return NULL;
+ }
+
+ PyObject *result = NULL;
+
+ PyObject *filename_ob = PyUnicode_FromString("<string>");
+ if (filename_ob == NULL) {
+ goto error;
+ }
+
+ mod_ty res = _PyPegen_run_parser_from_string(the_string, Py_file_input, filename_ob,
+ PyCF_IGNORE_COOKIE, arena);
+ if (res == NULL) {
+ goto error;
+ }
+ result = _build_return_object(res, mode, filename_ob, arena);
+
+error:
+ Py_XDECREF(filename_ob);
+ PyArena_Free(arena);
+ return result;
+}
+
+static PyObject *
+clear_memo_stats()
+{
+ _PyPegen_clear_memo_statistics();
+ Py_RETURN_NONE;
+}
+
+static PyObject *
+get_memo_stats()
+{
+ return _PyPegen_get_memo_statistics();
+}
+
+// TODO: Write to Python's sys.stdout instead of C's stdout.
+static PyObject *
+dump_memo_stats()
+{
+ PyObject *list = _PyPegen_get_memo_statistics();
+ if (list == NULL) {
+ return NULL;
+ }
+ Py_ssize_t len = PyList_Size(list);
+ for (Py_ssize_t i = 0; i < len; i++) {
+ PyObject *value = PyList_GetItem(list, i); // Borrowed reference.
+ long count = PyLong_AsLong(value);
+ if (count < 0) {
+ break;
+ }
+ if (count > 0) {
+ printf("%4ld %9ld\n", i, count);
+ }
+ }
+ Py_DECREF(list);
+ Py_RETURN_NONE;
+}
+
+static PyMethodDef ParseMethods[] = {
+ {"parse_file", (PyCFunction)(void(*)(void))parse_file, METH_VARARGS|METH_KEYWORDS, "Parse a file."},
+ {"parse_string", (PyCFunction)(void(*)(void))parse_string, METH_VARARGS|METH_KEYWORDS, "Parse a string."},
+ {"clear_memo_stats", clear_memo_stats, METH_NOARGS},
+ {"dump_memo_stats", dump_memo_stats, METH_NOARGS},
+ {"get_memo_stats", get_memo_stats, METH_NOARGS},
+ {NULL, NULL, 0, NULL} /* Sentinel */
+};
+
+static struct PyModuleDef parsemodule = {
+ PyModuleDef_HEAD_INIT,
+ .m_name = "parse",
+ .m_doc = "A parser.",
+ .m_methods = ParseMethods,
+};
+
+PyMODINIT_FUNC
+PyInit_parse(void)
+{
+ return PyModule_Create(&parsemodule);
+}