1 #include <Python.h>
2 #include "pegen_interface.h"
3 
4 static int
5 _mode_str_to_int(char *mode_str)
6 {
7     int mode;
8     if (strcmp(mode_str, "exec") == 0) {
9         mode = Py_file_input;
10     }
11     else if (strcmp(mode_str, "eval") == 0) {
12         mode = Py_eval_input;
13     }
14     else if (strcmp(mode_str, "single") == 0) {
15         mode = Py_single_input;
16     }
17     else {
18         mode = -1;
19     }
20     return mode;
21 }
22 
23 static mod_ty
24 _run_parser(char *str, char *filename, int mode, PyCompilerFlags *flags, PyArena *arena, int oldparser)
25 {
26     mod_ty mod;
27     if (!oldparser) {
28         mod = PyPegen_ASTFromString(str, filename, mode, flags, arena);
29     }
30     else {
31         mod = PyParser_ASTFromString(str, filename, mode, flags, arena);
32     }
33     return mod;
34 }
35 
36 PyObject *
37 _Py_compile_string(PyObject *self, PyObject *args, PyObject *kwds)
38 {
39     static char *keywords[] = {"string", "filename", "mode", "oldparser", NULL};
40     char *the_string;
41     char *filename = "<string>";
42     char *mode_str = "exec";
43     int oldparser = 0;
44 
45     if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|ssp", keywords,
46             &the_string, &filename, &mode_str, &oldparser)) {
47         return NULL;
48     }
49 
50     int mode = _mode_str_to_int(mode_str);
51     if (mode == -1) {
52         return PyErr_Format(PyExc_ValueError, "mode must be either 'exec' or 'eval' or 'single'");
53     }
54 
55     PyCompilerFlags flags = _PyCompilerFlags_INIT;
56     flags.cf_flags = PyCF_IGNORE_COOKIE;
57 
58     PyArena *arena = PyArena_New();
59     if (arena == NULL) {
60         return NULL;
61     }
62 
63     mod_ty mod = _run_parser(the_string, filename, mode, &flags, arena, oldparser);
64     if (mod == NULL) {
65         PyArena_Free(arena);
66         return NULL;
67     }
68 
69     PyObject *filename_ob = PyUnicode_DecodeFSDefault(filename);
70     if (filename_ob == NULL) {
71         PyArena_Free(arena);
72         return NULL;
73     }
74     PyCodeObject *result = PyAST_CompileObject(mod, filename_ob, &flags, -1, arena);
75     Py_XDECREF(filename_ob);
76     PyArena_Free(arena);
77     return (PyObject *)result;
78 }
79 
80 PyObject *
81 _Py_parse_string(PyObject *self, PyObject *args, PyObject *kwds)
82 {
83     static char *keywords[] = {"string", "filename", "mode", "oldparser", "ast", NULL};
84     char *the_string;
85     char *filename = "<string>";
86     char *mode_str = "exec";
87     int oldparser = 0;
88     int ast = 1;
89 
90     if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|sspp", keywords,
91             &the_string, &filename, &mode_str, &oldparser, &ast)) {
92         return NULL;
93     }
94 
95     int mode = _mode_str_to_int(mode_str);
96     if (mode == -1) {
97         return PyErr_Format(PyExc_ValueError, "mode must be either 'exec' or 'eval' or 'single'");
98     }
99 
100     PyCompilerFlags flags = _PyCompilerFlags_INIT;
101     flags.cf_flags = PyCF_IGNORE_COOKIE;
102 
103     PyArena *arena = PyArena_New();
104     if (arena == NULL) {
105         return NULL;
106     }
107 
108     mod_ty mod = _run_parser(the_string, filename, mode, &flags, arena, oldparser);
109     if (mod == NULL) {
110         PyArena_Free(arena);
111         return NULL;
112     }
113 
114     PyObject *result;
115     if (ast) {
116         result = PyAST_mod2obj(mod);
117     }
118     else {
119         Py_INCREF(Py_None);
120         result = Py_None;
121     }
122     PyArena_Free(arena);
123     return result;
124 }
125 
126 static PyMethodDef ParseMethods[] = {
127     {
128         "parse_string",
129         (PyCFunction)(void (*)(void))_Py_parse_string,
130         METH_VARARGS|METH_KEYWORDS,
131         "Parse a string, return an AST."
132     },
133     {
134         "compile_string",
135         (PyCFunction)(void (*)(void))_Py_compile_string,
136         METH_VARARGS|METH_KEYWORDS,
137         "Compile a string, return a code object."
138     },
139     {NULL, NULL, 0, NULL} /* Sentinel */
140 };
141 
142 static struct PyModuleDef parsemodule = {
143     PyModuleDef_HEAD_INIT,
144     .m_name = "peg_parser",
145     .m_doc = "A parser.",
146     .m_methods = ParseMethods,
147 };
148 
149 PyMODINIT_FUNC
150 PyInit__peg_parser(void)
151 {
152     return PyModule_Create(&parsemodule);
153 }
154