154 lines
3.8 KiB
C
154 lines
3.8 KiB
C
#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);
|
|
}
|