blob: ca2a3cf7b5fd8078c5cc25978c097a63889b7f2f [file] [log] [blame]
Pablo Galindoc5fc1562020-04-22 23:29:27 +01001#include <Python.h>
Lysandros Nikolaouebebb642020-04-23 18:36:06 +03002#include "pegen_interface.h"
Pablo Galindoc5fc1562020-04-22 23:29:27 +01003
Miss Islington (bot)3c6c86a2020-05-25 13:11:36 -07004static int
5_mode_str_to_int(char *mode_str)
Pablo Galindoc5fc1562020-04-22 23:29:27 +01006{
Pablo Galindoc5fc1562020-04-22 23:29:27 +01007 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 {
Miss Islington (bot)3c6c86a2020-05-25 13:11:36 -070018 mode = -1;
19 }
20 return mode;
21}
22
23static 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
36PyObject *
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) {
Pablo Galindoc5fc1562020-04-22 23:29:27 +010052 return PyErr_Format(PyExc_ValueError, "mode must be either 'exec' or 'eval' or 'single'");
53 }
54
Miss Islington (bot)3c6c86a2020-05-25 13:11:36 -070055 PyCompilerFlags flags = _PyCompilerFlags_INIT;
56 flags.cf_flags = PyCF_IGNORE_COOKIE;
57
Pablo Galindoc5fc1562020-04-22 23:29:27 +010058 PyArena *arena = PyArena_New();
59 if (arena == NULL) {
60 return NULL;
61 }
62
Miss Islington (bot)3c6c86a2020-05-25 13:11:36 -070063 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
80PyObject *
81_Py_parse_string(PyObject *self, PyObject *args, PyObject *kwds)
82{
Miss Islington (bot)18f12262020-06-05 21:41:12 -070083 static char *keywords[] = {"string", "filename", "mode", "oldparser", "ast", NULL};
Miss Islington (bot)3c6c86a2020-05-25 13:11:36 -070084 char *the_string;
85 char *filename = "<string>";
86 char *mode_str = "exec";
87 int oldparser = 0;
Miss Islington (bot)18f12262020-06-05 21:41:12 -070088 int ast = 1;
Miss Islington (bot)3c6c86a2020-05-25 13:11:36 -070089
Miss Islington (bot)18f12262020-06-05 21:41:12 -070090 if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|sspp", keywords,
91 &the_string, &filename, &mode_str, &oldparser, &ast)) {
Miss Islington (bot)3c6c86a2020-05-25 13:11:36 -070092 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 }
Pablo Galindoc5fc1562020-04-22 23:29:27 +010099
100 PyCompilerFlags flags = _PyCompilerFlags_INIT;
101 flags.cf_flags = PyCF_IGNORE_COOKIE;
102
Miss Islington (bot)3c6c86a2020-05-25 13:11:36 -0700103 PyArena *arena = PyArena_New();
104 if (arena == NULL) {
105 return NULL;
Lysandros Nikolaou69e802e2020-04-30 01:53:30 +0300106 }
Pablo Galindoc5fc1562020-04-22 23:29:27 +0100107
Miss Islington (bot)3c6c86a2020-05-25 13:11:36 -0700108 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
Miss Islington (bot)18f12262020-06-05 21:41:12 -0700114 PyObject *result;
115 if (ast) {
116 result = PyAST_mod2obj(mod);
117 }
118 else {
119 Py_INCREF(Py_None);
120 result = Py_None;
121 }
Pablo Galindoc5fc1562020-04-22 23:29:27 +0100122 PyArena_Free(arena);
123 return result;
124}
125
126static PyMethodDef ParseMethods[] = {
Miss Islington (bot)3c6c86a2020-05-25 13:11:36 -0700127 {
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 },
Pablo Galindoc5fc1562020-04-22 23:29:27 +0100139 {NULL, NULL, 0, NULL} /* Sentinel */
140};
141
142static struct PyModuleDef parsemodule = {
143 PyModuleDef_HEAD_INIT,
144 .m_name = "peg_parser",
145 .m_doc = "A parser.",
146 .m_methods = ParseMethods,
147};
148
149PyMODINIT_FUNC
150PyInit__peg_parser(void)
151{
152 return PyModule_Create(&parsemodule);
153}