| #include <Python.h> |
| #include "pegen_interface.h" |
| |
| static int |
| _mode_str_to_int(char *mode_str) |
| { |
| 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 { |
| mode = -1; |
| } |
| return mode; |
| } |
| |
| static mod_ty |
| _run_parser(char *str, char *filename, int mode, PyCompilerFlags *flags, PyArena *arena, int oldparser) |
| { |
| mod_ty mod; |
| if (!oldparser) { |
| mod = PyPegen_ASTFromString(str, filename, mode, flags, arena); |
| } |
| else { |
| mod = PyParser_ASTFromString(str, filename, mode, flags, arena); |
| } |
| return mod; |
| } |
| |
| PyObject * |
| _Py_compile_string(PyObject *self, PyObject *args, PyObject *kwds) |
| { |
| static char *keywords[] = {"string", "filename", "mode", "oldparser", NULL}; |
| char *the_string; |
| char *filename = "<string>"; |
| char *mode_str = "exec"; |
| int oldparser = 0; |
| |
| if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|ssp", keywords, |
| &the_string, &filename, &mode_str, &oldparser)) { |
| return NULL; |
| } |
| |
| int mode = _mode_str_to_int(mode_str); |
| if (mode == -1) { |
| return PyErr_Format(PyExc_ValueError, "mode must be either 'exec' or 'eval' or 'single'"); |
| } |
| |
| PyCompilerFlags flags = _PyCompilerFlags_INIT; |
| flags.cf_flags = PyCF_IGNORE_COOKIE; |
| |
| PyArena *arena = PyArena_New(); |
| if (arena == NULL) { |
| return NULL; |
| } |
| |
| mod_ty mod = _run_parser(the_string, filename, mode, &flags, arena, oldparser); |
| if (mod == NULL) { |
| PyArena_Free(arena); |
| return NULL; |
| } |
| |
| PyObject *filename_ob = PyUnicode_DecodeFSDefault(filename); |
| if (filename_ob == NULL) { |
| PyArena_Free(arena); |
| return NULL; |
| } |
| PyCodeObject *result = PyAST_CompileObject(mod, filename_ob, &flags, -1, arena); |
| Py_XDECREF(filename_ob); |
| PyArena_Free(arena); |
| return (PyObject *)result; |
| } |
| |
| PyObject * |
| _Py_parse_string(PyObject *self, PyObject *args, PyObject *kwds) |
| { |
| static char *keywords[] = {"string", "filename", "mode", "oldparser", "ast", NULL}; |
| char *the_string; |
| char *filename = "<string>"; |
| char *mode_str = "exec"; |
| int oldparser = 0; |
| int ast = 1; |
| |
| if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|sspp", keywords, |
| &the_string, &filename, &mode_str, &oldparser, &ast)) { |
| return NULL; |
| } |
| |
| int mode = _mode_str_to_int(mode_str); |
| if (mode == -1) { |
| return PyErr_Format(PyExc_ValueError, "mode must be either 'exec' or 'eval' or 'single'"); |
| } |
| |
| PyCompilerFlags flags = _PyCompilerFlags_INIT; |
| flags.cf_flags = PyCF_IGNORE_COOKIE; |
| |
| PyArena *arena = PyArena_New(); |
| if (arena == NULL) { |
| return NULL; |
| } |
| |
| mod_ty mod = _run_parser(the_string, filename, mode, &flags, arena, oldparser); |
| if (mod == NULL) { |
| PyArena_Free(arena); |
| return NULL; |
| } |
| |
| PyObject *result; |
| if (ast) { |
| result = PyAST_mod2obj(mod); |
| } |
| else { |
| Py_INCREF(Py_None); |
| result = Py_None; |
| } |
| PyArena_Free(arena); |
| return result; |
| } |
| |
| static PyMethodDef ParseMethods[] = { |
| { |
| "parse_string", |
| (PyCFunction)(void (*)(void))_Py_parse_string, |
| METH_VARARGS|METH_KEYWORDS, |
| "Parse a string, return an AST." |
| }, |
| { |
| "compile_string", |
| (PyCFunction)(void (*)(void))_Py_compile_string, |
| METH_VARARGS|METH_KEYWORDS, |
| "Compile a string, return a code object." |
| }, |
| {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); |
| } |