| 
									
										
										
										
											2020-04-22 23:29:27 +01:00
										 |  |  | #include "pegen.h"
 | 
					
						
							| 
									
										
										
										
											2021-03-24 00:51:50 +01:00
										 |  |  | #include "pycore_compile.h"       // _PyAST_Compile()
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-22 23:29:27 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | PyObject * | 
					
						
							|  |  |  | _build_return_object(mod_ty module, int mode, PyObject *filename_ob, PyArena *arena) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     PyObject *result = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (mode == 2) { | 
					
						
							| 
									
										
										
										
											2021-03-24 00:51:50 +01:00
										 |  |  |         result = (PyObject *)_PyAST_Compile(module, filename_ob, NULL, -1, arena); | 
					
						
							| 
									
										
										
										
											2020-04-22 23:29:27 +01:00
										 |  |  |     } else if (mode == 1) { | 
					
						
							|  |  |  |         result = PyAST_mod2obj(module); | 
					
						
							|  |  |  |     } else { | 
					
						
							| 
									
										
										
										
											2022-11-10 15:30:05 +01:00
										 |  |  |         result = Py_NewRef(Py_None); | 
					
						
							| 
									
										
										
										
											2020-04-22 23:29:27 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return result; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | parse_file(PyObject *self, PyObject *args, PyObject *kwds) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     static char *keywords[] = {"file", "mode", NULL}; | 
					
						
							|  |  |  |     const char *filename; | 
					
						
							|  |  |  |     int mode = 2; | 
					
						
							|  |  |  |     if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|i", keywords, &filename, &mode)) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (mode < 0 || mode > 2) { | 
					
						
							|  |  |  |         return PyErr_Format(PyExc_ValueError, "Bad mode, must be 0 <= mode <= 2"); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-24 02:23:01 +01:00
										 |  |  |     PyArena *arena = _PyArena_New(); | 
					
						
							| 
									
										
										
										
											2020-04-22 23:29:27 +01:00
										 |  |  |     if (arena == NULL) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     PyObject *result = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     PyObject *filename_ob = PyUnicode_FromString(filename); | 
					
						
							|  |  |  |     if (filename_ob == NULL) { | 
					
						
							|  |  |  |         goto error; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-24 01:29:09 +01:00
										 |  |  |     FILE *fp = fopen(filename, "rb"); | 
					
						
							|  |  |  |     if (fp == NULL) { | 
					
						
							|  |  |  |         PyErr_SetFromErrnoWithFilename(PyExc_OSError, filename); | 
					
						
							|  |  |  |         goto error; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-27 18:02:07 +01:00
										 |  |  |     PyCompilerFlags flags = _PyCompilerFlags_INIT; | 
					
						
							| 
									
										
										
										
											2021-03-24 01:29:09 +01:00
										 |  |  |     mod_ty res = _PyPegen_run_parser_from_file_pointer( | 
					
						
							|  |  |  |                         fp, Py_file_input, filename_ob, | 
					
						
							| 
									
										
										
										
											2023-10-13 13:04:23 +02:00
										 |  |  |                         NULL, NULL, NULL, &flags, NULL, NULL, arena); | 
					
						
							| 
									
										
										
										
											2021-03-24 01:29:09 +01:00
										 |  |  |     fclose(fp); | 
					
						
							| 
									
										
										
										
											2020-04-22 23:29:27 +01:00
										 |  |  |     if (res == NULL) { | 
					
						
							|  |  |  |         goto error; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     result = _build_return_object(res, mode, filename_ob, arena); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | error: | 
					
						
							|  |  |  |     Py_XDECREF(filename_ob); | 
					
						
							| 
									
										
										
										
											2021-03-24 02:23:01 +01:00
										 |  |  |     _PyArena_Free(arena); | 
					
						
							| 
									
										
										
										
											2020-04-22 23:29:27 +01:00
										 |  |  |     return result; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | parse_string(PyObject *self, PyObject *args, PyObject *kwds) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     static char *keywords[] = {"str", "mode", NULL}; | 
					
						
							|  |  |  |     const char *the_string; | 
					
						
							|  |  |  |     int mode = 2; | 
					
						
							|  |  |  |     if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|i", keywords, &the_string, &mode)) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (mode < 0 || mode > 2) { | 
					
						
							|  |  |  |         return PyErr_Format(PyExc_ValueError, "Bad mode, must be 0 <= mode <= 2"); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-24 02:23:01 +01:00
										 |  |  |     PyArena *arena = _PyArena_New(); | 
					
						
							| 
									
										
										
										
											2020-04-22 23:29:27 +01:00
										 |  |  |     if (arena == NULL) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     PyObject *result = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     PyObject *filename_ob = PyUnicode_FromString("<string>"); | 
					
						
							|  |  |  |     if (filename_ob == NULL) { | 
					
						
							|  |  |  |         goto error; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-27 18:02:07 +01:00
										 |  |  |     PyCompilerFlags flags = _PyCompilerFlags_INIT; | 
					
						
							| 
									
										
										
										
											2020-04-22 23:29:27 +01:00
										 |  |  |     mod_ty res = _PyPegen_run_parser_from_string(the_string, Py_file_input, filename_ob, | 
					
						
							| 
									
										
										
										
											2020-04-27 18:02:07 +01:00
										 |  |  |                                         &flags, arena); | 
					
						
							| 
									
										
										
										
											2020-04-22 23:29:27 +01:00
										 |  |  |     if (res == NULL) { | 
					
						
							|  |  |  |         goto error; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     result = _build_return_object(res, mode, filename_ob, arena); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | error: | 
					
						
							|  |  |  |     Py_XDECREF(filename_ob); | 
					
						
							| 
									
										
										
										
											2021-03-24 02:23:01 +01:00
										 |  |  |     _PyArena_Free(arena); | 
					
						
							| 
									
										
										
										
											2020-04-22 23:29:27 +01:00
										 |  |  |     return result; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2020-05-26 04:33:35 +00:00
										 |  |  | clear_memo_stats(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(ignored)) | 
					
						
							| 
									
										
										
										
											2020-04-22 23:29:27 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-04-09 01:17:31 +01:00
										 |  |  | #if defined(PY_DEBUG)
 | 
					
						
							| 
									
										
										
										
											2020-04-22 23:29:27 +01:00
										 |  |  |     _PyPegen_clear_memo_statistics(); | 
					
						
							| 
									
										
										
										
											2021-04-09 01:17:31 +01:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2020-04-22 23:29:27 +01:00
										 |  |  |     Py_RETURN_NONE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2020-05-26 04:33:35 +00:00
										 |  |  | get_memo_stats(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(ignored)) | 
					
						
							| 
									
										
										
										
											2020-04-22 23:29:27 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-04-09 01:17:31 +01:00
										 |  |  | #if defined(PY_DEBUG)
 | 
					
						
							| 
									
										
										
										
											2020-04-22 23:29:27 +01:00
										 |  |  |     return _PyPegen_get_memo_statistics(); | 
					
						
							| 
									
										
										
										
											2021-04-09 01:17:31 +01:00
										 |  |  | #else
 | 
					
						
							|  |  |  |     Py_RETURN_NONE; | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2020-04-22 23:29:27 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // TODO: Write to Python's sys.stdout instead of C's stdout.
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2020-05-26 04:33:35 +00:00
										 |  |  | dump_memo_stats(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(ignored)) | 
					
						
							| 
									
										
										
										
											2020-04-22 23:29:27 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-04-09 01:17:31 +01:00
										 |  |  | #if defined(PY_DEBUG)
 | 
					
						
							| 
									
										
										
										
											2020-04-22 23:29:27 +01:00
										 |  |  |     PyObject *list = _PyPegen_get_memo_statistics(); | 
					
						
							|  |  |  |     if (list == NULL) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     Py_ssize_t len = PyList_Size(list); | 
					
						
							|  |  |  |     for (Py_ssize_t i = 0; i < len; i++) { | 
					
						
							|  |  |  |         PyObject *value = PyList_GetItem(list, i);  // Borrowed reference.
 | 
					
						
							|  |  |  |         long count = PyLong_AsLong(value); | 
					
						
							|  |  |  |         if (count < 0) { | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (count > 0) { | 
					
						
							| 
									
										
										
										
											2020-05-26 04:33:35 +00:00
										 |  |  |             printf("%4zd %9ld\n", i, count); | 
					
						
							| 
									
										
										
										
											2020-04-22 23:29:27 +01:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     Py_DECREF(list); | 
					
						
							| 
									
										
										
										
											2021-04-09 01:17:31 +01:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2020-04-22 23:29:27 +01:00
										 |  |  |     Py_RETURN_NONE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyMethodDef ParseMethods[] = { | 
					
						
							| 
									
										
										
										
											2022-05-03 21:42:14 +02:00
										 |  |  |     {"parse_file", _PyCFunction_CAST(parse_file), METH_VARARGS|METH_KEYWORDS, "Parse a file."}, | 
					
						
							|  |  |  |     {"parse_string", _PyCFunction_CAST(parse_string), METH_VARARGS|METH_KEYWORDS, "Parse a string."}, | 
					
						
							| 
									
										
										
										
											2020-04-22 23:29:27 +01:00
										 |  |  |     {"clear_memo_stats", clear_memo_stats, METH_NOARGS}, | 
					
						
							|  |  |  |     {"dump_memo_stats", dump_memo_stats, METH_NOARGS}, | 
					
						
							|  |  |  |     {"get_memo_stats", get_memo_stats, METH_NOARGS}, | 
					
						
							|  |  |  |     {NULL, NULL, 0, NULL}        /* Sentinel */ | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static struct PyModuleDef parsemodule = { | 
					
						
							|  |  |  |     PyModuleDef_HEAD_INIT, | 
					
						
							|  |  |  |     .m_name = "parse", | 
					
						
							|  |  |  |     .m_doc = "A parser.", | 
					
						
							|  |  |  |     .m_methods = ParseMethods, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyMODINIT_FUNC | 
					
						
							|  |  |  | PyInit_parse(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return PyModule_Create(&parsemodule); | 
					
						
							|  |  |  | } |