#include "pegen.h" #include "pycore_compile.h" // _PyAST_Compile() PyObject * _build_return_object(mod_ty module, int mode, PyObject *filename_ob, PyArena *arena) { PyObject *result = NULL; if (mode == 2) { result = (PyObject *)_PyAST_Compile(module, filename_ob, NULL, -1, arena); } else if (mode == 1) { result = PyAST_mod2obj(module); } else { result = Py_NewRef(Py_None); } 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; } FILE *fp = fopen(filename, "rb"); if (fp == NULL) { PyErr_SetFromErrnoWithFilename(PyExc_OSError, filename); goto error; } PyCompilerFlags flags = _PyCompilerFlags_INIT; mod_ty res = _PyPegen_run_parser_from_file_pointer( fp, Py_file_input, filename_ob, NULL, NULL, NULL, &flags, NULL, NULL, arena); fclose(fp); 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(""); if (filename_ob == NULL) { goto error; } PyCompilerFlags flags = _PyCompilerFlags_INIT; mod_ty res = _PyPegen_run_parser_from_string(the_string, Py_file_input, filename_ob, &flags, 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(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(ignored)) { #if defined(PY_DEBUG) _PyPegen_clear_memo_statistics(); #endif Py_RETURN_NONE; } static PyObject * get_memo_stats(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(ignored)) { #if defined(PY_DEBUG) return _PyPegen_get_memo_statistics(); #else Py_RETURN_NONE; #endif } // TODO: Write to Python's sys.stdout instead of C's stdout. static PyObject * dump_memo_stats(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(ignored)) { #if defined(PY_DEBUG) 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("%4zd %9ld\n", i, count); } } Py_DECREF(list); #endif Py_RETURN_NONE; } static PyMethodDef ParseMethods[] = { {"parse_file", _PyCFunction_CAST(parse_file), METH_VARARGS|METH_KEYWORDS, "Parse a file."}, {"parse_string", _PyCFunction_CAST(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); }