• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "pegen.h"
2 
3 PyObject *
_build_return_object(mod_ty module,int mode,PyObject * filename_ob,PyArena * arena)4 _build_return_object(mod_ty module, int mode, PyObject *filename_ob, PyArena *arena)
5 {
6     PyObject *result = NULL;
7 
8     if (mode == 2) {
9         result = (PyObject *)PyAST_CompileObject(module, filename_ob, NULL, -1, arena);
10     } else if (mode == 1) {
11         result = PyAST_mod2obj(module);
12     } else {
13         result = Py_None;
14         Py_INCREF(result);
15     }
16 
17     return result;
18 }
19 
20 static PyObject *
parse_file(PyObject * self,PyObject * args,PyObject * kwds)21 parse_file(PyObject *self, PyObject *args, PyObject *kwds)
22 {
23     static char *keywords[] = {"file", "mode", NULL};
24     const char *filename;
25     int mode = 2;
26     if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|i", keywords, &filename, &mode)) {
27         return NULL;
28     }
29     if (mode < 0 || mode > 2) {
30         return PyErr_Format(PyExc_ValueError, "Bad mode, must be 0 <= mode <= 2");
31     }
32 
33     PyArena *arena = PyArena_New();
34     if (arena == NULL) {
35         return NULL;
36     }
37 
38     PyObject *result = NULL;
39 
40     PyObject *filename_ob = PyUnicode_FromString(filename);
41     if (filename_ob == NULL) {
42         goto error;
43     }
44 
45     PyCompilerFlags flags = _PyCompilerFlags_INIT;
46     mod_ty res = _PyPegen_run_parser_from_file(filename, Py_file_input, filename_ob, &flags, arena);
47     if (res == NULL) {
48         goto error;
49     }
50 
51     result = _build_return_object(res, mode, filename_ob, arena);
52 
53 error:
54     Py_XDECREF(filename_ob);
55     PyArena_Free(arena);
56     return result;
57 }
58 
59 static PyObject *
parse_string(PyObject * self,PyObject * args,PyObject * kwds)60 parse_string(PyObject *self, PyObject *args, PyObject *kwds)
61 {
62     static char *keywords[] = {"str", "mode", NULL};
63     const char *the_string;
64     int mode = 2;
65     if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|i", keywords, &the_string, &mode)) {
66         return NULL;
67     }
68     if (mode < 0 || mode > 2) {
69         return PyErr_Format(PyExc_ValueError, "Bad mode, must be 0 <= mode <= 2");
70     }
71 
72     PyArena *arena = PyArena_New();
73     if (arena == NULL) {
74         return NULL;
75     }
76 
77     PyObject *result = NULL;
78 
79     PyObject *filename_ob = PyUnicode_FromString("<string>");
80     if (filename_ob == NULL) {
81         goto error;
82     }
83 
84     PyCompilerFlags flags = _PyCompilerFlags_INIT;
85     mod_ty res = _PyPegen_run_parser_from_string(the_string, Py_file_input, filename_ob,
86                                         &flags, arena);
87     if (res == NULL) {
88         goto error;
89     }
90     result = _build_return_object(res, mode, filename_ob, arena);
91 
92 error:
93     Py_XDECREF(filename_ob);
94     PyArena_Free(arena);
95     return result;
96 }
97 
98 static PyObject *
clear_memo_stats(PyObject * Py_UNUSED (self),PyObject * Py_UNUSED (ignored))99 clear_memo_stats(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(ignored))
100 {
101     _PyPegen_clear_memo_statistics();
102     Py_RETURN_NONE;
103 }
104 
105 static PyObject *
get_memo_stats(PyObject * Py_UNUSED (self),PyObject * Py_UNUSED (ignored))106 get_memo_stats(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(ignored))
107 {
108     return _PyPegen_get_memo_statistics();
109 }
110 
111 // TODO: Write to Python's sys.stdout instead of C's stdout.
112 static PyObject *
dump_memo_stats(PyObject * Py_UNUSED (self),PyObject * Py_UNUSED (ignored))113 dump_memo_stats(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(ignored))
114 {
115     PyObject *list = _PyPegen_get_memo_statistics();
116     if (list == NULL) {
117         return NULL;
118     }
119     Py_ssize_t len = PyList_Size(list);
120     for (Py_ssize_t i = 0; i < len; i++) {
121         PyObject *value = PyList_GetItem(list, i);  // Borrowed reference.
122         long count = PyLong_AsLong(value);
123         if (count < 0) {
124             break;
125         }
126         if (count > 0) {
127             printf("%4zd %9ld\n", i, count);
128         }
129     }
130     Py_DECREF(list);
131     Py_RETURN_NONE;
132 }
133 
134 static PyMethodDef ParseMethods[] = {
135     {"parse_file", (PyCFunction)(void(*)(void))parse_file, METH_VARARGS|METH_KEYWORDS, "Parse a file."},
136     {"parse_string", (PyCFunction)(void(*)(void))parse_string, METH_VARARGS|METH_KEYWORDS, "Parse a string."},
137     {"clear_memo_stats", clear_memo_stats, METH_NOARGS},
138     {"dump_memo_stats", dump_memo_stats, METH_NOARGS},
139     {"get_memo_stats", get_memo_stats, METH_NOARGS},
140     {NULL, NULL, 0, NULL}        /* Sentinel */
141 };
142 
143 static struct PyModuleDef parsemodule = {
144     PyModuleDef_HEAD_INIT,
145     .m_name = "parse",
146     .m_doc = "A parser.",
147     .m_methods = ParseMethods,
148 };
149 
150 PyMODINIT_FUNC
PyInit_parse(void)151 PyInit_parse(void)
152 {
153     return PyModule_Create(&parsemodule);
154 }
155