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