mirror of
https://github.com/python/cpython.git
synced 2025-07-24 11:44:31 +00:00

Now that the default parser is the new PEG parser, ast.parse uses it, which means that we don't actually test something in test_peg_parser. This commit introduces a new keyword argument (`oldparser`) for `_peg_parser.parse_string` for specifying that a string needs to be parsed with the old parser. This keyword argument is used in the tests to actually compare the ASTs the new parser generates with those generated by the old parser.
116 lines
2.8 KiB
C
116 lines
2.8 KiB
C
#include <Python.h>
|
|
#include "pegen_interface.h"
|
|
|
|
PyObject *
|
|
_Py_parse_file(PyObject *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
static char *keywords[] = {"file", "mode", NULL};
|
|
char *filename;
|
|
char *mode_str = "exec";
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|s", keywords, &filename, &mode_str)) {
|
|
return NULL;
|
|
}
|
|
|
|
int mode;
|
|
if (strcmp(mode_str, "exec") == 0) {
|
|
mode = Py_file_input;
|
|
}
|
|
else if (strcmp(mode_str, "single") == 0) {
|
|
mode = Py_single_input;
|
|
}
|
|
else {
|
|
return PyErr_Format(PyExc_ValueError, "mode must be either 'exec' or 'single'");
|
|
}
|
|
|
|
PyArena *arena = PyArena_New();
|
|
if (arena == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
PyCompilerFlags flags = _PyCompilerFlags_INIT;
|
|
PyObject *result = NULL;
|
|
|
|
mod_ty res = PyPegen_ASTFromFile(filename, mode, &flags, arena);
|
|
if (res == NULL) {
|
|
goto error;
|
|
}
|
|
result = PyAST_mod2obj(res);
|
|
|
|
error:
|
|
PyArena_Free(arena);
|
|
return result;
|
|
}
|
|
|
|
PyObject *
|
|
_Py_parse_string(PyObject *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
static char *keywords[] = {"string", "mode", "oldparser", NULL};
|
|
char *the_string;
|
|
char *mode_str = "exec";
|
|
int oldparser = 0;
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|sp", keywords,
|
|
&the_string, &mode_str, &oldparser)) {
|
|
return NULL;
|
|
}
|
|
|
|
int mode;
|
|
if (strcmp(mode_str, "exec") == 0) {
|
|
mode = Py_file_input;
|
|
}
|
|
else if (strcmp(mode_str, "eval") == 0) {
|
|
mode = Py_eval_input;
|
|
}
|
|
else if (strcmp(mode_str, "single") == 0) {
|
|
mode = Py_single_input;
|
|
}
|
|
else {
|
|
return PyErr_Format(PyExc_ValueError, "mode must be either 'exec' or 'eval' or 'single'");
|
|
}
|
|
|
|
PyArena *arena = PyArena_New();
|
|
if (arena == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
PyObject *result = NULL;
|
|
|
|
PyCompilerFlags flags = _PyCompilerFlags_INIT;
|
|
flags.cf_flags = PyCF_IGNORE_COOKIE;
|
|
|
|
mod_ty res;
|
|
if (oldparser) {
|
|
res = PyParser_ASTFromString(the_string, "<string>", mode, &flags, arena);
|
|
}
|
|
else {
|
|
res = PyPegen_ASTFromString(the_string, mode, &flags, arena);
|
|
}
|
|
if (res == NULL) {
|
|
goto error;
|
|
}
|
|
result = PyAST_mod2obj(res);
|
|
|
|
error:
|
|
PyArena_Free(arena);
|
|
return result;
|
|
}
|
|
|
|
static PyMethodDef ParseMethods[] = {
|
|
{"parse_file", (PyCFunction)(void (*)(void))_Py_parse_file, METH_VARARGS|METH_KEYWORDS, "Parse a file."},
|
|
{"parse_string", (PyCFunction)(void (*)(void))_Py_parse_string, METH_VARARGS|METH_KEYWORDS,"Parse a string."},
|
|
{NULL, NULL, 0, NULL} /* Sentinel */
|
|
};
|
|
|
|
static struct PyModuleDef parsemodule = {
|
|
PyModuleDef_HEAD_INIT,
|
|
.m_name = "peg_parser",
|
|
.m_doc = "A parser.",
|
|
.m_methods = ParseMethods,
|
|
};
|
|
|
|
PyMODINIT_FUNC
|
|
PyInit__peg_parser(void)
|
|
{
|
|
return PyModule_Create(&parsemodule);
|
|
}
|