mirror of https://github.com/python/cpython
173 lines
4.4 KiB
C
173 lines
4.4 KiB
C
#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("<string>");
|
|
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);
|
|
}
|