diff --git a/Grammar/python.gram b/Grammar/python.gram index 7c7366c7a212fa..b5920e9d6d4997 100644 --- a/Grammar/python.gram +++ b/Grammar/python.gram @@ -8,6 +8,8 @@ parse_start(Parser *p) { return start_rule(p); } + +// The end ''' start[mod_ty]: a=[statements] ENDMARKER { Module(a, NULL, p->arena) } diff --git a/Include/pegen_interface.h b/Include/pegen_interface.h index c48137fff04619..3a46b72d29a787 100644 --- a/Include/pegen_interface.h +++ b/Include/pegen_interface.h @@ -10,8 +10,8 @@ extern "C" { PyAPI_FUNC(mod_ty) PyPegen_ASTFromFile(const char *filename, PyArena *arena); PyAPI_FUNC(mod_ty) PyPegen_ASTFromString(const char *str, PyArena *arena); -PyAPI_FUNC(PyCodeObject *) PyPegen_CodeObjectFromFile(const char *filename, PyArena *arena); -PyAPI_FUNC(PyCodeObject *) PyPegen_CodeObjectFromString(const char *str, PyArena *arena); +PyAPI_FUNC(PyCodeObject *) PyPegen_CodeObjectFromFile(const char *filename); +PyAPI_FUNC(PyCodeObject *) PyPegen_CodeObjectFromString(const char *str); #ifdef __cplusplus } diff --git a/Modules/peg_parser.c b/Modules/peg_parser.c index 9be947ba88366b..a6e01c369a9456 100644 --- a/Modules/peg_parser.c +++ b/Modules/peg_parser.c @@ -15,13 +15,15 @@ _Py_parse_file(PyObject *self, PyObject *args) return NULL; } + PyObject *result = NULL; + mod_ty res = PyPegen_ASTFromFile(filename, arena); if (res == NULL) { - PyArena_Free(arena); - return NULL; + goto error; } - PyObject *result = PyAST_mod2obj(res); + result = PyAST_mod2obj(res); +error: PyArena_Free(arena); return result; } @@ -40,13 +42,15 @@ _Py_parse_string(PyObject *self, PyObject *args) return NULL; } + PyObject *result = NULL; + mod_ty res = PyPegen_ASTFromString(the_string, arena); if (res == NULL) { - PyArena_Free(arena); - return NULL; + goto error; } - PyObject *result = PyAST_mod2obj(res); + result = PyAST_mod2obj(res); +error: PyArena_Free(arena); return result; } diff --git a/Parser/pegen/parse.c b/Parser/pegen/parse.c index de7d64c2a1e38c..05bf0fe9347992 100644 --- a/Parser/pegen/parse.c +++ b/Parser/pegen/parse.c @@ -13564,3 +13564,5 @@ parse_start(Parser *p) { return start_rule(p); } + +// The end diff --git a/Parser/pegen/peg_api.c b/Parser/pegen/peg_api.c index 479028c37d4c61..5ed5cd4a9c0cbd 100644 --- a/Parser/pegen/peg_api.c +++ b/Parser/pegen/peg_api.c @@ -6,23 +6,81 @@ mod_ty PyPegen_ASTFromString(const char *str, PyArena *arena) { - return run_parser_from_string(str, parse_start, RAW_AST_OBJECT, arena); + PyObject *filename_ob = PyUnicode_FromString(""); + if (filename_ob == NULL) { + return NULL; + } + + mod_ty result = run_parser_from_string(str, parse_start, filename_ob, arena); + Py_XDECREF(filename_ob); + return result; } mod_ty PyPegen_ASTFromFile(const char *filename, PyArena *arena) { - return run_parser_from_file(filename, parse_start, RAW_AST_OBJECT, arena); + PyObject *filename_ob = PyUnicode_FromString(filename); + if (filename_ob == NULL) { + return NULL; + } + + mod_ty result = run_parser_from_file(filename, parse_start, filename_ob, arena); + Py_XDECREF(filename_ob); + return result; } PyCodeObject * -PyPegen_CodeObjectFromString(const char *str, PyArena *arena) +PyPegen_CodeObjectFromString(const char *str) { - return run_parser_from_string(str, parse_start, CODE_OBJECT, arena); + PyArena *arena = PyArena_New(); + if (arena == NULL) { + return NULL; + } + + PyCodeObject *result = NULL; + + PyObject *filename_ob = PyUnicode_FromString(""); + if (filename_ob == NULL) { + goto error; + } + + mod_ty res = PyPegen_ASTFromString(str, arena); + if (res == NULL) { + goto error; + } + + result = PyAST_CompileObject(res, filename_ob, NULL, -1, arena); + +error: + Py_XDECREF(filename_ob); + PyArena_Free(arena); + return result; } PyCodeObject * -PyPegen_CodeObjectFromFile(const char *file, PyArena *arena) +PyPegen_CodeObjectFromFile(const char *filename) { - return run_parser_from_file(file, parse_start, CODE_OBJECT, arena); + PyArena *arena = PyArena_New(); + if (arena == NULL) { + return NULL; + } + + PyCodeObject *result = NULL; + + PyObject *filename_ob = PyUnicode_FromString(filename); + if (filename_ob == NULL) { + goto error; + } + + mod_ty res = PyPegen_ASTFromFile(filename, arena); + if (res == NULL) { + goto error; + } + + result = PyAST_CompileObject(res, filename_ob, NULL, -1, arena); + +error: + Py_XDECREF(filename_ob); + PyArena_Free(arena); + return result; } diff --git a/Parser/pegen/pegen.c b/Parser/pegen/pegen.c index 66dd78499e0fd1..74f8e568a5a67f 100644 --- a/Parser/pegen/pegen.c +++ b/Parser/pegen/pegen.c @@ -536,8 +536,8 @@ Parser_New(struct tok_state *tok, mod_ty (*parse_func)(Parser *), int input_mode return p; } -void * -run_parser(Parser *p, int mode) +mod_ty +run_parser(Parser *p) { int error = setjmp(p->error_env); if (error) { @@ -559,23 +559,12 @@ run_parser(Parser *p, int mode) return NULL; } - void *result = NULL; - if (mode == CODE_OBJECT) { - result = PyAST_CompileObject(res, p->tok->filename, NULL, -1, p->arena); - } - else if (mode == AST_OBJECT) { - result = PyAST_mod2obj(res); - } - else { - result = res; - } - - return result; + return res; } -void * -run_parser_from_file(const char *filename, mod_ty (*parse_func)(Parser *), int mode, - PyArena *arena) +mod_ty +run_parser_from_file(const char *filename, mod_ty (*parse_func)(Parser *), + PyObject *filename_ob, PyArena *arena) { FILE *fp = fopen(filename, "rb"); if (fp == NULL) { @@ -583,65 +572,56 @@ run_parser_from_file(const char *filename, mod_ty (*parse_func)(Parser *), int m return NULL; } - PyObject *filename_ob = NULL; - if ((filename_ob = PyUnicode_FromString(filename)) == NULL) { - return NULL; - } - // From here on we need to clean up even if there's an error - void *result = NULL; + mod_ty result = NULL; struct tok_state *tok = PyTokenizer_FromFile(fp, NULL, NULL, NULL); if (tok == NULL) { goto error; } - - // Transfers ownership + // This transfers the ownership to the tokenizer tok->filename = filename_ob; - filename_ob = NULL; + Py_INCREF(filename_ob); Parser *p = Parser_New(tok, parse_func, FILE_INPUT, arena); if (p == NULL) { - PyTokenizer_Free(tok); - goto error; + goto after_tok_error; } - result = run_parser(p, mode); - + result = run_parser(p); Parser_Free(p); - PyTokenizer_Free(tok); +after_tok_error: + PyTokenizer_Free(tok); error: fclose(fp); - Py_XDECREF(filename_ob); return result; } -void * -run_parser_from_string(const char *str, mod_ty (*parse_func)(Parser *), int mode, +mod_ty +run_parser_from_string(const char *str, mod_ty (*parse_func)(Parser *), PyObject *filename_ob, PyArena *arena) { - void *result = NULL; struct tok_state *tok = PyTokenizer_FromString(str, 1); if (tok == NULL) { return NULL; } + // This transfers the ownership to the tokenizer + tok->filename = filename_ob; + Py_INCREF(filename_ob); - tok->filename = PyUnicode_FromString(""); - if (tok->filename == NULL) { - PyTokenizer_Free(tok); - return NULL; - } + // We need to clear up from here on + mod_ty result = NULL; Parser *p = Parser_New(tok, parse_func, STRING_INPUT, arena); if (p == NULL) { - PyTokenizer_Free(tok); - return NULL; + goto error; } - result = run_parser(p, mode); - + result = run_parser(p); Parser_Free(p); + +error: PyTokenizer_Free(tok); return result; } diff --git a/Parser/pegen/pegen.h b/Parser/pegen/pegen.h index 7ba70f9731219d..b33c332a316e45 100644 --- a/Parser/pegen/pegen.h +++ b/Parser/pegen/pegen.h @@ -14,13 +14,6 @@ enum INPUT_MODE { }; typedef enum INPUT_MODE INPUT_MODE; -enum MODE { - RAW_AST_OBJECT, - AST_OBJECT, - CODE_OBJECT -}; -typedef enum MODE MODE; - typedef struct _memo { int type; void *node; @@ -143,8 +136,8 @@ CHECK_CALL_NULL_ALLOWED(Parser *p, void *result) #define CHECK_NULL_ALLOWED(result) CHECK_CALL_NULL_ALLOWED(p, result) PyObject *new_identifier(Parser *, char *); -void *run_parser_from_file(const char *, mod_ty(*)(Parser *), int, PyArena *); -void *run_parser_from_string(const char *, mod_ty(*)(Parser *), int, PyArena *); +mod_ty run_parser_from_file(const char *, mod_ty(*)(Parser *), PyObject *, PyArena *); +mod_ty run_parser_from_string(const char *, mod_ty(*)(Parser *), PyObject *, PyArena *); asdl_seq *singleton_seq(Parser *, void *); asdl_seq *seq_insert_in_front(Parser *, void *, asdl_seq *); asdl_seq *seq_flatten(Parser *, asdl_seq *); diff --git a/Tools/peg_generator/peg_parser/pegen.c b/Tools/peg_generator/peg_parser/pegen.c index 9f0e50c49e8e96..c3a3329a96f3a8 100644 --- a/Tools/peg_generator/peg_parser/pegen.c +++ b/Tools/peg_generator/peg_parser/pegen.c @@ -536,8 +536,8 @@ Parser_New(struct tok_state *tok, mod_ty (*parse_func)(Parser *), int input_mode return p; } -void * -run_parser(Parser *p, int mode) +mod_ty +run_parser(Parser *p) { int error = setjmp(p->error_env); if (error) { @@ -559,23 +559,12 @@ run_parser(Parser *p, int mode) return NULL; } - void *result = NULL; - if (mode == CODE_OBJECT) { - result = PyAST_CompileObject(res, p->tok->filename, NULL, -1, p->arena); - } - else if (mode == AST_OBJECT) { - result = PyAST_mod2obj(res); - } - else { - result = res; - } - - return result; + return res; } -void * -run_parser_from_file(const char *filename, mod_ty (*parse_func)(Parser *), int mode, - PyArena *arena) +mod_ty +run_parser_from_file(const char *filename, mod_ty (*parse_func)(Parser *), + PyObject *filename_ob, PyArena *arena) { FILE *fp = fopen(filename, "rb"); if (fp == NULL) { @@ -583,65 +572,56 @@ run_parser_from_file(const char *filename, mod_ty (*parse_func)(Parser *), int m return NULL; } - PyObject *filename_ob = NULL; - if ((filename_ob = PyUnicode_FromString(filename)) == NULL) { - return NULL; - } - // From here on we need to clean up even if there's an error - void *result = NULL; + mod_ty result = NULL; struct tok_state *tok = PyTokenizer_FromFile(fp, NULL, NULL, NULL); if (tok == NULL) { goto error; } - - // Transfers ownership + // This transfers the ownership to the tokenizer tok->filename = filename_ob; - filename_ob = NULL; + Py_INCREF(filename_ob); Parser *p = Parser_New(tok, parse_func, FILE_INPUT, arena); if (p == NULL) { - PyTokenizer_Free(tok); - goto error; + goto after_tok_error; } - result = run_parser(p, mode); - + result = run_parser(p); Parser_Free(p); - PyTokenizer_Free(tok); +after_tok_error: + PyTokenizer_Free(tok); error: fclose(fp); - Py_XDECREF(filename_ob); return result; } -void * -run_parser_from_string(const char *str, mod_ty (*parse_func)(Parser *), int mode, +mod_ty +run_parser_from_string(const char *str, mod_ty (*parse_func)(Parser *), PyObject *filename_ob, PyArena *arena) { - void *result = NULL; struct tok_state *tok = PyTokenizer_FromString(str, 1); if (tok == NULL) { return NULL; } + // This transfers the ownership to the tokenizer + tok->filename = filename_ob; + Py_INCREF(filename_ob); - tok->filename = PyUnicode_FromString(""); - if (tok->filename == NULL) { - PyTokenizer_Free(tok); - return NULL; - } + // We need to clear up from here on + mod_ty result = NULL; Parser *p = Parser_New(tok, parse_func, STRING_INPUT, arena); if (p == NULL) { - PyTokenizer_Free(tok); - return NULL; + goto error; } - result = run_parser(p, mode); - + result = run_parser(p); Parser_Free(p); + +error: PyTokenizer_Free(tok); return result; } diff --git a/Tools/peg_generator/peg_parser/pegen.h b/Tools/peg_generator/peg_parser/pegen.h index 32c770ca978dae..0c9b4639039191 100644 --- a/Tools/peg_generator/peg_parser/pegen.h +++ b/Tools/peg_generator/peg_parser/pegen.h @@ -14,13 +14,6 @@ enum INPUT_MODE { }; typedef enum INPUT_MODE INPUT_MODE; -enum MODE { - RAW_AST_OBJECT, - AST_OBJECT, - CODE_OBJECT, -}; -typedef enum MODE MODE; - typedef struct _memo { int type; void *node; @@ -143,8 +136,8 @@ CHECK_CALL_NULL_ALLOWED(Parser *p, void *result) #define CHECK_NULL_ALLOWED(result) CHECK_CALL_NULL_ALLOWED(p, result) PyObject *new_identifier(Parser *, char *); -void *run_parser_from_file(const char *, mod_ty(*)(Parser *), int, PyArena *); -void *run_parser_from_string(const char *, mod_ty(*)(Parser *), int, PyArena *); +mod_ty run_parser_from_file(const char *, mod_ty(*)(Parser *), PyObject *, PyArena *); +mod_ty run_parser_from_string(const char *, mod_ty(*)(Parser *), PyObject *, PyArena *); asdl_seq *singleton_seq(Parser *, void *); asdl_seq *seq_insert_in_front(Parser *, void *, asdl_seq *); asdl_seq *seq_flatten(Parser *, asdl_seq *); diff --git a/Tools/peg_generator/pegen/c_generator.py b/Tools/peg_generator/pegen/c_generator.py index 14e1aeb9838feb..c0495276d5cfe2 100644 --- a/Tools/peg_generator/pegen/c_generator.py +++ b/Tools/peg_generator/pegen/c_generator.py @@ -30,28 +30,53 @@ """ EXTENSION_SUFFIX = """ +PyObject * +_build_return_object(mod_ty module, int mode, PyObject *filename_ob, PyArena *arena) +{ + if (mode == 2) { + return (PyObject *)PyAST_CompileObject(module, filename_ob, NULL, -1, arena); + } else if (mode == 1) { + return PyAST_mod2obj(module); + } else { + Py_INCREF(Py_None); + return Py_None; + } +} + static PyObject * parse_file(PyObject *self, PyObject *args, PyObject *kwds) { static char *keywords[] = {"file", "mode", NULL}; const char *filename; int mode = %(mode)s; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|i", keywords, &filename, &mode)) + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|i", keywords, &filename, &mode)) { return NULL; - if (mode < 0 || mode > %(mode)s) + } + if (mode < 0 || mode > %(mode)s) { return PyErr_Format(PyExc_ValueError, "Bad mode, must be 0 <= mode <= %(mode)s"); + } PyArena *arena = PyArena_New(); if (arena == NULL) { return NULL; } - void *result = run_parser_from_file(filename, start_rule, mode, arena); - if (result != NULL && mode == 0) { - result = Py_None; - Py_INCREF(result); + PyObject *result = NULL; + + PyObject *filename_ob = PyUnicode_FromString(filename); + if (filename_ob == NULL) { + goto error; } + mod_ty res = run_parser_from_file(filename, start_rule, filename_ob, arena); + if (res == NULL) { + goto error; + } + + result = _build_return_object(res, mode, filename_ob, arena); + +error: + Py_XDECREF(filename_ob); PyArena_Free(arena); return result; } @@ -62,22 +87,33 @@ static char *keywords[] = {"str", "mode", NULL}; const char *the_string; int mode = %(mode)s; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|i", keywords, &the_string, &mode)) + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|i", keywords, &the_string, &mode)) { return NULL; - if (mode < 0 || mode > %(mode)s) + } + if (mode < 0 || mode > %(mode)s) { return PyErr_Format(PyExc_ValueError, "Bad mode, must be 0 <= mode <= %(mode)s"); + } PyArena *arena = PyArena_New(); if (arena == NULL) { return NULL; } - void *result = run_parser_from_string(the_string, start_rule, mode, arena); - if (result != NULL && mode == 0) { - result = Py_None; - Py_INCREF(result); + PyObject *result = NULL; + + PyObject *filename_ob = PyUnicode_FromString(""); + if (filename_ob == NULL) { + goto error; + } + + mod_ty res = run_parser_from_string(the_string, start_rule, filename_ob, arena); + if (res == NULL) { + goto error; } + result = _build_return_object(res, mode, filename_ob, arena); +error: + Py_XDECREF(filename_ob); PyArena_Free(arena); return result; }