| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1 | #include <Python.h> | 
| Nick Coghlan | 1e7b858 | 2021-04-29 15:58:44 +1000 | [diff] [blame] | 2 | #include "pycore_ast.h"           // _PyAST_Validate(), | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 3 | #include <errcode.h> | 
| Pablo Galindo | 1ed83ad | 2020-06-11 17:30:46 +0100 | [diff] [blame] | 4 | #include "tokenizer.h" | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 5 |  | 
|  | 6 | #include "pegen.h" | 
| Pablo Galindo | 1ed83ad | 2020-06-11 17:30:46 +0100 | [diff] [blame] | 7 | #include "string_parser.h" | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 8 |  | 
| Guido van Rossum | c001c09 | 2020-04-30 12:12:19 -0700 | [diff] [blame] | 9 | PyObject * | 
| Serhiy Storchaka | c43317d | 2021-06-12 20:44:32 +0300 | [diff] [blame] | 10 | _PyPegen_new_type_comment(Parser *p, const char *s) | 
| Guido van Rossum | c001c09 | 2020-04-30 12:12:19 -0700 | [diff] [blame] | 11 | { | 
|  | 12 | PyObject *res = PyUnicode_DecodeUTF8(s, strlen(s), NULL); | 
|  | 13 | if (res == NULL) { | 
|  | 14 | return NULL; | 
|  | 15 | } | 
| Victor Stinner | 8370e07 | 2021-03-24 02:23:01 +0100 | [diff] [blame] | 16 | if (_PyArena_AddPyObject(p->arena, res) < 0) { | 
| Guido van Rossum | c001c09 | 2020-04-30 12:12:19 -0700 | [diff] [blame] | 17 | Py_DECREF(res); | 
|  | 18 | return NULL; | 
|  | 19 | } | 
|  | 20 | return res; | 
|  | 21 | } | 
|  | 22 |  | 
|  | 23 | arg_ty | 
|  | 24 | _PyPegen_add_type_comment_to_arg(Parser *p, arg_ty a, Token *tc) | 
|  | 25 | { | 
|  | 26 | if (tc == NULL) { | 
|  | 27 | return a; | 
|  | 28 | } | 
| Serhiy Storchaka | c43317d | 2021-06-12 20:44:32 +0300 | [diff] [blame] | 29 | const char *bytes = PyBytes_AsString(tc->bytes); | 
| Guido van Rossum | c001c09 | 2020-04-30 12:12:19 -0700 | [diff] [blame] | 30 | if (bytes == NULL) { | 
|  | 31 | return NULL; | 
|  | 32 | } | 
|  | 33 | PyObject *tco = _PyPegen_new_type_comment(p, bytes); | 
|  | 34 | if (tco == NULL) { | 
|  | 35 | return NULL; | 
|  | 36 | } | 
| Victor Stinner | d27f8d2 | 2021-04-07 21:34:22 +0200 | [diff] [blame] | 37 | return _PyAST_arg(a->arg, a->annotation, tco, | 
|  | 38 | a->lineno, a->col_offset, a->end_lineno, a->end_col_offset, | 
|  | 39 | p->arena); | 
| Guido van Rossum | c001c09 | 2020-04-30 12:12:19 -0700 | [diff] [blame] | 40 | } | 
|  | 41 |  | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 42 | static int | 
|  | 43 | init_normalization(Parser *p) | 
|  | 44 | { | 
| Lysandros Nikolaou | ebebb64 | 2020-04-23 18:36:06 +0300 | [diff] [blame] | 45 | if (p->normalize) { | 
|  | 46 | return 1; | 
|  | 47 | } | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 48 | PyObject *m = PyImport_ImportModuleNoBlock("unicodedata"); | 
|  | 49 | if (!m) | 
|  | 50 | { | 
|  | 51 | return 0; | 
|  | 52 | } | 
|  | 53 | p->normalize = PyObject_GetAttrString(m, "normalize"); | 
|  | 54 | Py_DECREF(m); | 
|  | 55 | if (!p->normalize) | 
|  | 56 | { | 
|  | 57 | return 0; | 
|  | 58 | } | 
|  | 59 | return 1; | 
|  | 60 | } | 
|  | 61 |  | 
| Pablo Galindo | 2b74c83 | 2020-04-27 18:02:07 +0100 | [diff] [blame] | 62 | /* Checks if the NOTEQUAL token is valid given the current parser flags | 
|  | 63 | 0 indicates success and nonzero indicates failure (an exception may be set) */ | 
|  | 64 | int | 
| Pablo Galindo | 06f8c33 | 2020-10-30 23:48:42 +0000 | [diff] [blame] | 65 | _PyPegen_check_barry_as_flufl(Parser *p, Token* t) { | 
| Pablo Galindo | 2b74c83 | 2020-04-27 18:02:07 +0100 | [diff] [blame] | 66 | assert(t->bytes != NULL); | 
|  | 67 | assert(t->type == NOTEQUAL); | 
|  | 68 |  | 
| Serhiy Storchaka | c43317d | 2021-06-12 20:44:32 +0300 | [diff] [blame] | 69 | const char* tok_str = PyBytes_AS_STRING(t->bytes); | 
| Pablo Galindo | fb61c42 | 2020-06-15 14:23:43 +0100 | [diff] [blame] | 70 | if (p->flags & PyPARSE_BARRY_AS_BDFL && strcmp(tok_str, "<>") != 0) { | 
| Pablo Galindo | 2b74c83 | 2020-04-27 18:02:07 +0100 | [diff] [blame] | 71 | RAISE_SYNTAX_ERROR("with Barry as BDFL, use '<>' instead of '!='"); | 
|  | 72 | return -1; | 
| Pablo Galindo | fb61c42 | 2020-06-15 14:23:43 +0100 | [diff] [blame] | 73 | } | 
|  | 74 | if (!(p->flags & PyPARSE_BARRY_AS_BDFL)) { | 
| Pablo Galindo | 2b74c83 | 2020-04-27 18:02:07 +0100 | [diff] [blame] | 75 | return strcmp(tok_str, "!="); | 
|  | 76 | } | 
|  | 77 | return 0; | 
|  | 78 | } | 
|  | 79 |  | 
| Pablo Galindo Salgado | b977f85 | 2021-07-27 18:52:32 +0100 | [diff] [blame] | 80 | int | 
|  | 81 | _PyPegen_check_legacy_stmt(Parser *p, expr_ty name) { | 
|  | 82 | assert(name->kind == Name_kind); | 
|  | 83 | const char* candidates[2] = {"print", "exec"}; | 
|  | 84 | for (int i=0; i<2; i++) { | 
|  | 85 | if (PyUnicode_CompareWithASCIIString(name->v.Name.id, candidates[i]) == 0) { | 
|  | 86 | return 1; | 
|  | 87 | } | 
|  | 88 | } | 
|  | 89 | return 0; | 
|  | 90 | } | 
|  | 91 |  | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 92 | PyObject * | 
| Serhiy Storchaka | c43317d | 2021-06-12 20:44:32 +0300 | [diff] [blame] | 93 | _PyPegen_new_identifier(Parser *p, const char *n) | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 94 | { | 
|  | 95 | PyObject *id = PyUnicode_DecodeUTF8(n, strlen(n), NULL); | 
|  | 96 | if (!id) { | 
|  | 97 | goto error; | 
|  | 98 | } | 
|  | 99 | /* PyUnicode_DecodeUTF8 should always return a ready string. */ | 
|  | 100 | assert(PyUnicode_IS_READY(id)); | 
|  | 101 | /* Check whether there are non-ASCII characters in the | 
|  | 102 | identifier; if so, normalize to NFKC. */ | 
|  | 103 | if (!PyUnicode_IS_ASCII(id)) | 
|  | 104 | { | 
|  | 105 | PyObject *id2; | 
| Lysandros Nikolaou | ebebb64 | 2020-04-23 18:36:06 +0300 | [diff] [blame] | 106 | if (!init_normalization(p)) | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 107 | { | 
|  | 108 | Py_DECREF(id); | 
|  | 109 | goto error; | 
|  | 110 | } | 
|  | 111 | PyObject *form = PyUnicode_InternFromString("NFKC"); | 
|  | 112 | if (form == NULL) | 
|  | 113 | { | 
|  | 114 | Py_DECREF(id); | 
|  | 115 | goto error; | 
|  | 116 | } | 
|  | 117 | PyObject *args[2] = {form, id}; | 
|  | 118 | id2 = _PyObject_FastCall(p->normalize, args, 2); | 
|  | 119 | Py_DECREF(id); | 
|  | 120 | Py_DECREF(form); | 
|  | 121 | if (!id2) { | 
|  | 122 | goto error; | 
|  | 123 | } | 
|  | 124 | if (!PyUnicode_Check(id2)) | 
|  | 125 | { | 
|  | 126 | PyErr_Format(PyExc_TypeError, | 
|  | 127 | "unicodedata.normalize() must return a string, not " | 
|  | 128 | "%.200s", | 
|  | 129 | _PyType_Name(Py_TYPE(id2))); | 
|  | 130 | Py_DECREF(id2); | 
|  | 131 | goto error; | 
|  | 132 | } | 
|  | 133 | id = id2; | 
|  | 134 | } | 
|  | 135 | PyUnicode_InternInPlace(&id); | 
| Victor Stinner | 8370e07 | 2021-03-24 02:23:01 +0100 | [diff] [blame] | 136 | if (_PyArena_AddPyObject(p->arena, id) < 0) | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 137 | { | 
|  | 138 | Py_DECREF(id); | 
|  | 139 | goto error; | 
|  | 140 | } | 
|  | 141 | return id; | 
|  | 142 |  | 
|  | 143 | error: | 
|  | 144 | p->error_indicator = 1; | 
|  | 145 | return NULL; | 
|  | 146 | } | 
|  | 147 |  | 
|  | 148 | static PyObject * | 
|  | 149 | _create_dummy_identifier(Parser *p) | 
|  | 150 | { | 
|  | 151 | return _PyPegen_new_identifier(p, ""); | 
|  | 152 | } | 
|  | 153 |  | 
|  | 154 | static inline Py_ssize_t | 
| Pablo Galindo | 51c5896 | 2020-06-16 16:49:43 +0100 | [diff] [blame] | 155 | byte_offset_to_character_offset(PyObject *line, Py_ssize_t col_offset) | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 156 | { | 
|  | 157 | const char *str = PyUnicode_AsUTF8(line); | 
| Lysandros Nikolaou | ebebb64 | 2020-04-23 18:36:06 +0300 | [diff] [blame] | 158 | if (!str) { | 
|  | 159 | return 0; | 
|  | 160 | } | 
| Pablo Galindo | 123ff26 | 2021-03-22 16:24:39 +0000 | [diff] [blame] | 161 | Py_ssize_t len = strlen(str); | 
| Pablo Galindo | b86ed8e | 2021-04-12 16:59:30 +0100 | [diff] [blame] | 162 | if (col_offset > len + 1) { | 
|  | 163 | col_offset = len + 1; | 
| Pablo Galindo | 123ff26 | 2021-03-22 16:24:39 +0000 | [diff] [blame] | 164 | } | 
|  | 165 | assert(col_offset >= 0); | 
| Batuhan Taskaya | 76c1b4d | 2020-05-01 16:13:43 +0300 | [diff] [blame] | 166 | PyObject *text = PyUnicode_DecodeUTF8(str, col_offset, "replace"); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 167 | if (!text) { | 
|  | 168 | return 0; | 
|  | 169 | } | 
|  | 170 | Py_ssize_t size = PyUnicode_GET_LENGTH(text); | 
|  | 171 | Py_DECREF(text); | 
|  | 172 | return size; | 
|  | 173 | } | 
|  | 174 |  | 
|  | 175 | const char * | 
|  | 176 | _PyPegen_get_expr_name(expr_ty e) | 
|  | 177 | { | 
| Pablo Galindo | 9f49590 | 2020-06-08 02:57:00 +0100 | [diff] [blame] | 178 | assert(e != NULL); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 179 | switch (e->kind) { | 
|  | 180 | case Attribute_kind: | 
|  | 181 | return "attribute"; | 
|  | 182 | case Subscript_kind: | 
|  | 183 | return "subscript"; | 
|  | 184 | case Starred_kind: | 
|  | 185 | return "starred"; | 
|  | 186 | case Name_kind: | 
|  | 187 | return "name"; | 
|  | 188 | case List_kind: | 
|  | 189 | return "list"; | 
|  | 190 | case Tuple_kind: | 
|  | 191 | return "tuple"; | 
|  | 192 | case Lambda_kind: | 
|  | 193 | return "lambda"; | 
|  | 194 | case Call_kind: | 
|  | 195 | return "function call"; | 
|  | 196 | case BoolOp_kind: | 
|  | 197 | case BinOp_kind: | 
|  | 198 | case UnaryOp_kind: | 
| Pablo Galindo | b86ed8e | 2021-04-12 16:59:30 +0100 | [diff] [blame] | 199 | return "expression"; | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 200 | case GeneratorExp_kind: | 
|  | 201 | return "generator expression"; | 
|  | 202 | case Yield_kind: | 
|  | 203 | case YieldFrom_kind: | 
|  | 204 | return "yield expression"; | 
|  | 205 | case Await_kind: | 
|  | 206 | return "await expression"; | 
|  | 207 | case ListComp_kind: | 
|  | 208 | return "list comprehension"; | 
|  | 209 | case SetComp_kind: | 
|  | 210 | return "set comprehension"; | 
|  | 211 | case DictComp_kind: | 
|  | 212 | return "dict comprehension"; | 
|  | 213 | case Dict_kind: | 
| Pablo Galindo | b86ed8e | 2021-04-12 16:59:30 +0100 | [diff] [blame] | 214 | return "dict literal"; | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 215 | case Set_kind: | 
|  | 216 | return "set display"; | 
|  | 217 | case JoinedStr_kind: | 
|  | 218 | case FormattedValue_kind: | 
|  | 219 | return "f-string expression"; | 
|  | 220 | case Constant_kind: { | 
|  | 221 | PyObject *value = e->v.Constant.value; | 
|  | 222 | if (value == Py_None) { | 
|  | 223 | return "None"; | 
|  | 224 | } | 
|  | 225 | if (value == Py_False) { | 
|  | 226 | return "False"; | 
|  | 227 | } | 
|  | 228 | if (value == Py_True) { | 
|  | 229 | return "True"; | 
|  | 230 | } | 
|  | 231 | if (value == Py_Ellipsis) { | 
| Pablo Galindo | 3283bf4 | 2021-06-03 22:22:28 +0100 | [diff] [blame] | 232 | return "ellipsis"; | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 233 | } | 
|  | 234 | return "literal"; | 
|  | 235 | } | 
|  | 236 | case Compare_kind: | 
|  | 237 | return "comparison"; | 
|  | 238 | case IfExp_kind: | 
|  | 239 | return "conditional expression"; | 
|  | 240 | case NamedExpr_kind: | 
|  | 241 | return "named expression"; | 
|  | 242 | default: | 
|  | 243 | PyErr_Format(PyExc_SystemError, | 
|  | 244 | "unexpected expression in assignment %d (line %d)", | 
|  | 245 | e->kind, e->lineno); | 
|  | 246 | return NULL; | 
|  | 247 | } | 
|  | 248 | } | 
|  | 249 |  | 
| Lysandros Nikolaou | ebebb64 | 2020-04-23 18:36:06 +0300 | [diff] [blame] | 250 | static int | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 251 | raise_decode_error(Parser *p) | 
|  | 252 | { | 
| Lysandros Nikolaou | ebebb64 | 2020-04-23 18:36:06 +0300 | [diff] [blame] | 253 | assert(PyErr_Occurred()); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 254 | const char *errtype = NULL; | 
|  | 255 | if (PyErr_ExceptionMatches(PyExc_UnicodeError)) { | 
|  | 256 | errtype = "unicode error"; | 
|  | 257 | } | 
|  | 258 | else if (PyErr_ExceptionMatches(PyExc_ValueError)) { | 
|  | 259 | errtype = "value error"; | 
|  | 260 | } | 
|  | 261 | if (errtype) { | 
| Pablo Galindo | fb61c42 | 2020-06-15 14:23:43 +0100 | [diff] [blame] | 262 | PyObject *type; | 
|  | 263 | PyObject *value; | 
|  | 264 | PyObject *tback; | 
|  | 265 | PyObject *errstr; | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 266 | PyErr_Fetch(&type, &value, &tback); | 
|  | 267 | errstr = PyObject_Str(value); | 
|  | 268 | if (errstr) { | 
|  | 269 | RAISE_SYNTAX_ERROR("(%s) %U", errtype, errstr); | 
|  | 270 | Py_DECREF(errstr); | 
|  | 271 | } | 
|  | 272 | else { | 
|  | 273 | PyErr_Clear(); | 
|  | 274 | RAISE_SYNTAX_ERROR("(%s) unknown error", errtype); | 
|  | 275 | } | 
|  | 276 | Py_XDECREF(type); | 
|  | 277 | Py_XDECREF(value); | 
|  | 278 | Py_XDECREF(tback); | 
|  | 279 | } | 
| Lysandros Nikolaou | ebebb64 | 2020-04-23 18:36:06 +0300 | [diff] [blame] | 280 |  | 
|  | 281 | return -1; | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 282 | } | 
|  | 283 |  | 
| Pablo Galindo | d6d6371 | 2021-01-19 23:59:33 +0000 | [diff] [blame] | 284 | static inline void | 
|  | 285 | raise_unclosed_parentheses_error(Parser *p) { | 
|  | 286 | int error_lineno = p->tok->parenlinenostack[p->tok->level-1]; | 
|  | 287 | int error_col = p->tok->parencolstack[p->tok->level-1]; | 
|  | 288 | RAISE_ERROR_KNOWN_LOCATION(p, PyExc_SyntaxError, | 
| Pablo Galindo | a77aac4 | 2021-04-23 14:27:05 +0100 | [diff] [blame] | 289 | error_lineno, error_col, error_lineno, -1, | 
| Pablo Galindo | d6d6371 | 2021-01-19 23:59:33 +0000 | [diff] [blame] | 290 | "'%c' was never closed", | 
|  | 291 | p->tok->parenstack[p->tok->level-1]); | 
|  | 292 | } | 
|  | 293 |  | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 294 | static void | 
|  | 295 | raise_tokenizer_init_error(PyObject *filename) | 
|  | 296 | { | 
|  | 297 | if (!(PyErr_ExceptionMatches(PyExc_LookupError) | 
| Miss Islington (bot) | 133cddf | 2021-06-14 10:07:52 -0700 | [diff] [blame] | 298 | || PyErr_ExceptionMatches(PyExc_SyntaxError) | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 299 | || PyErr_ExceptionMatches(PyExc_ValueError) | 
|  | 300 | || PyErr_ExceptionMatches(PyExc_UnicodeDecodeError))) { | 
|  | 301 | return; | 
|  | 302 | } | 
| Lysandros Nikolaou | ebebb64 | 2020-04-23 18:36:06 +0300 | [diff] [blame] | 303 | PyObject *errstr = NULL; | 
|  | 304 | PyObject *tuple = NULL; | 
| Pablo Galindo | fb61c42 | 2020-06-15 14:23:43 +0100 | [diff] [blame] | 305 | PyObject *type; | 
|  | 306 | PyObject *value; | 
|  | 307 | PyObject *tback; | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 308 | PyErr_Fetch(&type, &value, &tback); | 
|  | 309 | errstr = PyObject_Str(value); | 
| Lysandros Nikolaou | ebebb64 | 2020-04-23 18:36:06 +0300 | [diff] [blame] | 310 | if (!errstr) { | 
|  | 311 | goto error; | 
|  | 312 | } | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 313 |  | 
| Lysandros Nikolaou | ebebb64 | 2020-04-23 18:36:06 +0300 | [diff] [blame] | 314 | PyObject *tmp = Py_BuildValue("(OiiO)", filename, 0, -1, Py_None); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 315 | if (!tmp) { | 
|  | 316 | goto error; | 
|  | 317 | } | 
|  | 318 |  | 
| Lysandros Nikolaou | ebebb64 | 2020-04-23 18:36:06 +0300 | [diff] [blame] | 319 | tuple = PyTuple_Pack(2, errstr, tmp); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 320 | Py_DECREF(tmp); | 
|  | 321 | if (!value) { | 
|  | 322 | goto error; | 
|  | 323 | } | 
| Lysandros Nikolaou | ebebb64 | 2020-04-23 18:36:06 +0300 | [diff] [blame] | 324 | PyErr_SetObject(PyExc_SyntaxError, tuple); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 325 |  | 
|  | 326 | error: | 
|  | 327 | Py_XDECREF(type); | 
|  | 328 | Py_XDECREF(value); | 
|  | 329 | Py_XDECREF(tback); | 
| Lysandros Nikolaou | ebebb64 | 2020-04-23 18:36:06 +0300 | [diff] [blame] | 330 | Py_XDECREF(errstr); | 
|  | 331 | Py_XDECREF(tuple); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 332 | } | 
|  | 333 |  | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 334 | static int | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 335 | tokenizer_error(Parser *p) | 
|  | 336 | { | 
|  | 337 | if (PyErr_Occurred()) { | 
|  | 338 | return -1; | 
|  | 339 | } | 
|  | 340 |  | 
|  | 341 | const char *msg = NULL; | 
|  | 342 | PyObject* errtype = PyExc_SyntaxError; | 
| Pablo Galindo | 96eeff5 | 2021-03-22 17:28:11 +0000 | [diff] [blame] | 343 | Py_ssize_t col_offset = -1; | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 344 | switch (p->tok->done) { | 
|  | 345 | case E_TOKEN: | 
|  | 346 | msg = "invalid token"; | 
|  | 347 | break; | 
| Lysandros Nikolaou | d55133f | 2020-04-28 03:23:35 +0300 | [diff] [blame] | 348 | case E_EOF: | 
| Pablo Galindo | d6d6371 | 2021-01-19 23:59:33 +0000 | [diff] [blame] | 349 | if (p->tok->level) { | 
|  | 350 | raise_unclosed_parentheses_error(p); | 
|  | 351 | } else { | 
|  | 352 | RAISE_SYNTAX_ERROR("unexpected EOF while parsing"); | 
|  | 353 | } | 
| Batuhan Taskaya | 76c1b4d | 2020-05-01 16:13:43 +0300 | [diff] [blame] | 354 | return -1; | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 355 | case E_DEDENT: | 
| Batuhan Taskaya | 76c1b4d | 2020-05-01 16:13:43 +0300 | [diff] [blame] | 356 | RAISE_INDENTATION_ERROR("unindent does not match any outer indentation level"); | 
|  | 357 | return -1; | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 358 | case E_INTR: | 
|  | 359 | if (!PyErr_Occurred()) { | 
|  | 360 | PyErr_SetNone(PyExc_KeyboardInterrupt); | 
|  | 361 | } | 
|  | 362 | return -1; | 
|  | 363 | case E_NOMEM: | 
|  | 364 | PyErr_NoMemory(); | 
|  | 365 | return -1; | 
|  | 366 | case E_TABSPACE: | 
|  | 367 | errtype = PyExc_TabError; | 
|  | 368 | msg = "inconsistent use of tabs and spaces in indentation"; | 
|  | 369 | break; | 
|  | 370 | case E_TOODEEP: | 
|  | 371 | errtype = PyExc_IndentationError; | 
|  | 372 | msg = "too many levels of indentation"; | 
|  | 373 | break; | 
| Łukasz Langa | 5c9cab5 | 2021-10-19 22:31:18 +0200 | [diff] [blame^] | 374 | case E_LINECONT: { | 
|  | 375 | char* loc = strrchr(p->tok->buf, '\n'); | 
|  | 376 | const char* last_char = p->tok->cur - 1; | 
|  | 377 | if (loc != NULL && loc != last_char) { | 
|  | 378 | col_offset = p->tok->cur - loc - 1; | 
|  | 379 | p->tok->buf = loc; | 
|  | 380 | } else { | 
|  | 381 | col_offset = last_char - p->tok->buf - 1; | 
|  | 382 | } | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 383 | msg = "unexpected character after line continuation character"; | 
|  | 384 | break; | 
| Łukasz Langa | 5c9cab5 | 2021-10-19 22:31:18 +0200 | [diff] [blame^] | 385 | } | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 386 | default: | 
|  | 387 | msg = "unknown parsing error"; | 
|  | 388 | } | 
|  | 389 |  | 
| Pablo Galindo | a77aac4 | 2021-04-23 14:27:05 +0100 | [diff] [blame] | 390 | RAISE_ERROR_KNOWN_LOCATION(p, errtype, p->tok->lineno, col_offset, p->tok->lineno, -1, msg); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 391 | return -1; | 
|  | 392 | } | 
|  | 393 |  | 
|  | 394 | void * | 
| Lysandros Nikolaou | a15c9b3 | 2020-05-13 22:36:27 +0300 | [diff] [blame] | 395 | _PyPegen_raise_error(Parser *p, PyObject *errtype, const char *errmsg, ...) | 
|  | 396 | { | 
|  | 397 | Token *t = p->known_err_token != NULL ? p->known_err_token : p->tokens[p->fill - 1]; | 
| Pablo Galindo | 51c5896 | 2020-06-16 16:49:43 +0100 | [diff] [blame] | 398 | Py_ssize_t col_offset; | 
| Pablo Galindo | a77aac4 | 2021-04-23 14:27:05 +0100 | [diff] [blame] | 399 | Py_ssize_t end_col_offset = -1; | 
| Lysandros Nikolaou | a15c9b3 | 2020-05-13 22:36:27 +0300 | [diff] [blame] | 400 | if (t->col_offset == -1) { | 
|  | 401 | col_offset = Py_SAFE_DOWNCAST(p->tok->cur - p->tok->buf, | 
|  | 402 | intptr_t, int); | 
|  | 403 | } else { | 
|  | 404 | col_offset = t->col_offset + 1; | 
|  | 405 | } | 
|  | 406 |  | 
| Pablo Galindo | a77aac4 | 2021-04-23 14:27:05 +0100 | [diff] [blame] | 407 | if (t->end_col_offset != -1) { | 
|  | 408 | end_col_offset = t->end_col_offset + 1; | 
|  | 409 | } | 
|  | 410 |  | 
| Lysandros Nikolaou | a15c9b3 | 2020-05-13 22:36:27 +0300 | [diff] [blame] | 411 | va_list va; | 
|  | 412 | va_start(va, errmsg); | 
| Pablo Galindo | a77aac4 | 2021-04-23 14:27:05 +0100 | [diff] [blame] | 413 | _PyPegen_raise_error_known_location(p, errtype, t->lineno, col_offset, t->end_lineno, end_col_offset, errmsg, va); | 
| Lysandros Nikolaou | a15c9b3 | 2020-05-13 22:36:27 +0300 | [diff] [blame] | 414 | va_end(va); | 
|  | 415 |  | 
|  | 416 | return NULL; | 
|  | 417 | } | 
|  | 418 |  | 
| Lysandros Nikolaou | e5fe509 | 2021-01-14 23:36:30 +0200 | [diff] [blame] | 419 | static PyObject * | 
|  | 420 | get_error_line(Parser *p, Py_ssize_t lineno) | 
|  | 421 | { | 
| Pablo Galindo | 123ff26 | 2021-03-22 16:24:39 +0000 | [diff] [blame] | 422 | /* If the file descriptor is interactive, the source lines of the current | 
|  | 423 | * (multi-line) statement are stored in p->tok->interactive_src_start. | 
|  | 424 | * If not, we're parsing from a string, which means that the whole source | 
|  | 425 | * is stored in p->tok->str. */ | 
| Lysandros Nikolaou | e5fe509 | 2021-01-14 23:36:30 +0200 | [diff] [blame] | 426 | assert(p->tok->fp == NULL || p->tok->fp == stdin); | 
|  | 427 |  | 
| Pablo Galindo | cd8dcbc | 2021-03-14 04:38:40 +0100 | [diff] [blame] | 428 | char *cur_line = p->tok->fp_interactive ? p->tok->interactive_src_start : p->tok->str; | 
|  | 429 |  | 
| Lysandros Nikolaou | e5fe509 | 2021-01-14 23:36:30 +0200 | [diff] [blame] | 430 | for (int i = 0; i < lineno - 1; i++) { | 
|  | 431 | cur_line = strchr(cur_line, '\n') + 1; | 
|  | 432 | } | 
|  | 433 |  | 
|  | 434 | char *next_newline; | 
|  | 435 | if ((next_newline = strchr(cur_line, '\n')) == NULL) { // This is the last line | 
|  | 436 | next_newline = cur_line + strlen(cur_line); | 
|  | 437 | } | 
|  | 438 | return PyUnicode_DecodeUTF8(cur_line, next_newline - cur_line, "replace"); | 
|  | 439 | } | 
|  | 440 |  | 
| Lysandros Nikolaou | a15c9b3 | 2020-05-13 22:36:27 +0300 | [diff] [blame] | 441 | void * | 
|  | 442 | _PyPegen_raise_error_known_location(Parser *p, PyObject *errtype, | 
| Pablo Galindo | 51c5896 | 2020-06-16 16:49:43 +0100 | [diff] [blame] | 443 | Py_ssize_t lineno, Py_ssize_t col_offset, | 
| Pablo Galindo | a77aac4 | 2021-04-23 14:27:05 +0100 | [diff] [blame] | 444 | Py_ssize_t end_lineno, Py_ssize_t end_col_offset, | 
| Lysandros Nikolaou | a15c9b3 | 2020-05-13 22:36:27 +0300 | [diff] [blame] | 445 | const char *errmsg, va_list va) | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 446 | { | 
|  | 447 | PyObject *value = NULL; | 
|  | 448 | PyObject *errstr = NULL; | 
| Lysandros Nikolaou | a15c9b3 | 2020-05-13 22:36:27 +0300 | [diff] [blame] | 449 | PyObject *error_line = NULL; | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 450 | PyObject *tmp = NULL; | 
| Lysandros Nikolaou | 7f06af6 | 2020-05-04 03:20:09 +0300 | [diff] [blame] | 451 | p->error_indicator = 1; | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 452 |  | 
| Pablo Galindo | a77aac4 | 2021-04-23 14:27:05 +0100 | [diff] [blame] | 453 | if (end_lineno == CURRENT_POS) { | 
|  | 454 | end_lineno = p->tok->lineno; | 
|  | 455 | } | 
|  | 456 | if (end_col_offset == CURRENT_POS) { | 
|  | 457 | end_col_offset = p->tok->cur - p->tok->line_start; | 
|  | 458 | } | 
|  | 459 |  | 
| Lysandros Nikolaou | 2e0a920 | 2020-06-26 14:24:05 +0300 | [diff] [blame] | 460 | if (p->start_rule == Py_fstring_input) { | 
|  | 461 | const char *fstring_msg = "f-string: "; | 
|  | 462 | Py_ssize_t len = strlen(fstring_msg) + strlen(errmsg); | 
|  | 463 |  | 
| Lysandros Nikolaou | 6dcbc24 | 2020-06-27 20:47:00 +0300 | [diff] [blame] | 464 | char *new_errmsg = PyMem_Malloc(len + 1); // Lengths of both strings plus NULL character | 
| Lysandros Nikolaou | 2e0a920 | 2020-06-26 14:24:05 +0300 | [diff] [blame] | 465 | if (!new_errmsg) { | 
|  | 466 | return (void *) PyErr_NoMemory(); | 
|  | 467 | } | 
|  | 468 |  | 
|  | 469 | // Copy both strings into new buffer | 
|  | 470 | memcpy(new_errmsg, fstring_msg, strlen(fstring_msg)); | 
|  | 471 | memcpy(new_errmsg + strlen(fstring_msg), errmsg, strlen(errmsg)); | 
|  | 472 | new_errmsg[len] = 0; | 
|  | 473 | errmsg = new_errmsg; | 
|  | 474 | } | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 475 | errstr = PyUnicode_FromFormatV(errmsg, va); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 476 | if (!errstr) { | 
|  | 477 | goto error; | 
|  | 478 | } | 
|  | 479 |  | 
| Miss Islington (bot) | c049609 | 2021-06-08 17:29:21 -0700 | [diff] [blame] | 480 | // PyErr_ProgramTextObject assumes that the text is utf-8 so we cannot call it with a file | 
|  | 481 | // with an arbitrary encoding or otherwise we could get some badly decoded text. | 
|  | 482 | int uses_utf8_codec = (!p->tok->encoding || strcmp(p->tok->encoding, "utf-8") == 0); | 
| Pablo Galindo | cd8dcbc | 2021-03-14 04:38:40 +0100 | [diff] [blame] | 483 | if (p->tok->fp_interactive) { | 
|  | 484 | error_line = get_error_line(p, lineno); | 
|  | 485 | } | 
| Miss Islington (bot) | c049609 | 2021-06-08 17:29:21 -0700 | [diff] [blame] | 486 | else if (uses_utf8_codec && p->start_rule == Py_file_input) { | 
| Lysandros Nikolaou | 861efc6 | 2020-06-20 15:57:27 +0300 | [diff] [blame] | 487 | error_line = PyErr_ProgramTextObject(p->tok->filename, (int) lineno); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 488 | } | 
|  | 489 |  | 
| Lysandros Nikolaou | a15c9b3 | 2020-05-13 22:36:27 +0300 | [diff] [blame] | 490 | if (!error_line) { | 
| Lysandros Nikolaou | e5fe509 | 2021-01-14 23:36:30 +0200 | [diff] [blame] | 491 | /* PyErr_ProgramTextObject was not called or returned NULL. If it was not called, | 
|  | 492 | then we need to find the error line from some other source, because | 
|  | 493 | p->start_rule != Py_file_input. If it returned NULL, then it either unexpectedly | 
|  | 494 | failed or we're parsing from a string or the REPL. There's a third edge case where | 
|  | 495 | we're actually parsing from a file, which has an E_EOF SyntaxError and in that case | 
|  | 496 | `PyErr_ProgramTextObject` fails because lineno points to last_file_line + 1, which | 
|  | 497 | does not physically exist */ | 
| Miss Islington (bot) | c049609 | 2021-06-08 17:29:21 -0700 | [diff] [blame] | 498 | assert(p->tok->fp == NULL || p->tok->fp == stdin || p->tok->done == E_EOF || !uses_utf8_codec); | 
| Lysandros Nikolaou | e5fe509 | 2021-01-14 23:36:30 +0200 | [diff] [blame] | 499 |  | 
| Pablo Galindo | 4090151 | 2021-01-31 22:48:23 +0000 | [diff] [blame] | 500 | if (p->tok->lineno <= lineno) { | 
| Lysandros Nikolaou | e5fe509 | 2021-01-14 23:36:30 +0200 | [diff] [blame] | 501 | Py_ssize_t size = p->tok->inp - p->tok->buf; | 
|  | 502 | error_line = PyUnicode_DecodeUTF8(p->tok->buf, size, "replace"); | 
|  | 503 | } | 
|  | 504 | else { | 
|  | 505 | error_line = get_error_line(p, lineno); | 
|  | 506 | } | 
| Lysandros Nikolaou | a15c9b3 | 2020-05-13 22:36:27 +0300 | [diff] [blame] | 507 | if (!error_line) { | 
|  | 508 | goto error; | 
| Batuhan Taskaya | 76c1b4d | 2020-05-01 16:13:43 +0300 | [diff] [blame] | 509 | } | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 510 | } | 
|  | 511 |  | 
| Lysandros Nikolaou | 1f0f4ab | 2020-06-28 02:41:48 +0300 | [diff] [blame] | 512 | if (p->start_rule == Py_fstring_input) { | 
|  | 513 | col_offset -= p->starting_col_offset; | 
| Pablo Galindo | a77aac4 | 2021-04-23 14:27:05 +0100 | [diff] [blame] | 514 | end_col_offset -= p->starting_col_offset; | 
| Lysandros Nikolaou | 1f0f4ab | 2020-06-28 02:41:48 +0300 | [diff] [blame] | 515 | } | 
| Pablo Galindo | a77aac4 | 2021-04-23 14:27:05 +0100 | [diff] [blame] | 516 |  | 
| Pablo Galindo | 51c5896 | 2020-06-16 16:49:43 +0100 | [diff] [blame] | 517 | Py_ssize_t col_number = col_offset; | 
| Pablo Galindo | a77aac4 | 2021-04-23 14:27:05 +0100 | [diff] [blame] | 518 | Py_ssize_t end_col_number = end_col_offset; | 
| Pablo Galindo | 51c5896 | 2020-06-16 16:49:43 +0100 | [diff] [blame] | 519 |  | 
|  | 520 | if (p->tok->encoding != NULL) { | 
|  | 521 | col_number = byte_offset_to_character_offset(error_line, col_offset); | 
| Pablo Galindo | a77aac4 | 2021-04-23 14:27:05 +0100 | [diff] [blame] | 522 | end_col_number = end_col_number > 0 ? | 
|  | 523 | byte_offset_to_character_offset(error_line, end_col_offset) : | 
|  | 524 | end_col_number; | 
| Pablo Galindo | 51c5896 | 2020-06-16 16:49:43 +0100 | [diff] [blame] | 525 | } | 
| Pablo Galindo | a77aac4 | 2021-04-23 14:27:05 +0100 | [diff] [blame] | 526 | tmp = Py_BuildValue("(OiiNii)", p->tok->filename, lineno, col_number, error_line, end_lineno, end_col_number); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 527 | if (!tmp) { | 
|  | 528 | goto error; | 
|  | 529 | } | 
|  | 530 | value = PyTuple_Pack(2, errstr, tmp); | 
|  | 531 | Py_DECREF(tmp); | 
|  | 532 | if (!value) { | 
|  | 533 | goto error; | 
|  | 534 | } | 
|  | 535 | PyErr_SetObject(errtype, value); | 
|  | 536 |  | 
|  | 537 | Py_DECREF(errstr); | 
|  | 538 | Py_DECREF(value); | 
| Lysandros Nikolaou | 2e0a920 | 2020-06-26 14:24:05 +0300 | [diff] [blame] | 539 | if (p->start_rule == Py_fstring_input) { | 
| Lysandros Nikolaou | 6dcbc24 | 2020-06-27 20:47:00 +0300 | [diff] [blame] | 540 | PyMem_Free((void *)errmsg); | 
| Lysandros Nikolaou | 2e0a920 | 2020-06-26 14:24:05 +0300 | [diff] [blame] | 541 | } | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 542 | return NULL; | 
|  | 543 |  | 
|  | 544 | error: | 
|  | 545 | Py_XDECREF(errstr); | 
| Lysandros Nikolaou | a15c9b3 | 2020-05-13 22:36:27 +0300 | [diff] [blame] | 546 | Py_XDECREF(error_line); | 
| Lysandros Nikolaou | 2e0a920 | 2020-06-26 14:24:05 +0300 | [diff] [blame] | 547 | if (p->start_rule == Py_fstring_input) { | 
| Lysandros Nikolaou | 6dcbc24 | 2020-06-27 20:47:00 +0300 | [diff] [blame] | 548 | PyMem_Free((void *)errmsg); | 
| Lysandros Nikolaou | 2e0a920 | 2020-06-26 14:24:05 +0300 | [diff] [blame] | 549 | } | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 550 | return NULL; | 
|  | 551 | } | 
|  | 552 |  | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 553 | #if 0 | 
|  | 554 | static const char * | 
|  | 555 | token_name(int type) | 
|  | 556 | { | 
|  | 557 | if (0 <= type && type <= N_TOKENS) { | 
|  | 558 | return _PyParser_TokenNames[type]; | 
|  | 559 | } | 
|  | 560 | return "<Huh?>"; | 
|  | 561 | } | 
|  | 562 | #endif | 
|  | 563 |  | 
|  | 564 | // Here, mark is the start of the node, while p->mark is the end. | 
|  | 565 | // If node==NULL, they should be the same. | 
|  | 566 | int | 
|  | 567 | _PyPegen_insert_memo(Parser *p, int mark, int type, void *node) | 
|  | 568 | { | 
|  | 569 | // Insert in front | 
| Victor Stinner | 8370e07 | 2021-03-24 02:23:01 +0100 | [diff] [blame] | 570 | Memo *m = _PyArena_Malloc(p->arena, sizeof(Memo)); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 571 | if (m == NULL) { | 
|  | 572 | return -1; | 
|  | 573 | } | 
|  | 574 | m->type = type; | 
|  | 575 | m->node = node; | 
|  | 576 | m->mark = p->mark; | 
|  | 577 | m->next = p->tokens[mark]->memo; | 
|  | 578 | p->tokens[mark]->memo = m; | 
|  | 579 | return 0; | 
|  | 580 | } | 
|  | 581 |  | 
|  | 582 | // Like _PyPegen_insert_memo(), but updates an existing node if found. | 
|  | 583 | int | 
|  | 584 | _PyPegen_update_memo(Parser *p, int mark, int type, void *node) | 
|  | 585 | { | 
|  | 586 | for (Memo *m = p->tokens[mark]->memo; m != NULL; m = m->next) { | 
|  | 587 | if (m->type == type) { | 
|  | 588 | // Update existing node. | 
|  | 589 | m->node = node; | 
|  | 590 | m->mark = p->mark; | 
|  | 591 | return 0; | 
|  | 592 | } | 
|  | 593 | } | 
|  | 594 | // Insert new node. | 
|  | 595 | return _PyPegen_insert_memo(p, mark, type, node); | 
|  | 596 | } | 
|  | 597 |  | 
|  | 598 | // Return dummy NAME. | 
|  | 599 | void * | 
|  | 600 | _PyPegen_dummy_name(Parser *p, ...) | 
|  | 601 | { | 
|  | 602 | static void *cache = NULL; | 
|  | 603 |  | 
|  | 604 | if (cache != NULL) { | 
|  | 605 | return cache; | 
|  | 606 | } | 
|  | 607 |  | 
|  | 608 | PyObject *id = _create_dummy_identifier(p); | 
|  | 609 | if (!id) { | 
|  | 610 | return NULL; | 
|  | 611 | } | 
| Victor Stinner | d27f8d2 | 2021-04-07 21:34:22 +0200 | [diff] [blame] | 612 | cache = _PyAST_Name(id, Load, 1, 0, 1, 0, p->arena); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 613 | return cache; | 
|  | 614 | } | 
|  | 615 |  | 
|  | 616 | static int | 
|  | 617 | _get_keyword_or_name_type(Parser *p, const char *name, int name_len) | 
|  | 618 | { | 
| Lysandros Nikolaou | 782f44b | 2020-07-07 01:42:21 +0300 | [diff] [blame] | 619 | assert(name_len > 0); | 
| Pablo Galindo | 1ac0cbc | 2020-07-06 20:31:16 +0100 | [diff] [blame] | 620 | if (name_len >= p->n_keyword_lists || | 
|  | 621 | p->keywords[name_len] == NULL || | 
|  | 622 | p->keywords[name_len]->type == -1) { | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 623 | return NAME; | 
|  | 624 | } | 
| Pablo Galindo | 1ac0cbc | 2020-07-06 20:31:16 +0100 | [diff] [blame] | 625 | for (KeywordToken *k = p->keywords[name_len]; k != NULL && k->type != -1; k++) { | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 626 | if (strncmp(k->str, name, name_len) == 0) { | 
|  | 627 | return k->type; | 
|  | 628 | } | 
|  | 629 | } | 
|  | 630 | return NAME; | 
|  | 631 | } | 
|  | 632 |  | 
| Guido van Rossum | c001c09 | 2020-04-30 12:12:19 -0700 | [diff] [blame] | 633 | static int | 
|  | 634 | growable_comment_array_init(growable_comment_array *arr, size_t initial_size) { | 
|  | 635 | assert(initial_size > 0); | 
|  | 636 | arr->items = PyMem_Malloc(initial_size * sizeof(*arr->items)); | 
|  | 637 | arr->size = initial_size; | 
|  | 638 | arr->num_items = 0; | 
|  | 639 |  | 
|  | 640 | return arr->items != NULL; | 
|  | 641 | } | 
|  | 642 |  | 
|  | 643 | static int | 
|  | 644 | growable_comment_array_add(growable_comment_array *arr, int lineno, char *comment) { | 
|  | 645 | if (arr->num_items >= arr->size) { | 
|  | 646 | size_t new_size = arr->size * 2; | 
|  | 647 | void *new_items_array = PyMem_Realloc(arr->items, new_size * sizeof(*arr->items)); | 
|  | 648 | if (!new_items_array) { | 
|  | 649 | return 0; | 
|  | 650 | } | 
|  | 651 | arr->items = new_items_array; | 
|  | 652 | arr->size = new_size; | 
|  | 653 | } | 
|  | 654 |  | 
|  | 655 | arr->items[arr->num_items].lineno = lineno; | 
|  | 656 | arr->items[arr->num_items].comment = comment;  // Take ownership | 
|  | 657 | arr->num_items++; | 
|  | 658 | return 1; | 
|  | 659 | } | 
|  | 660 |  | 
|  | 661 | static void | 
|  | 662 | growable_comment_array_deallocate(growable_comment_array *arr) { | 
|  | 663 | for (unsigned i = 0; i < arr->num_items; i++) { | 
|  | 664 | PyMem_Free(arr->items[i].comment); | 
|  | 665 | } | 
|  | 666 | PyMem_Free(arr->items); | 
|  | 667 | } | 
|  | 668 |  | 
| Pablo Galindo | d00a449 | 2021-04-09 01:32:25 +0100 | [diff] [blame] | 669 | static int | 
|  | 670 | initialize_token(Parser *p, Token *token, const char *start, const char *end, int token_type) { | 
|  | 671 | assert(token != NULL); | 
|  | 672 |  | 
|  | 673 | token->type = (token_type == NAME) ? _get_keyword_or_name_type(p, start, (int)(end - start)) : token_type; | 
|  | 674 | token->bytes = PyBytes_FromStringAndSize(start, end - start); | 
|  | 675 | if (token->bytes == NULL) { | 
|  | 676 | return -1; | 
|  | 677 | } | 
|  | 678 |  | 
|  | 679 | if (_PyArena_AddPyObject(p->arena, token->bytes) < 0) { | 
|  | 680 | Py_DECREF(token->bytes); | 
|  | 681 | return -1; | 
|  | 682 | } | 
|  | 683 |  | 
|  | 684 | const char *line_start = token_type == STRING ? p->tok->multi_line_start : p->tok->line_start; | 
|  | 685 | int lineno = token_type == STRING ? p->tok->first_lineno : p->tok->lineno; | 
|  | 686 | int end_lineno = p->tok->lineno; | 
|  | 687 |  | 
|  | 688 | int col_offset = (start != NULL && start >= line_start) ? (int)(start - line_start) : -1; | 
|  | 689 | int end_col_offset = (end != NULL && end >= p->tok->line_start) ? (int)(end - p->tok->line_start) : -1; | 
|  | 690 |  | 
|  | 691 | token->lineno = p->starting_lineno + lineno; | 
|  | 692 | token->col_offset = p->tok->lineno == 1 ? p->starting_col_offset + col_offset : col_offset; | 
|  | 693 | token->end_lineno = p->starting_lineno + end_lineno; | 
|  | 694 | token->end_col_offset = p->tok->lineno == 1 ? p->starting_col_offset + end_col_offset : end_col_offset; | 
|  | 695 |  | 
|  | 696 | p->fill += 1; | 
|  | 697 |  | 
|  | 698 | if (token_type == ERRORTOKEN && p->tok->done == E_DECODE) { | 
|  | 699 | return raise_decode_error(p); | 
|  | 700 | } | 
|  | 701 |  | 
|  | 702 | return (token_type == ERRORTOKEN ? tokenizer_error(p) : 0); | 
|  | 703 | } | 
|  | 704 |  | 
|  | 705 | static int | 
|  | 706 | _resize_tokens_array(Parser *p) { | 
|  | 707 | int newsize = p->size * 2; | 
|  | 708 | Token **new_tokens = PyMem_Realloc(p->tokens, newsize * sizeof(Token *)); | 
|  | 709 | if (new_tokens == NULL) { | 
|  | 710 | PyErr_NoMemory(); | 
|  | 711 | return -1; | 
|  | 712 | } | 
|  | 713 | p->tokens = new_tokens; | 
|  | 714 |  | 
|  | 715 | for (int i = p->size; i < newsize; i++) { | 
|  | 716 | p->tokens[i] = PyMem_Calloc(1, sizeof(Token)); | 
|  | 717 | if (p->tokens[i] == NULL) { | 
|  | 718 | p->size = i; // Needed, in order to cleanup correctly after parser fails | 
|  | 719 | PyErr_NoMemory(); | 
|  | 720 | return -1; | 
|  | 721 | } | 
|  | 722 | } | 
|  | 723 | p->size = newsize; | 
|  | 724 | return 0; | 
|  | 725 | } | 
|  | 726 |  | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 727 | int | 
|  | 728 | _PyPegen_fill_token(Parser *p) | 
|  | 729 | { | 
| Pablo Galindo | fb61c42 | 2020-06-15 14:23:43 +0100 | [diff] [blame] | 730 | const char *start; | 
|  | 731 | const char *end; | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 732 | int type = PyTokenizer_Get(p->tok, &start, &end); | 
| Guido van Rossum | c001c09 | 2020-04-30 12:12:19 -0700 | [diff] [blame] | 733 |  | 
|  | 734 | // Record and skip '# type: ignore' comments | 
|  | 735 | while (type == TYPE_IGNORE) { | 
|  | 736 | Py_ssize_t len = end - start; | 
|  | 737 | char *tag = PyMem_Malloc(len + 1); | 
|  | 738 | if (tag == NULL) { | 
|  | 739 | PyErr_NoMemory(); | 
|  | 740 | return -1; | 
|  | 741 | } | 
|  | 742 | strncpy(tag, start, len); | 
|  | 743 | tag[len] = '\0'; | 
|  | 744 | // Ownership of tag passes to the growable array | 
|  | 745 | if (!growable_comment_array_add(&p->type_ignore_comments, p->tok->lineno, tag)) { | 
|  | 746 | PyErr_NoMemory(); | 
|  | 747 | return -1; | 
|  | 748 | } | 
|  | 749 | type = PyTokenizer_Get(p->tok, &start, &end); | 
|  | 750 | } | 
|  | 751 |  | 
| Pablo Galindo | d00a449 | 2021-04-09 01:32:25 +0100 | [diff] [blame] | 752 | // If we have reached the end and we are in single input mode we need to insert a newline and reset the parsing | 
|  | 753 | if (p->start_rule == Py_single_input && type == ENDMARKER && p->parsing_started) { | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 754 | type = NEWLINE; /* Add an extra newline */ | 
|  | 755 | p->parsing_started = 0; | 
|  | 756 |  | 
| Pablo Galindo | b94dbd7 | 2020-04-27 18:35:58 +0100 | [diff] [blame] | 757 | if (p->tok->indent && !(p->flags & PyPARSE_DONT_IMPLY_DEDENT)) { | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 758 | p->tok->pendin = -p->tok->indent; | 
|  | 759 | p->tok->indent = 0; | 
|  | 760 | } | 
|  | 761 | } | 
|  | 762 | else { | 
|  | 763 | p->parsing_started = 1; | 
|  | 764 | } | 
|  | 765 |  | 
| Pablo Galindo | d00a449 | 2021-04-09 01:32:25 +0100 | [diff] [blame] | 766 | // Check if we are at the limit of the token array capacity and resize if needed | 
|  | 767 | if ((p->fill == p->size) && (_resize_tokens_array(p) != 0)) { | 
|  | 768 | return -1; | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 769 | } | 
|  | 770 |  | 
|  | 771 | Token *t = p->tokens[p->fill]; | 
| Pablo Galindo | d00a449 | 2021-04-09 01:32:25 +0100 | [diff] [blame] | 772 | return initialize_token(p, t, start, end, type); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 773 | } | 
|  | 774 |  | 
| Pablo Galindo | 58bafe4 | 2021-04-09 01:17:31 +0100 | [diff] [blame] | 775 |  | 
|  | 776 | #if defined(Py_DEBUG) | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 777 | // Instrumentation to count the effectiveness of memoization. | 
|  | 778 | // The array counts the number of tokens skipped by memoization, | 
|  | 779 | // indexed by type. | 
|  | 780 |  | 
|  | 781 | #define NSTATISTICS 2000 | 
|  | 782 | static long memo_statistics[NSTATISTICS]; | 
|  | 783 |  | 
|  | 784 | void | 
|  | 785 | _PyPegen_clear_memo_statistics() | 
|  | 786 | { | 
|  | 787 | for (int i = 0; i < NSTATISTICS; i++) { | 
|  | 788 | memo_statistics[i] = 0; | 
|  | 789 | } | 
|  | 790 | } | 
|  | 791 |  | 
|  | 792 | PyObject * | 
|  | 793 | _PyPegen_get_memo_statistics() | 
|  | 794 | { | 
|  | 795 | PyObject *ret = PyList_New(NSTATISTICS); | 
|  | 796 | if (ret == NULL) { | 
|  | 797 | return NULL; | 
|  | 798 | } | 
|  | 799 | for (int i = 0; i < NSTATISTICS; i++) { | 
|  | 800 | PyObject *value = PyLong_FromLong(memo_statistics[i]); | 
|  | 801 | if (value == NULL) { | 
|  | 802 | Py_DECREF(ret); | 
|  | 803 | return NULL; | 
|  | 804 | } | 
|  | 805 | // PyList_SetItem borrows a reference to value. | 
|  | 806 | if (PyList_SetItem(ret, i, value) < 0) { | 
|  | 807 | Py_DECREF(ret); | 
|  | 808 | return NULL; | 
|  | 809 | } | 
|  | 810 | } | 
|  | 811 | return ret; | 
|  | 812 | } | 
| Pablo Galindo | 58bafe4 | 2021-04-09 01:17:31 +0100 | [diff] [blame] | 813 | #endif | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 814 |  | 
|  | 815 | int  // bool | 
|  | 816 | _PyPegen_is_memoized(Parser *p, int type, void *pres) | 
|  | 817 | { | 
|  | 818 | if (p->mark == p->fill) { | 
|  | 819 | if (_PyPegen_fill_token(p) < 0) { | 
| Lysandros Nikolaou | ebebb64 | 2020-04-23 18:36:06 +0300 | [diff] [blame] | 820 | p->error_indicator = 1; | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 821 | return -1; | 
|  | 822 | } | 
|  | 823 | } | 
|  | 824 |  | 
|  | 825 | Token *t = p->tokens[p->mark]; | 
|  | 826 |  | 
|  | 827 | for (Memo *m = t->memo; m != NULL; m = m->next) { | 
|  | 828 | if (m->type == type) { | 
| Pablo Galindo | 58bafe4 | 2021-04-09 01:17:31 +0100 | [diff] [blame] | 829 | #if defined(PY_DEBUG) | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 830 | if (0 <= type && type < NSTATISTICS) { | 
|  | 831 | long count = m->mark - p->mark; | 
|  | 832 | // A memoized negative result counts for one. | 
|  | 833 | if (count <= 0) { | 
|  | 834 | count = 1; | 
|  | 835 | } | 
|  | 836 | memo_statistics[type] += count; | 
|  | 837 | } | 
| Pablo Galindo | 58bafe4 | 2021-04-09 01:17:31 +0100 | [diff] [blame] | 838 | #endif | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 839 | p->mark = m->mark; | 
|  | 840 | *(void **)(pres) = m->node; | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 841 | return 1; | 
|  | 842 | } | 
|  | 843 | } | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 844 | return 0; | 
|  | 845 | } | 
|  | 846 |  | 
| Pablo Galindo | 1df5a9e | 2020-04-23 12:42:13 +0100 | [diff] [blame] | 847 | int | 
|  | 848 | _PyPegen_lookahead_with_name(int positive, expr_ty (func)(Parser *), Parser *p) | 
|  | 849 | { | 
|  | 850 | int mark = p->mark; | 
|  | 851 | void *res = func(p); | 
|  | 852 | p->mark = mark; | 
|  | 853 | return (res != NULL) == positive; | 
|  | 854 | } | 
|  | 855 |  | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 856 | int | 
| Pablo Galindo | 404b23b | 2020-05-27 00:15:52 +0100 | [diff] [blame] | 857 | _PyPegen_lookahead_with_string(int positive, expr_ty (func)(Parser *, const char*), Parser *p, const char* arg) | 
|  | 858 | { | 
|  | 859 | int mark = p->mark; | 
|  | 860 | void *res = func(p, arg); | 
|  | 861 | p->mark = mark; | 
|  | 862 | return (res != NULL) == positive; | 
|  | 863 | } | 
|  | 864 |  | 
|  | 865 | int | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 866 | _PyPegen_lookahead_with_int(int positive, Token *(func)(Parser *, int), Parser *p, int arg) | 
|  | 867 | { | 
|  | 868 | int mark = p->mark; | 
|  | 869 | void *res = func(p, arg); | 
|  | 870 | p->mark = mark; | 
|  | 871 | return (res != NULL) == positive; | 
|  | 872 | } | 
|  | 873 |  | 
|  | 874 | int | 
|  | 875 | _PyPegen_lookahead(int positive, void *(func)(Parser *), Parser *p) | 
|  | 876 | { | 
|  | 877 | int mark = p->mark; | 
| Pablo Galindo | 1df5a9e | 2020-04-23 12:42:13 +0100 | [diff] [blame] | 878 | void *res = (void*)func(p); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 879 | p->mark = mark; | 
|  | 880 | return (res != NULL) == positive; | 
|  | 881 | } | 
|  | 882 |  | 
|  | 883 | Token * | 
|  | 884 | _PyPegen_expect_token(Parser *p, int type) | 
|  | 885 | { | 
|  | 886 | if (p->mark == p->fill) { | 
|  | 887 | if (_PyPegen_fill_token(p) < 0) { | 
| Lysandros Nikolaou | ebebb64 | 2020-04-23 18:36:06 +0300 | [diff] [blame] | 888 | p->error_indicator = 1; | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 889 | return NULL; | 
|  | 890 | } | 
|  | 891 | } | 
|  | 892 | Token *t = p->tokens[p->mark]; | 
|  | 893 | if (t->type != type) { | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 894 | return NULL; | 
|  | 895 | } | 
|  | 896 | p->mark += 1; | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 897 | return t; | 
|  | 898 | } | 
|  | 899 |  | 
| Pablo Galindo | 58fb156 | 2021-02-02 19:54:22 +0000 | [diff] [blame] | 900 | Token * | 
|  | 901 | _PyPegen_expect_forced_token(Parser *p, int type, const char* expected) { | 
|  | 902 |  | 
|  | 903 | if (p->error_indicator == 1) { | 
|  | 904 | return NULL; | 
|  | 905 | } | 
|  | 906 |  | 
|  | 907 | if (p->mark == p->fill) { | 
|  | 908 | if (_PyPegen_fill_token(p) < 0) { | 
|  | 909 | p->error_indicator = 1; | 
|  | 910 | return NULL; | 
|  | 911 | } | 
|  | 912 | } | 
|  | 913 | Token *t = p->tokens[p->mark]; | 
|  | 914 | if (t->type != type) { | 
|  | 915 | RAISE_SYNTAX_ERROR_KNOWN_LOCATION(t, "expected '%s'", expected); | 
|  | 916 | return NULL; | 
|  | 917 | } | 
|  | 918 | p->mark += 1; | 
|  | 919 | return t; | 
|  | 920 | } | 
|  | 921 |  | 
| Guido van Rossum | b45af1a | 2020-05-26 10:58:44 -0700 | [diff] [blame] | 922 | expr_ty | 
|  | 923 | _PyPegen_expect_soft_keyword(Parser *p, const char *keyword) | 
|  | 924 | { | 
|  | 925 | if (p->mark == p->fill) { | 
|  | 926 | if (_PyPegen_fill_token(p) < 0) { | 
|  | 927 | p->error_indicator = 1; | 
|  | 928 | return NULL; | 
|  | 929 | } | 
|  | 930 | } | 
|  | 931 | Token *t = p->tokens[p->mark]; | 
|  | 932 | if (t->type != NAME) { | 
|  | 933 | return NULL; | 
|  | 934 | } | 
| Serhiy Storchaka | c43317d | 2021-06-12 20:44:32 +0300 | [diff] [blame] | 935 | const char *s = PyBytes_AsString(t->bytes); | 
| Guido van Rossum | b45af1a | 2020-05-26 10:58:44 -0700 | [diff] [blame] | 936 | if (!s) { | 
| Lysandros Nikolaou | 526e23f | 2020-05-27 19:04:11 +0300 | [diff] [blame] | 937 | p->error_indicator = 1; | 
| Guido van Rossum | b45af1a | 2020-05-26 10:58:44 -0700 | [diff] [blame] | 938 | return NULL; | 
|  | 939 | } | 
|  | 940 | if (strcmp(s, keyword) != 0) { | 
|  | 941 | return NULL; | 
|  | 942 | } | 
| Lysandros Nikolaou | 526e23f | 2020-05-27 19:04:11 +0300 | [diff] [blame] | 943 | return _PyPegen_name_token(p); | 
| Guido van Rossum | b45af1a | 2020-05-26 10:58:44 -0700 | [diff] [blame] | 944 | } | 
|  | 945 |  | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 946 | Token * | 
|  | 947 | _PyPegen_get_last_nonnwhitespace_token(Parser *p) | 
|  | 948 | { | 
|  | 949 | assert(p->mark >= 0); | 
|  | 950 | Token *token = NULL; | 
|  | 951 | for (int m = p->mark - 1; m >= 0; m--) { | 
|  | 952 | token = p->tokens[m]; | 
|  | 953 | if (token->type != ENDMARKER && (token->type < NEWLINE || token->type > DEDENT)) { | 
|  | 954 | break; | 
|  | 955 | } | 
|  | 956 | } | 
|  | 957 | return token; | 
|  | 958 | } | 
|  | 959 |  | 
| Miss Islington (bot) | f807a4f | 2021-06-09 14:45:43 -0700 | [diff] [blame] | 960 | static expr_ty | 
|  | 961 | _PyPegen_name_from_token(Parser *p, Token* t) | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 962 | { | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 963 | if (t == NULL) { | 
|  | 964 | return NULL; | 
|  | 965 | } | 
| Serhiy Storchaka | c43317d | 2021-06-12 20:44:32 +0300 | [diff] [blame] | 966 | const char *s = PyBytes_AsString(t->bytes); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 967 | if (!s) { | 
| Lysandros Nikolaou | 526e23f | 2020-05-27 19:04:11 +0300 | [diff] [blame] | 968 | p->error_indicator = 1; | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 969 | return NULL; | 
|  | 970 | } | 
|  | 971 | PyObject *id = _PyPegen_new_identifier(p, s); | 
|  | 972 | if (id == NULL) { | 
| Lysandros Nikolaou | 526e23f | 2020-05-27 19:04:11 +0300 | [diff] [blame] | 973 | p->error_indicator = 1; | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 974 | return NULL; | 
|  | 975 | } | 
| Victor Stinner | d27f8d2 | 2021-04-07 21:34:22 +0200 | [diff] [blame] | 976 | return _PyAST_Name(id, Load, t->lineno, t->col_offset, t->end_lineno, | 
|  | 977 | t->end_col_offset, p->arena); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 978 | } | 
|  | 979 |  | 
| Miss Islington (bot) | f807a4f | 2021-06-09 14:45:43 -0700 | [diff] [blame] | 980 |  | 
|  | 981 | expr_ty | 
|  | 982 | _PyPegen_name_token(Parser *p) | 
|  | 983 | { | 
|  | 984 | Token *t = _PyPegen_expect_token(p, NAME); | 
|  | 985 | return _PyPegen_name_from_token(p, t); | 
|  | 986 | } | 
|  | 987 |  | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 988 | void * | 
|  | 989 | _PyPegen_string_token(Parser *p) | 
|  | 990 | { | 
|  | 991 | return _PyPegen_expect_token(p, STRING); | 
|  | 992 | } | 
|  | 993 |  | 
| Pablo Galindo | b280248 | 2021-04-15 21:38:45 +0100 | [diff] [blame] | 994 |  | 
|  | 995 | expr_ty _PyPegen_soft_keyword_token(Parser *p) { | 
|  | 996 | Token *t = _PyPegen_expect_token(p, NAME); | 
|  | 997 | if (t == NULL) { | 
|  | 998 | return NULL; | 
|  | 999 | } | 
|  | 1000 | char *the_token; | 
|  | 1001 | Py_ssize_t size; | 
|  | 1002 | PyBytes_AsStringAndSize(t->bytes, &the_token, &size); | 
|  | 1003 | for (char **keyword = p->soft_keywords; *keyword != NULL; keyword++) { | 
|  | 1004 | if (strncmp(*keyword, the_token, size) == 0) { | 
| Miss Islington (bot) | f807a4f | 2021-06-09 14:45:43 -0700 | [diff] [blame] | 1005 | return _PyPegen_name_from_token(p, t); | 
| Pablo Galindo | b280248 | 2021-04-15 21:38:45 +0100 | [diff] [blame] | 1006 | } | 
|  | 1007 | } | 
|  | 1008 | return NULL; | 
|  | 1009 | } | 
|  | 1010 |  | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1011 | static PyObject * | 
|  | 1012 | parsenumber_raw(const char *s) | 
|  | 1013 | { | 
|  | 1014 | const char *end; | 
|  | 1015 | long x; | 
|  | 1016 | double dx; | 
|  | 1017 | Py_complex compl; | 
|  | 1018 | int imflag; | 
|  | 1019 |  | 
|  | 1020 | assert(s != NULL); | 
|  | 1021 | errno = 0; | 
|  | 1022 | end = s + strlen(s) - 1; | 
|  | 1023 | imflag = *end == 'j' || *end == 'J'; | 
|  | 1024 | if (s[0] == '0') { | 
|  | 1025 | x = (long)PyOS_strtoul(s, (char **)&end, 0); | 
|  | 1026 | if (x < 0 && errno == 0) { | 
|  | 1027 | return PyLong_FromString(s, (char **)0, 0); | 
|  | 1028 | } | 
|  | 1029 | } | 
| Pablo Galindo | fb61c42 | 2020-06-15 14:23:43 +0100 | [diff] [blame] | 1030 | else { | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1031 | x = PyOS_strtol(s, (char **)&end, 0); | 
| Pablo Galindo | fb61c42 | 2020-06-15 14:23:43 +0100 | [diff] [blame] | 1032 | } | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1033 | if (*end == '\0') { | 
| Pablo Galindo | fb61c42 | 2020-06-15 14:23:43 +0100 | [diff] [blame] | 1034 | if (errno != 0) { | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1035 | return PyLong_FromString(s, (char **)0, 0); | 
| Pablo Galindo | fb61c42 | 2020-06-15 14:23:43 +0100 | [diff] [blame] | 1036 | } | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1037 | return PyLong_FromLong(x); | 
|  | 1038 | } | 
|  | 1039 | /* XXX Huge floats may silently fail */ | 
|  | 1040 | if (imflag) { | 
|  | 1041 | compl.real = 0.; | 
|  | 1042 | compl.imag = PyOS_string_to_double(s, (char **)&end, NULL); | 
| Pablo Galindo | fb61c42 | 2020-06-15 14:23:43 +0100 | [diff] [blame] | 1043 | if (compl.imag == -1.0 && PyErr_Occurred()) { | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1044 | return NULL; | 
| Pablo Galindo | fb61c42 | 2020-06-15 14:23:43 +0100 | [diff] [blame] | 1045 | } | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1046 | return PyComplex_FromCComplex(compl); | 
|  | 1047 | } | 
| Pablo Galindo | fb61c42 | 2020-06-15 14:23:43 +0100 | [diff] [blame] | 1048 | dx = PyOS_string_to_double(s, NULL, NULL); | 
|  | 1049 | if (dx == -1.0 && PyErr_Occurred()) { | 
|  | 1050 | return NULL; | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1051 | } | 
| Pablo Galindo | fb61c42 | 2020-06-15 14:23:43 +0100 | [diff] [blame] | 1052 | return PyFloat_FromDouble(dx); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1053 | } | 
|  | 1054 |  | 
|  | 1055 | static PyObject * | 
|  | 1056 | parsenumber(const char *s) | 
|  | 1057 | { | 
| Pablo Galindo | fb61c42 | 2020-06-15 14:23:43 +0100 | [diff] [blame] | 1058 | char *dup; | 
|  | 1059 | char *end; | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1060 | PyObject *res = NULL; | 
|  | 1061 |  | 
|  | 1062 | assert(s != NULL); | 
|  | 1063 |  | 
|  | 1064 | if (strchr(s, '_') == NULL) { | 
|  | 1065 | return parsenumber_raw(s); | 
|  | 1066 | } | 
|  | 1067 | /* Create a duplicate without underscores. */ | 
|  | 1068 | dup = PyMem_Malloc(strlen(s) + 1); | 
|  | 1069 | if (dup == NULL) { | 
|  | 1070 | return PyErr_NoMemory(); | 
|  | 1071 | } | 
|  | 1072 | end = dup; | 
|  | 1073 | for (; *s; s++) { | 
|  | 1074 | if (*s != '_') { | 
|  | 1075 | *end++ = *s; | 
|  | 1076 | } | 
|  | 1077 | } | 
|  | 1078 | *end = '\0'; | 
|  | 1079 | res = parsenumber_raw(dup); | 
|  | 1080 | PyMem_Free(dup); | 
|  | 1081 | return res; | 
|  | 1082 | } | 
|  | 1083 |  | 
|  | 1084 | expr_ty | 
|  | 1085 | _PyPegen_number_token(Parser *p) | 
|  | 1086 | { | 
|  | 1087 | Token *t = _PyPegen_expect_token(p, NUMBER); | 
|  | 1088 | if (t == NULL) { | 
|  | 1089 | return NULL; | 
|  | 1090 | } | 
|  | 1091 |  | 
| Serhiy Storchaka | c43317d | 2021-06-12 20:44:32 +0300 | [diff] [blame] | 1092 | const char *num_raw = PyBytes_AsString(t->bytes); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1093 | if (num_raw == NULL) { | 
| Lysandros Nikolaou | 526e23f | 2020-05-27 19:04:11 +0300 | [diff] [blame] | 1094 | p->error_indicator = 1; | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1095 | return NULL; | 
|  | 1096 | } | 
|  | 1097 |  | 
| Lysandros Nikolaou | 3e0a6f3 | 2020-05-01 06:27:52 +0300 | [diff] [blame] | 1098 | if (p->feature_version < 6 && strchr(num_raw, '_') != NULL) { | 
|  | 1099 | p->error_indicator = 1; | 
| Shantanu | c3f0014 | 2020-05-04 01:13:30 -0700 | [diff] [blame] | 1100 | return RAISE_SYNTAX_ERROR("Underscores in numeric literals are only supported " | 
| Lysandros Nikolaou | 3e0a6f3 | 2020-05-01 06:27:52 +0300 | [diff] [blame] | 1101 | "in Python 3.6 and greater"); | 
|  | 1102 | } | 
|  | 1103 |  | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1104 | PyObject *c = parsenumber(num_raw); | 
|  | 1105 |  | 
|  | 1106 | if (c == NULL) { | 
| Lysandros Nikolaou | 526e23f | 2020-05-27 19:04:11 +0300 | [diff] [blame] | 1107 | p->error_indicator = 1; | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1108 | return NULL; | 
|  | 1109 | } | 
|  | 1110 |  | 
| Victor Stinner | 8370e07 | 2021-03-24 02:23:01 +0100 | [diff] [blame] | 1111 | if (_PyArena_AddPyObject(p->arena, c) < 0) { | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1112 | Py_DECREF(c); | 
| Lysandros Nikolaou | 526e23f | 2020-05-27 19:04:11 +0300 | [diff] [blame] | 1113 | p->error_indicator = 1; | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1114 | return NULL; | 
|  | 1115 | } | 
|  | 1116 |  | 
| Victor Stinner | d27f8d2 | 2021-04-07 21:34:22 +0200 | [diff] [blame] | 1117 | return _PyAST_Constant(c, NULL, t->lineno, t->col_offset, t->end_lineno, | 
|  | 1118 | t->end_col_offset, p->arena); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1119 | } | 
|  | 1120 |  | 
| Lysandros Nikolaou | 6d65087 | 2020-04-29 04:42:27 +0300 | [diff] [blame] | 1121 | static int // bool | 
|  | 1122 | newline_in_string(Parser *p, const char *cur) | 
|  | 1123 | { | 
| Pablo Galindo | 2e6593d | 2020-06-06 00:52:27 +0100 | [diff] [blame] | 1124 | for (const char *c = cur; c >= p->tok->buf; c--) { | 
|  | 1125 | if (*c == '\'' || *c == '"') { | 
| Lysandros Nikolaou | 6d65087 | 2020-04-29 04:42:27 +0300 | [diff] [blame] | 1126 | return 1; | 
|  | 1127 | } | 
|  | 1128 | } | 
|  | 1129 | return 0; | 
|  | 1130 | } | 
|  | 1131 |  | 
|  | 1132 | /* Check that the source for a single input statement really is a single | 
|  | 1133 | statement by looking at what is left in the buffer after parsing. | 
|  | 1134 | Trailing whitespace and comments are OK. */ | 
|  | 1135 | static int // bool | 
|  | 1136 | bad_single_statement(Parser *p) | 
|  | 1137 | { | 
|  | 1138 | const char *cur = strchr(p->tok->buf, '\n'); | 
|  | 1139 |  | 
|  | 1140 | /* Newlines are allowed if preceded by a line continuation character | 
|  | 1141 | or if they appear inside a string. */ | 
| Pablo Galindo | e68c678 | 2020-10-25 23:03:41 +0000 | [diff] [blame] | 1142 | if (!cur || (cur != p->tok->buf && *(cur - 1) == '\\') | 
|  | 1143 | || newline_in_string(p, cur)) { | 
| Lysandros Nikolaou | 6d65087 | 2020-04-29 04:42:27 +0300 | [diff] [blame] | 1144 | return 0; | 
|  | 1145 | } | 
|  | 1146 | char c = *cur; | 
|  | 1147 |  | 
|  | 1148 | for (;;) { | 
|  | 1149 | while (c == ' ' || c == '\t' || c == '\n' || c == '\014') { | 
|  | 1150 | c = *++cur; | 
|  | 1151 | } | 
|  | 1152 |  | 
|  | 1153 | if (!c) { | 
|  | 1154 | return 0; | 
|  | 1155 | } | 
|  | 1156 |  | 
|  | 1157 | if (c != '#') { | 
|  | 1158 | return 1; | 
|  | 1159 | } | 
|  | 1160 |  | 
|  | 1161 | /* Suck up comment. */ | 
|  | 1162 | while (c && c != '\n') { | 
|  | 1163 | c = *++cur; | 
|  | 1164 | } | 
|  | 1165 | } | 
|  | 1166 | } | 
|  | 1167 |  | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1168 | void | 
|  | 1169 | _PyPegen_Parser_Free(Parser *p) | 
|  | 1170 | { | 
|  | 1171 | Py_XDECREF(p->normalize); | 
|  | 1172 | for (int i = 0; i < p->size; i++) { | 
|  | 1173 | PyMem_Free(p->tokens[i]); | 
|  | 1174 | } | 
|  | 1175 | PyMem_Free(p->tokens); | 
| Guido van Rossum | c001c09 | 2020-04-30 12:12:19 -0700 | [diff] [blame] | 1176 | growable_comment_array_deallocate(&p->type_ignore_comments); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1177 | PyMem_Free(p); | 
|  | 1178 | } | 
|  | 1179 |  | 
| Pablo Galindo | 2b74c83 | 2020-04-27 18:02:07 +0100 | [diff] [blame] | 1180 | static int | 
|  | 1181 | compute_parser_flags(PyCompilerFlags *flags) | 
|  | 1182 | { | 
|  | 1183 | int parser_flags = 0; | 
|  | 1184 | if (!flags) { | 
|  | 1185 | return 0; | 
|  | 1186 | } | 
|  | 1187 | if (flags->cf_flags & PyCF_DONT_IMPLY_DEDENT) { | 
|  | 1188 | parser_flags |= PyPARSE_DONT_IMPLY_DEDENT; | 
|  | 1189 | } | 
|  | 1190 | if (flags->cf_flags & PyCF_IGNORE_COOKIE) { | 
|  | 1191 | parser_flags |= PyPARSE_IGNORE_COOKIE; | 
|  | 1192 | } | 
|  | 1193 | if (flags->cf_flags & CO_FUTURE_BARRY_AS_BDFL) { | 
|  | 1194 | parser_flags |= PyPARSE_BARRY_AS_BDFL; | 
|  | 1195 | } | 
|  | 1196 | if (flags->cf_flags & PyCF_TYPE_COMMENTS) { | 
|  | 1197 | parser_flags |= PyPARSE_TYPE_COMMENTS; | 
|  | 1198 | } | 
| Guido van Rossum | 9d197c7 | 2020-06-27 17:33:49 -0700 | [diff] [blame] | 1199 | if ((flags->cf_flags & PyCF_ONLY_AST) && flags->cf_feature_version < 7) { | 
| Lysandros Nikolaou | 3e0a6f3 | 2020-05-01 06:27:52 +0300 | [diff] [blame] | 1200 | parser_flags |= PyPARSE_ASYNC_HACKS; | 
|  | 1201 | } | 
| Pablo Galindo | 2b74c83 | 2020-04-27 18:02:07 +0100 | [diff] [blame] | 1202 | return parser_flags; | 
|  | 1203 | } | 
|  | 1204 |  | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1205 | Parser * | 
| Pablo Galindo | 2b74c83 | 2020-04-27 18:02:07 +0100 | [diff] [blame] | 1206 | _PyPegen_Parser_New(struct tok_state *tok, int start_rule, int flags, | 
| Lysandros Nikolaou | 3e0a6f3 | 2020-05-01 06:27:52 +0300 | [diff] [blame] | 1207 | int feature_version, int *errcode, PyArena *arena) | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1208 | { | 
|  | 1209 | Parser *p = PyMem_Malloc(sizeof(Parser)); | 
|  | 1210 | if (p == NULL) { | 
| Lysandros Nikolaou | ebebb64 | 2020-04-23 18:36:06 +0300 | [diff] [blame] | 1211 | return (Parser *) PyErr_NoMemory(); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1212 | } | 
|  | 1213 | assert(tok != NULL); | 
| Guido van Rossum | d9d6ead | 2020-05-01 09:42:32 -0700 | [diff] [blame] | 1214 | tok->type_comments = (flags & PyPARSE_TYPE_COMMENTS) > 0; | 
|  | 1215 | tok->async_hacks = (flags & PyPARSE_ASYNC_HACKS) > 0; | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1216 | p->tok = tok; | 
|  | 1217 | p->keywords = NULL; | 
|  | 1218 | p->n_keyword_lists = -1; | 
| Pablo Galindo | b280248 | 2021-04-15 21:38:45 +0100 | [diff] [blame] | 1219 | p->soft_keywords = NULL; | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1220 | p->tokens = PyMem_Malloc(sizeof(Token *)); | 
|  | 1221 | if (!p->tokens) { | 
|  | 1222 | PyMem_Free(p); | 
| Lysandros Nikolaou | ebebb64 | 2020-04-23 18:36:06 +0300 | [diff] [blame] | 1223 | return (Parser *) PyErr_NoMemory(); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1224 | } | 
| Guido van Rossum | c001c09 | 2020-04-30 12:12:19 -0700 | [diff] [blame] | 1225 | p->tokens[0] = PyMem_Calloc(1, sizeof(Token)); | 
| Lysandros Nikolaou | ebebb64 | 2020-04-23 18:36:06 +0300 | [diff] [blame] | 1226 | if (!p->tokens) { | 
|  | 1227 | PyMem_Free(p->tokens); | 
|  | 1228 | PyMem_Free(p); | 
|  | 1229 | return (Parser *) PyErr_NoMemory(); | 
|  | 1230 | } | 
| Guido van Rossum | c001c09 | 2020-04-30 12:12:19 -0700 | [diff] [blame] | 1231 | if (!growable_comment_array_init(&p->type_ignore_comments, 10)) { | 
|  | 1232 | PyMem_Free(p->tokens[0]); | 
|  | 1233 | PyMem_Free(p->tokens); | 
|  | 1234 | PyMem_Free(p); | 
|  | 1235 | return (Parser *) PyErr_NoMemory(); | 
|  | 1236 | } | 
|  | 1237 |  | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1238 | p->mark = 0; | 
|  | 1239 | p->fill = 0; | 
|  | 1240 | p->size = 1; | 
|  | 1241 |  | 
|  | 1242 | p->errcode = errcode; | 
|  | 1243 | p->arena = arena; | 
|  | 1244 | p->start_rule = start_rule; | 
|  | 1245 | p->parsing_started = 0; | 
|  | 1246 | p->normalize = NULL; | 
|  | 1247 | p->error_indicator = 0; | 
|  | 1248 |  | 
|  | 1249 | p->starting_lineno = 0; | 
|  | 1250 | p->starting_col_offset = 0; | 
| Pablo Galindo | 2b74c83 | 2020-04-27 18:02:07 +0100 | [diff] [blame] | 1251 | p->flags = flags; | 
| Lysandros Nikolaou | 3e0a6f3 | 2020-05-01 06:27:52 +0300 | [diff] [blame] | 1252 | p->feature_version = feature_version; | 
| Lysandros Nikolaou | 2f37c35 | 2020-05-07 13:37:51 +0300 | [diff] [blame] | 1253 | p->known_err_token = NULL; | 
| Pablo Galindo | 800a35c6 | 2020-05-25 18:38:45 +0100 | [diff] [blame] | 1254 | p->level = 0; | 
| Lysandros Nikolaou | bca7014 | 2020-10-27 00:42:04 +0200 | [diff] [blame] | 1255 | p->call_invalid_rules = 0; | 
| Miss Islington (bot) | ae1732d | 2021-05-21 11:20:43 -0700 | [diff] [blame] | 1256 | p->in_raw_rule = 0; | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1257 | return p; | 
|  | 1258 | } | 
|  | 1259 |  | 
| Lysandros Nikolaou | bca7014 | 2020-10-27 00:42:04 +0200 | [diff] [blame] | 1260 | static void | 
|  | 1261 | reset_parser_state(Parser *p) | 
|  | 1262 | { | 
|  | 1263 | for (int i = 0; i < p->fill; i++) { | 
|  | 1264 | p->tokens[i]->memo = NULL; | 
|  | 1265 | } | 
|  | 1266 | p->mark = 0; | 
|  | 1267 | p->call_invalid_rules = 1; | 
| Miss Islington (bot) | 1fb6b9e | 2021-05-22 15:23:26 -0700 | [diff] [blame] | 1268 | // Don't try to get extra tokens in interactive mode when trying to | 
|  | 1269 | // raise specialized errors in the second pass. | 
|  | 1270 | p->tok->interactive_underflow = IUNDERFLOW_STOP; | 
| Lysandros Nikolaou | bca7014 | 2020-10-27 00:42:04 +0200 | [diff] [blame] | 1271 | } | 
|  | 1272 |  | 
| Pablo Galindo | d6d6371 | 2021-01-19 23:59:33 +0000 | [diff] [blame] | 1273 | static int | 
|  | 1274 | _PyPegen_check_tokenizer_errors(Parser *p) { | 
|  | 1275 | // Tokenize the whole input to see if there are any tokenization | 
|  | 1276 | // errors such as mistmatching parentheses. These will get priority | 
|  | 1277 | // over generic syntax errors only if the line number of the error is | 
|  | 1278 | // before the one that we had for the generic error. | 
|  | 1279 |  | 
|  | 1280 | // We don't want to tokenize to the end for interactive input | 
|  | 1281 | if (p->tok->prompt != NULL) { | 
|  | 1282 | return 0; | 
|  | 1283 | } | 
|  | 1284 |  | 
| Miss Islington (bot) | 2a8d712 | 2021-06-08 12:25:17 -0700 | [diff] [blame] | 1285 | PyObject *type, *value, *traceback; | 
|  | 1286 | PyErr_Fetch(&type, &value, &traceback); | 
|  | 1287 |  | 
| Pablo Galindo | d6d6371 | 2021-01-19 23:59:33 +0000 | [diff] [blame] | 1288 | Token *current_token = p->known_err_token != NULL ? p->known_err_token : p->tokens[p->fill - 1]; | 
|  | 1289 | Py_ssize_t current_err_line = current_token->lineno; | 
|  | 1290 |  | 
| Miss Islington (bot) | 2a8d712 | 2021-06-08 12:25:17 -0700 | [diff] [blame] | 1291 | int ret = 0; | 
|  | 1292 |  | 
| Pablo Galindo | d6d6371 | 2021-01-19 23:59:33 +0000 | [diff] [blame] | 1293 | for (;;) { | 
|  | 1294 | const char *start; | 
|  | 1295 | const char *end; | 
|  | 1296 | switch (PyTokenizer_Get(p->tok, &start, &end)) { | 
|  | 1297 | case ERRORTOKEN: | 
|  | 1298 | if (p->tok->level != 0) { | 
|  | 1299 | int error_lineno = p->tok->parenlinenostack[p->tok->level-1]; | 
|  | 1300 | if (current_err_line > error_lineno) { | 
|  | 1301 | raise_unclosed_parentheses_error(p); | 
| Miss Islington (bot) | 2a8d712 | 2021-06-08 12:25:17 -0700 | [diff] [blame] | 1302 | ret = -1; | 
|  | 1303 | goto exit; | 
| Pablo Galindo | d6d6371 | 2021-01-19 23:59:33 +0000 | [diff] [blame] | 1304 | } | 
|  | 1305 | } | 
|  | 1306 | break; | 
|  | 1307 | case ENDMARKER: | 
|  | 1308 | break; | 
|  | 1309 | default: | 
|  | 1310 | continue; | 
|  | 1311 | } | 
|  | 1312 | break; | 
|  | 1313 | } | 
|  | 1314 |  | 
| Miss Islington (bot) | 2a8d712 | 2021-06-08 12:25:17 -0700 | [diff] [blame] | 1315 |  | 
|  | 1316 | exit: | 
|  | 1317 | if (PyErr_Occurred()) { | 
|  | 1318 | Py_XDECREF(value); | 
|  | 1319 | Py_XDECREF(type); | 
|  | 1320 | Py_XDECREF(traceback); | 
|  | 1321 | } else { | 
|  | 1322 | PyErr_Restore(type, value, traceback); | 
|  | 1323 | } | 
|  | 1324 | return ret; | 
| Pablo Galindo | d6d6371 | 2021-01-19 23:59:33 +0000 | [diff] [blame] | 1325 | } | 
|  | 1326 |  | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1327 | void * | 
|  | 1328 | _PyPegen_run_parser(Parser *p) | 
|  | 1329 | { | 
|  | 1330 | void *res = _PyPegen_parse(p); | 
|  | 1331 | if (res == NULL) { | 
| Pablo Galindo Salgado | 4ce55a2 | 2021-10-08 00:50:10 +0100 | [diff] [blame] | 1332 | if (PyErr_Occurred() && !PyErr_ExceptionMatches(PyExc_SyntaxError)) { | 
|  | 1333 | return NULL; | 
|  | 1334 | } | 
| Miss Islington (bot) | 07dba47 | 2021-05-21 08:29:58 -0700 | [diff] [blame] | 1335 | Token *last_token = p->tokens[p->fill - 1]; | 
| Lysandros Nikolaou | bca7014 | 2020-10-27 00:42:04 +0200 | [diff] [blame] | 1336 | reset_parser_state(p); | 
|  | 1337 | _PyPegen_parse(p); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1338 | if (PyErr_Occurred()) { | 
| Miss Islington (bot) | 933b5b6 | 2021-06-08 04:46:56 -0700 | [diff] [blame] | 1339 | // Prioritize tokenizer errors to custom syntax errors raised | 
|  | 1340 | // on the second phase only if the errors come from the parser. | 
| Pablo Galindo Salgado | 4ce55a2 | 2021-10-08 00:50:10 +0100 | [diff] [blame] | 1341 | if (p->tok->done == E_DONE && PyErr_ExceptionMatches(PyExc_SyntaxError)) { | 
| Miss Islington (bot) | 756b7b9 | 2021-05-03 18:06:45 -0700 | [diff] [blame] | 1342 | _PyPegen_check_tokenizer_errors(p); | 
|  | 1343 | } | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1344 | return NULL; | 
|  | 1345 | } | 
|  | 1346 | if (p->fill == 0) { | 
|  | 1347 | RAISE_SYNTAX_ERROR("error at start before reading any input"); | 
|  | 1348 | } | 
| Pablo Galindo | cd8dcbc | 2021-03-14 04:38:40 +0100 | [diff] [blame] | 1349 | else if (p->tok->done == E_EOF) { | 
| Pablo Galindo | d6d6371 | 2021-01-19 23:59:33 +0000 | [diff] [blame] | 1350 | if (p->tok->level) { | 
|  | 1351 | raise_unclosed_parentheses_error(p); | 
|  | 1352 | } else { | 
|  | 1353 | RAISE_SYNTAX_ERROR("unexpected EOF while parsing"); | 
|  | 1354 | } | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1355 | } | 
|  | 1356 | else { | 
|  | 1357 | if (p->tokens[p->fill-1]->type == INDENT) { | 
|  | 1358 | RAISE_INDENTATION_ERROR("unexpected indent"); | 
|  | 1359 | } | 
|  | 1360 | else if (p->tokens[p->fill-1]->type == DEDENT) { | 
|  | 1361 | RAISE_INDENTATION_ERROR("unexpected unindent"); | 
|  | 1362 | } | 
|  | 1363 | else { | 
| Miss Islington (bot) | 07dba47 | 2021-05-21 08:29:58 -0700 | [diff] [blame] | 1364 | // Use the last token we found on the first pass to avoid reporting | 
|  | 1365 | // incorrect locations for generic syntax errors just because we reached | 
|  | 1366 | // further away when trying to find specific syntax errors in the second | 
|  | 1367 | // pass. | 
|  | 1368 | RAISE_SYNTAX_ERROR_KNOWN_LOCATION(last_token, "invalid syntax"); | 
| Pablo Galindo | c3f167d | 2021-01-20 19:11:56 +0000 | [diff] [blame] | 1369 | // _PyPegen_check_tokenizer_errors will override the existing | 
|  | 1370 | // generic SyntaxError we just raised if errors are found. | 
|  | 1371 | _PyPegen_check_tokenizer_errors(p); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1372 | } | 
|  | 1373 | } | 
|  | 1374 | return NULL; | 
|  | 1375 | } | 
|  | 1376 |  | 
| Lysandros Nikolaou | 6d65087 | 2020-04-29 04:42:27 +0300 | [diff] [blame] | 1377 | if (p->start_rule == Py_single_input && bad_single_statement(p)) { | 
|  | 1378 | p->tok->done = E_BADSINGLE; // This is not necessary for now, but might be in the future | 
|  | 1379 | return RAISE_SYNTAX_ERROR("multiple statements found while compiling a single statement"); | 
|  | 1380 | } | 
|  | 1381 |  | 
| Victor Stinner | e0bf70d | 2021-03-18 02:46:06 +0100 | [diff] [blame] | 1382 | // test_peg_generator defines _Py_TEST_PEGEN to not call PyAST_Validate() | 
|  | 1383 | #if defined(Py_DEBUG) && !defined(_Py_TEST_PEGEN) | 
| Pablo Galindo | 1332226 | 2020-07-27 23:46:59 +0100 | [diff] [blame] | 1384 | if (p->start_rule == Py_single_input || | 
|  | 1385 | p->start_rule == Py_file_input || | 
|  | 1386 | p->start_rule == Py_eval_input) | 
|  | 1387 | { | 
| Victor Stinner | eec8e61 | 2021-03-18 14:57:49 +0100 | [diff] [blame] | 1388 | if (!_PyAST_Validate(res)) { | 
| Batuhan Taskaya | 3af4b58 | 2020-10-30 14:48:41 +0300 | [diff] [blame] | 1389 | return NULL; | 
|  | 1390 | } | 
| Pablo Galindo | 1332226 | 2020-07-27 23:46:59 +0100 | [diff] [blame] | 1391 | } | 
|  | 1392 | #endif | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1393 | return res; | 
|  | 1394 | } | 
|  | 1395 |  | 
|  | 1396 | mod_ty | 
|  | 1397 | _PyPegen_run_parser_from_file_pointer(FILE *fp, int start_rule, PyObject *filename_ob, | 
|  | 1398 | const char *enc, const char *ps1, const char *ps2, | 
| Pablo Galindo | 2b74c83 | 2020-04-27 18:02:07 +0100 | [diff] [blame] | 1399 | PyCompilerFlags *flags, int *errcode, PyArena *arena) | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1400 | { | 
|  | 1401 | struct tok_state *tok = PyTokenizer_FromFile(fp, enc, ps1, ps2); | 
|  | 1402 | if (tok == NULL) { | 
|  | 1403 | if (PyErr_Occurred()) { | 
|  | 1404 | raise_tokenizer_init_error(filename_ob); | 
|  | 1405 | return NULL; | 
|  | 1406 | } | 
|  | 1407 | return NULL; | 
|  | 1408 | } | 
| Pablo Galindo | cd8dcbc | 2021-03-14 04:38:40 +0100 | [diff] [blame] | 1409 | if (!tok->fp || ps1 != NULL || ps2 != NULL || | 
|  | 1410 | PyUnicode_CompareWithASCIIString(filename_ob, "<stdin>") == 0) { | 
|  | 1411 | tok->fp_interactive = 1; | 
|  | 1412 | } | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1413 | // This transfers the ownership to the tokenizer | 
|  | 1414 | tok->filename = filename_ob; | 
|  | 1415 | Py_INCREF(filename_ob); | 
|  | 1416 |  | 
|  | 1417 | // From here on we need to clean up even if there's an error | 
|  | 1418 | mod_ty result = NULL; | 
|  | 1419 |  | 
| Pablo Galindo | 2b74c83 | 2020-04-27 18:02:07 +0100 | [diff] [blame] | 1420 | int parser_flags = compute_parser_flags(flags); | 
| Lysandros Nikolaou | 3e0a6f3 | 2020-05-01 06:27:52 +0300 | [diff] [blame] | 1421 | Parser *p = _PyPegen_Parser_New(tok, start_rule, parser_flags, PY_MINOR_VERSION, | 
|  | 1422 | errcode, arena); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1423 | if (p == NULL) { | 
|  | 1424 | goto error; | 
|  | 1425 | } | 
|  | 1426 |  | 
|  | 1427 | result = _PyPegen_run_parser(p); | 
|  | 1428 | _PyPegen_Parser_Free(p); | 
|  | 1429 |  | 
|  | 1430 | error: | 
|  | 1431 | PyTokenizer_Free(tok); | 
|  | 1432 | return result; | 
|  | 1433 | } | 
|  | 1434 |  | 
|  | 1435 | mod_ty | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1436 | _PyPegen_run_parser_from_string(const char *str, int start_rule, PyObject *filename_ob, | 
| Pablo Galindo | 2b74c83 | 2020-04-27 18:02:07 +0100 | [diff] [blame] | 1437 | PyCompilerFlags *flags, PyArena *arena) | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1438 | { | 
|  | 1439 | int exec_input = start_rule == Py_file_input; | 
|  | 1440 |  | 
|  | 1441 | struct tok_state *tok; | 
| Pablo Galindo | 2b74c83 | 2020-04-27 18:02:07 +0100 | [diff] [blame] | 1442 | if (flags == NULL || flags->cf_flags & PyCF_IGNORE_COOKIE) { | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1443 | tok = PyTokenizer_FromUTF8(str, exec_input); | 
|  | 1444 | } else { | 
|  | 1445 | tok = PyTokenizer_FromString(str, exec_input); | 
|  | 1446 | } | 
|  | 1447 | if (tok == NULL) { | 
|  | 1448 | if (PyErr_Occurred()) { | 
|  | 1449 | raise_tokenizer_init_error(filename_ob); | 
|  | 1450 | } | 
|  | 1451 | return NULL; | 
|  | 1452 | } | 
|  | 1453 | // This transfers the ownership to the tokenizer | 
|  | 1454 | tok->filename = filename_ob; | 
|  | 1455 | Py_INCREF(filename_ob); | 
|  | 1456 |  | 
|  | 1457 | // We need to clear up from here on | 
|  | 1458 | mod_ty result = NULL; | 
|  | 1459 |  | 
| Pablo Galindo | 2b74c83 | 2020-04-27 18:02:07 +0100 | [diff] [blame] | 1460 | int parser_flags = compute_parser_flags(flags); | 
| Guido van Rossum | 9d197c7 | 2020-06-27 17:33:49 -0700 | [diff] [blame] | 1461 | int feature_version = flags && (flags->cf_flags & PyCF_ONLY_AST) ? | 
|  | 1462 | flags->cf_feature_version : PY_MINOR_VERSION; | 
| Lysandros Nikolaou | 3e0a6f3 | 2020-05-01 06:27:52 +0300 | [diff] [blame] | 1463 | Parser *p = _PyPegen_Parser_New(tok, start_rule, parser_flags, feature_version, | 
|  | 1464 | NULL, arena); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1465 | if (p == NULL) { | 
|  | 1466 | goto error; | 
|  | 1467 | } | 
|  | 1468 |  | 
|  | 1469 | result = _PyPegen_run_parser(p); | 
|  | 1470 | _PyPegen_Parser_Free(p); | 
|  | 1471 |  | 
|  | 1472 | error: | 
|  | 1473 | PyTokenizer_Free(tok); | 
|  | 1474 | return result; | 
|  | 1475 | } | 
|  | 1476 |  | 
| Pablo Galindo | a5634c4 | 2020-09-16 19:42:00 +0100 | [diff] [blame] | 1477 | asdl_stmt_seq* | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1478 | _PyPegen_interactive_exit(Parser *p) | 
|  | 1479 | { | 
|  | 1480 | if (p->errcode) { | 
|  | 1481 | *(p->errcode) = E_EOF; | 
|  | 1482 | } | 
|  | 1483 | return NULL; | 
|  | 1484 | } | 
|  | 1485 |  | 
|  | 1486 | /* Creates a single-element asdl_seq* that contains a */ | 
|  | 1487 | asdl_seq * | 
|  | 1488 | _PyPegen_singleton_seq(Parser *p, void *a) | 
|  | 1489 | { | 
|  | 1490 | assert(a != NULL); | 
| Pablo Galindo | a5634c4 | 2020-09-16 19:42:00 +0100 | [diff] [blame] | 1491 | asdl_seq *seq = (asdl_seq*)_Py_asdl_generic_seq_new(1, p->arena); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1492 | if (!seq) { | 
|  | 1493 | return NULL; | 
|  | 1494 | } | 
| Pablo Galindo | a5634c4 | 2020-09-16 19:42:00 +0100 | [diff] [blame] | 1495 | asdl_seq_SET_UNTYPED(seq, 0, a); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1496 | return seq; | 
|  | 1497 | } | 
|  | 1498 |  | 
|  | 1499 | /* Creates a copy of seq and prepends a to it */ | 
|  | 1500 | asdl_seq * | 
|  | 1501 | _PyPegen_seq_insert_in_front(Parser *p, void *a, asdl_seq *seq) | 
|  | 1502 | { | 
|  | 1503 | assert(a != NULL); | 
|  | 1504 | if (!seq) { | 
|  | 1505 | return _PyPegen_singleton_seq(p, a); | 
|  | 1506 | } | 
|  | 1507 |  | 
| Pablo Galindo | a5634c4 | 2020-09-16 19:42:00 +0100 | [diff] [blame] | 1508 | asdl_seq *new_seq = (asdl_seq*)_Py_asdl_generic_seq_new(asdl_seq_LEN(seq) + 1, p->arena); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1509 | if (!new_seq) { | 
|  | 1510 | return NULL; | 
|  | 1511 | } | 
|  | 1512 |  | 
| Pablo Galindo | a5634c4 | 2020-09-16 19:42:00 +0100 | [diff] [blame] | 1513 | asdl_seq_SET_UNTYPED(new_seq, 0, a); | 
| Pablo Galindo | ee40e4b | 2020-04-23 03:43:08 +0100 | [diff] [blame] | 1514 | for (Py_ssize_t i = 1, l = asdl_seq_LEN(new_seq); i < l; i++) { | 
| Pablo Galindo | a5634c4 | 2020-09-16 19:42:00 +0100 | [diff] [blame] | 1515 | asdl_seq_SET_UNTYPED(new_seq, i, asdl_seq_GET_UNTYPED(seq, i - 1)); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1516 | } | 
|  | 1517 | return new_seq; | 
|  | 1518 | } | 
|  | 1519 |  | 
| Guido van Rossum | c001c09 | 2020-04-30 12:12:19 -0700 | [diff] [blame] | 1520 | /* Creates a copy of seq and appends a to it */ | 
|  | 1521 | asdl_seq * | 
|  | 1522 | _PyPegen_seq_append_to_end(Parser *p, asdl_seq *seq, void *a) | 
|  | 1523 | { | 
|  | 1524 | assert(a != NULL); | 
|  | 1525 | if (!seq) { | 
|  | 1526 | return _PyPegen_singleton_seq(p, a); | 
|  | 1527 | } | 
|  | 1528 |  | 
| Pablo Galindo | a5634c4 | 2020-09-16 19:42:00 +0100 | [diff] [blame] | 1529 | asdl_seq *new_seq = (asdl_seq*)_Py_asdl_generic_seq_new(asdl_seq_LEN(seq) + 1, p->arena); | 
| Guido van Rossum | c001c09 | 2020-04-30 12:12:19 -0700 | [diff] [blame] | 1530 | if (!new_seq) { | 
|  | 1531 | return NULL; | 
|  | 1532 | } | 
|  | 1533 |  | 
|  | 1534 | for (Py_ssize_t i = 0, l = asdl_seq_LEN(new_seq); i + 1 < l; i++) { | 
| Pablo Galindo | a5634c4 | 2020-09-16 19:42:00 +0100 | [diff] [blame] | 1535 | asdl_seq_SET_UNTYPED(new_seq, i, asdl_seq_GET_UNTYPED(seq, i)); | 
| Guido van Rossum | c001c09 | 2020-04-30 12:12:19 -0700 | [diff] [blame] | 1536 | } | 
| Pablo Galindo | a5634c4 | 2020-09-16 19:42:00 +0100 | [diff] [blame] | 1537 | asdl_seq_SET_UNTYPED(new_seq, asdl_seq_LEN(new_seq) - 1, a); | 
| Guido van Rossum | c001c09 | 2020-04-30 12:12:19 -0700 | [diff] [blame] | 1538 | return new_seq; | 
|  | 1539 | } | 
|  | 1540 |  | 
| Pablo Galindo | ee40e4b | 2020-04-23 03:43:08 +0100 | [diff] [blame] | 1541 | static Py_ssize_t | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1542 | _get_flattened_seq_size(asdl_seq *seqs) | 
|  | 1543 | { | 
| Pablo Galindo | ee40e4b | 2020-04-23 03:43:08 +0100 | [diff] [blame] | 1544 | Py_ssize_t size = 0; | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1545 | for (Py_ssize_t i = 0, l = asdl_seq_LEN(seqs); i < l; i++) { | 
| Pablo Galindo | a5634c4 | 2020-09-16 19:42:00 +0100 | [diff] [blame] | 1546 | asdl_seq *inner_seq = asdl_seq_GET_UNTYPED(seqs, i); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1547 | size += asdl_seq_LEN(inner_seq); | 
|  | 1548 | } | 
|  | 1549 | return size; | 
|  | 1550 | } | 
|  | 1551 |  | 
|  | 1552 | /* Flattens an asdl_seq* of asdl_seq*s */ | 
|  | 1553 | asdl_seq * | 
|  | 1554 | _PyPegen_seq_flatten(Parser *p, asdl_seq *seqs) | 
|  | 1555 | { | 
| Pablo Galindo | ee40e4b | 2020-04-23 03:43:08 +0100 | [diff] [blame] | 1556 | Py_ssize_t flattened_seq_size = _get_flattened_seq_size(seqs); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1557 | assert(flattened_seq_size > 0); | 
|  | 1558 |  | 
| Pablo Galindo | a5634c4 | 2020-09-16 19:42:00 +0100 | [diff] [blame] | 1559 | asdl_seq *flattened_seq = (asdl_seq*)_Py_asdl_generic_seq_new(flattened_seq_size, p->arena); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1560 | if (!flattened_seq) { | 
|  | 1561 | return NULL; | 
|  | 1562 | } | 
|  | 1563 |  | 
|  | 1564 | int flattened_seq_idx = 0; | 
|  | 1565 | for (Py_ssize_t i = 0, l = asdl_seq_LEN(seqs); i < l; i++) { | 
| Pablo Galindo | a5634c4 | 2020-09-16 19:42:00 +0100 | [diff] [blame] | 1566 | asdl_seq *inner_seq = asdl_seq_GET_UNTYPED(seqs, i); | 
| Pablo Galindo | ee40e4b | 2020-04-23 03:43:08 +0100 | [diff] [blame] | 1567 | for (Py_ssize_t j = 0, li = asdl_seq_LEN(inner_seq); j < li; j++) { | 
| Pablo Galindo | a5634c4 | 2020-09-16 19:42:00 +0100 | [diff] [blame] | 1568 | asdl_seq_SET_UNTYPED(flattened_seq, flattened_seq_idx++, asdl_seq_GET_UNTYPED(inner_seq, j)); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1569 | } | 
|  | 1570 | } | 
|  | 1571 | assert(flattened_seq_idx == flattened_seq_size); | 
|  | 1572 |  | 
|  | 1573 | return flattened_seq; | 
|  | 1574 | } | 
|  | 1575 |  | 
| Pablo Galindo | a77aac4 | 2021-04-23 14:27:05 +0100 | [diff] [blame] | 1576 | void * | 
|  | 1577 | _PyPegen_seq_last_item(asdl_seq *seq) | 
|  | 1578 | { | 
|  | 1579 | Py_ssize_t len = asdl_seq_LEN(seq); | 
|  | 1580 | return asdl_seq_GET_UNTYPED(seq, len - 1); | 
|  | 1581 | } | 
|  | 1582 |  | 
| Miss Islington (bot) | 11f1a30 | 2021-06-24 08:34:28 -0700 | [diff] [blame] | 1583 | void * | 
|  | 1584 | _PyPegen_seq_first_item(asdl_seq *seq) | 
|  | 1585 | { | 
|  | 1586 | return asdl_seq_GET_UNTYPED(seq, 0); | 
|  | 1587 | } | 
|  | 1588 |  | 
|  | 1589 |  | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1590 | /* Creates a new name of the form <first_name>.<second_name> */ | 
|  | 1591 | expr_ty | 
|  | 1592 | _PyPegen_join_names_with_dot(Parser *p, expr_ty first_name, expr_ty second_name) | 
|  | 1593 | { | 
|  | 1594 | assert(first_name != NULL && second_name != NULL); | 
|  | 1595 | PyObject *first_identifier = first_name->v.Name.id; | 
|  | 1596 | PyObject *second_identifier = second_name->v.Name.id; | 
|  | 1597 |  | 
|  | 1598 | if (PyUnicode_READY(first_identifier) == -1) { | 
|  | 1599 | return NULL; | 
|  | 1600 | } | 
|  | 1601 | if (PyUnicode_READY(second_identifier) == -1) { | 
|  | 1602 | return NULL; | 
|  | 1603 | } | 
|  | 1604 | const char *first_str = PyUnicode_AsUTF8(first_identifier); | 
|  | 1605 | if (!first_str) { | 
|  | 1606 | return NULL; | 
|  | 1607 | } | 
|  | 1608 | const char *second_str = PyUnicode_AsUTF8(second_identifier); | 
|  | 1609 | if (!second_str) { | 
|  | 1610 | return NULL; | 
|  | 1611 | } | 
| Pablo Galindo | 9f27dd3 | 2020-04-24 01:13:33 +0100 | [diff] [blame] | 1612 | Py_ssize_t len = strlen(first_str) + strlen(second_str) + 1;  // +1 for the dot | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1613 |  | 
|  | 1614 | PyObject *str = PyBytes_FromStringAndSize(NULL, len); | 
|  | 1615 | if (!str) { | 
|  | 1616 | return NULL; | 
|  | 1617 | } | 
|  | 1618 |  | 
|  | 1619 | char *s = PyBytes_AS_STRING(str); | 
|  | 1620 | if (!s) { | 
|  | 1621 | return NULL; | 
|  | 1622 | } | 
|  | 1623 |  | 
|  | 1624 | strcpy(s, first_str); | 
|  | 1625 | s += strlen(first_str); | 
|  | 1626 | *s++ = '.'; | 
|  | 1627 | strcpy(s, second_str); | 
|  | 1628 | s += strlen(second_str); | 
|  | 1629 | *s = '\0'; | 
|  | 1630 |  | 
|  | 1631 | PyObject *uni = PyUnicode_DecodeUTF8(PyBytes_AS_STRING(str), PyBytes_GET_SIZE(str), NULL); | 
|  | 1632 | Py_DECREF(str); | 
|  | 1633 | if (!uni) { | 
|  | 1634 | return NULL; | 
|  | 1635 | } | 
|  | 1636 | PyUnicode_InternInPlace(&uni); | 
| Victor Stinner | 8370e07 | 2021-03-24 02:23:01 +0100 | [diff] [blame] | 1637 | if (_PyArena_AddPyObject(p->arena, uni) < 0) { | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1638 | Py_DECREF(uni); | 
|  | 1639 | return NULL; | 
|  | 1640 | } | 
|  | 1641 |  | 
| Victor Stinner | d27f8d2 | 2021-04-07 21:34:22 +0200 | [diff] [blame] | 1642 | return _PyAST_Name(uni, Load, EXTRA_EXPR(first_name, second_name)); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1643 | } | 
|  | 1644 |  | 
|  | 1645 | /* Counts the total number of dots in seq's tokens */ | 
|  | 1646 | int | 
|  | 1647 | _PyPegen_seq_count_dots(asdl_seq *seq) | 
|  | 1648 | { | 
|  | 1649 | int number_of_dots = 0; | 
|  | 1650 | for (Py_ssize_t i = 0, l = asdl_seq_LEN(seq); i < l; i++) { | 
| Pablo Galindo | a5634c4 | 2020-09-16 19:42:00 +0100 | [diff] [blame] | 1651 | Token *current_expr = asdl_seq_GET_UNTYPED(seq, i); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1652 | switch (current_expr->type) { | 
|  | 1653 | case ELLIPSIS: | 
|  | 1654 | number_of_dots += 3; | 
|  | 1655 | break; | 
|  | 1656 | case DOT: | 
|  | 1657 | number_of_dots += 1; | 
|  | 1658 | break; | 
|  | 1659 | default: | 
| Lysandros Nikolaou | ebebb64 | 2020-04-23 18:36:06 +0300 | [diff] [blame] | 1660 | Py_UNREACHABLE(); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1661 | } | 
|  | 1662 | } | 
|  | 1663 |  | 
|  | 1664 | return number_of_dots; | 
|  | 1665 | } | 
|  | 1666 |  | 
|  | 1667 | /* Creates an alias with '*' as the identifier name */ | 
|  | 1668 | alias_ty | 
| Matthew Suozzo | 75a06f0 | 2021-04-10 16:56:28 -0400 | [diff] [blame] | 1669 | _PyPegen_alias_for_star(Parser *p, int lineno, int col_offset, int end_lineno, | 
|  | 1670 | int end_col_offset, PyArena *arena) { | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1671 | PyObject *str = PyUnicode_InternFromString("*"); | 
|  | 1672 | if (!str) { | 
|  | 1673 | return NULL; | 
|  | 1674 | } | 
| Victor Stinner | 8370e07 | 2021-03-24 02:23:01 +0100 | [diff] [blame] | 1675 | if (_PyArena_AddPyObject(p->arena, str) < 0) { | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1676 | Py_DECREF(str); | 
|  | 1677 | return NULL; | 
|  | 1678 | } | 
| Matthew Suozzo | 75a06f0 | 2021-04-10 16:56:28 -0400 | [diff] [blame] | 1679 | return _PyAST_alias(str, NULL, lineno, col_offset, end_lineno, end_col_offset, arena); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1680 | } | 
|  | 1681 |  | 
|  | 1682 | /* Creates a new asdl_seq* with the identifiers of all the names in seq */ | 
| Pablo Galindo | a5634c4 | 2020-09-16 19:42:00 +0100 | [diff] [blame] | 1683 | asdl_identifier_seq * | 
|  | 1684 | _PyPegen_map_names_to_ids(Parser *p, asdl_expr_seq *seq) | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1685 | { | 
| Pablo Galindo | ee40e4b | 2020-04-23 03:43:08 +0100 | [diff] [blame] | 1686 | Py_ssize_t len = asdl_seq_LEN(seq); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1687 | assert(len > 0); | 
|  | 1688 |  | 
| Pablo Galindo | a5634c4 | 2020-09-16 19:42:00 +0100 | [diff] [blame] | 1689 | asdl_identifier_seq *new_seq = _Py_asdl_identifier_seq_new(len, p->arena); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1690 | if (!new_seq) { | 
|  | 1691 | return NULL; | 
|  | 1692 | } | 
|  | 1693 | for (Py_ssize_t i = 0; i < len; i++) { | 
|  | 1694 | expr_ty e = asdl_seq_GET(seq, i); | 
|  | 1695 | asdl_seq_SET(new_seq, i, e->v.Name.id); | 
|  | 1696 | } | 
|  | 1697 | return new_seq; | 
|  | 1698 | } | 
|  | 1699 |  | 
|  | 1700 | /* Constructs a CmpopExprPair */ | 
|  | 1701 | CmpopExprPair * | 
|  | 1702 | _PyPegen_cmpop_expr_pair(Parser *p, cmpop_ty cmpop, expr_ty expr) | 
|  | 1703 | { | 
|  | 1704 | assert(expr != NULL); | 
| Victor Stinner | 8370e07 | 2021-03-24 02:23:01 +0100 | [diff] [blame] | 1705 | CmpopExprPair *a = _PyArena_Malloc(p->arena, sizeof(CmpopExprPair)); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1706 | if (!a) { | 
|  | 1707 | return NULL; | 
|  | 1708 | } | 
|  | 1709 | a->cmpop = cmpop; | 
|  | 1710 | a->expr = expr; | 
|  | 1711 | return a; | 
|  | 1712 | } | 
|  | 1713 |  | 
|  | 1714 | asdl_int_seq * | 
|  | 1715 | _PyPegen_get_cmpops(Parser *p, asdl_seq *seq) | 
|  | 1716 | { | 
| Pablo Galindo | ee40e4b | 2020-04-23 03:43:08 +0100 | [diff] [blame] | 1717 | Py_ssize_t len = asdl_seq_LEN(seq); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1718 | assert(len > 0); | 
|  | 1719 |  | 
|  | 1720 | asdl_int_seq *new_seq = _Py_asdl_int_seq_new(len, p->arena); | 
|  | 1721 | if (!new_seq) { | 
|  | 1722 | return NULL; | 
|  | 1723 | } | 
|  | 1724 | for (Py_ssize_t i = 0; i < len; i++) { | 
| Pablo Galindo | a5634c4 | 2020-09-16 19:42:00 +0100 | [diff] [blame] | 1725 | CmpopExprPair *pair = asdl_seq_GET_UNTYPED(seq, i); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1726 | asdl_seq_SET(new_seq, i, pair->cmpop); | 
|  | 1727 | } | 
|  | 1728 | return new_seq; | 
|  | 1729 | } | 
|  | 1730 |  | 
| Pablo Galindo | a5634c4 | 2020-09-16 19:42:00 +0100 | [diff] [blame] | 1731 | asdl_expr_seq * | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1732 | _PyPegen_get_exprs(Parser *p, asdl_seq *seq) | 
|  | 1733 | { | 
| Pablo Galindo | ee40e4b | 2020-04-23 03:43:08 +0100 | [diff] [blame] | 1734 | Py_ssize_t len = asdl_seq_LEN(seq); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1735 | assert(len > 0); | 
|  | 1736 |  | 
| Pablo Galindo | a5634c4 | 2020-09-16 19:42:00 +0100 | [diff] [blame] | 1737 | asdl_expr_seq *new_seq = _Py_asdl_expr_seq_new(len, p->arena); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1738 | if (!new_seq) { | 
|  | 1739 | return NULL; | 
|  | 1740 | } | 
|  | 1741 | for (Py_ssize_t i = 0; i < len; i++) { | 
| Pablo Galindo | a5634c4 | 2020-09-16 19:42:00 +0100 | [diff] [blame] | 1742 | CmpopExprPair *pair = asdl_seq_GET_UNTYPED(seq, i); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1743 | asdl_seq_SET(new_seq, i, pair->expr); | 
|  | 1744 | } | 
|  | 1745 | return new_seq; | 
|  | 1746 | } | 
|  | 1747 |  | 
|  | 1748 | /* Creates an asdl_seq* where all the elements have been changed to have ctx as context */ | 
| Pablo Galindo | a5634c4 | 2020-09-16 19:42:00 +0100 | [diff] [blame] | 1749 | static asdl_expr_seq * | 
|  | 1750 | _set_seq_context(Parser *p, asdl_expr_seq *seq, expr_context_ty ctx) | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1751 | { | 
| Pablo Galindo | ee40e4b | 2020-04-23 03:43:08 +0100 | [diff] [blame] | 1752 | Py_ssize_t len = asdl_seq_LEN(seq); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1753 | if (len == 0) { | 
|  | 1754 | return NULL; | 
|  | 1755 | } | 
|  | 1756 |  | 
| Pablo Galindo | a5634c4 | 2020-09-16 19:42:00 +0100 | [diff] [blame] | 1757 | asdl_expr_seq *new_seq = _Py_asdl_expr_seq_new(len, p->arena); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1758 | if (!new_seq) { | 
|  | 1759 | return NULL; | 
|  | 1760 | } | 
|  | 1761 | for (Py_ssize_t i = 0; i < len; i++) { | 
|  | 1762 | expr_ty e = asdl_seq_GET(seq, i); | 
|  | 1763 | asdl_seq_SET(new_seq, i, _PyPegen_set_expr_context(p, e, ctx)); | 
|  | 1764 | } | 
|  | 1765 | return new_seq; | 
|  | 1766 | } | 
|  | 1767 |  | 
|  | 1768 | static expr_ty | 
|  | 1769 | _set_name_context(Parser *p, expr_ty e, expr_context_ty ctx) | 
|  | 1770 | { | 
| Victor Stinner | d27f8d2 | 2021-04-07 21:34:22 +0200 | [diff] [blame] | 1771 | return _PyAST_Name(e->v.Name.id, ctx, EXTRA_EXPR(e, e)); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1772 | } | 
|  | 1773 |  | 
|  | 1774 | static expr_ty | 
|  | 1775 | _set_tuple_context(Parser *p, expr_ty e, expr_context_ty ctx) | 
|  | 1776 | { | 
| Victor Stinner | d27f8d2 | 2021-04-07 21:34:22 +0200 | [diff] [blame] | 1777 | return _PyAST_Tuple( | 
| Pablo Galindo | a5634c4 | 2020-09-16 19:42:00 +0100 | [diff] [blame] | 1778 | _set_seq_context(p, e->v.Tuple.elts, ctx), | 
|  | 1779 | ctx, | 
|  | 1780 | EXTRA_EXPR(e, e)); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1781 | } | 
|  | 1782 |  | 
|  | 1783 | static expr_ty | 
|  | 1784 | _set_list_context(Parser *p, expr_ty e, expr_context_ty ctx) | 
|  | 1785 | { | 
| Victor Stinner | d27f8d2 | 2021-04-07 21:34:22 +0200 | [diff] [blame] | 1786 | return _PyAST_List( | 
| Pablo Galindo | a5634c4 | 2020-09-16 19:42:00 +0100 | [diff] [blame] | 1787 | _set_seq_context(p, e->v.List.elts, ctx), | 
|  | 1788 | ctx, | 
|  | 1789 | EXTRA_EXPR(e, e)); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1790 | } | 
|  | 1791 |  | 
|  | 1792 | static expr_ty | 
|  | 1793 | _set_subscript_context(Parser *p, expr_ty e, expr_context_ty ctx) | 
|  | 1794 | { | 
| Victor Stinner | d27f8d2 | 2021-04-07 21:34:22 +0200 | [diff] [blame] | 1795 | return _PyAST_Subscript(e->v.Subscript.value, e->v.Subscript.slice, | 
|  | 1796 | ctx, EXTRA_EXPR(e, e)); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1797 | } | 
|  | 1798 |  | 
|  | 1799 | static expr_ty | 
|  | 1800 | _set_attribute_context(Parser *p, expr_ty e, expr_context_ty ctx) | 
|  | 1801 | { | 
| Victor Stinner | d27f8d2 | 2021-04-07 21:34:22 +0200 | [diff] [blame] | 1802 | return _PyAST_Attribute(e->v.Attribute.value, e->v.Attribute.attr, | 
|  | 1803 | ctx, EXTRA_EXPR(e, e)); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1804 | } | 
|  | 1805 |  | 
|  | 1806 | static expr_ty | 
|  | 1807 | _set_starred_context(Parser *p, expr_ty e, expr_context_ty ctx) | 
|  | 1808 | { | 
| Victor Stinner | d27f8d2 | 2021-04-07 21:34:22 +0200 | [diff] [blame] | 1809 | return _PyAST_Starred(_PyPegen_set_expr_context(p, e->v.Starred.value, ctx), | 
|  | 1810 | ctx, EXTRA_EXPR(e, e)); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1811 | } | 
|  | 1812 |  | 
|  | 1813 | /* Creates an `expr_ty` equivalent to `expr` but with `ctx` as context */ | 
|  | 1814 | expr_ty | 
|  | 1815 | _PyPegen_set_expr_context(Parser *p, expr_ty expr, expr_context_ty ctx) | 
|  | 1816 | { | 
|  | 1817 | assert(expr != NULL); | 
|  | 1818 |  | 
|  | 1819 | expr_ty new = NULL; | 
|  | 1820 | switch (expr->kind) { | 
|  | 1821 | case Name_kind: | 
|  | 1822 | new = _set_name_context(p, expr, ctx); | 
|  | 1823 | break; | 
|  | 1824 | case Tuple_kind: | 
|  | 1825 | new = _set_tuple_context(p, expr, ctx); | 
|  | 1826 | break; | 
|  | 1827 | case List_kind: | 
|  | 1828 | new = _set_list_context(p, expr, ctx); | 
|  | 1829 | break; | 
|  | 1830 | case Subscript_kind: | 
|  | 1831 | new = _set_subscript_context(p, expr, ctx); | 
|  | 1832 | break; | 
|  | 1833 | case Attribute_kind: | 
|  | 1834 | new = _set_attribute_context(p, expr, ctx); | 
|  | 1835 | break; | 
|  | 1836 | case Starred_kind: | 
|  | 1837 | new = _set_starred_context(p, expr, ctx); | 
|  | 1838 | break; | 
|  | 1839 | default: | 
|  | 1840 | new = expr; | 
|  | 1841 | } | 
|  | 1842 | return new; | 
|  | 1843 | } | 
|  | 1844 |  | 
|  | 1845 | /* Constructs a KeyValuePair that is used when parsing a dict's key value pairs */ | 
|  | 1846 | KeyValuePair * | 
|  | 1847 | _PyPegen_key_value_pair(Parser *p, expr_ty key, expr_ty value) | 
|  | 1848 | { | 
| Victor Stinner | 8370e07 | 2021-03-24 02:23:01 +0100 | [diff] [blame] | 1849 | KeyValuePair *a = _PyArena_Malloc(p->arena, sizeof(KeyValuePair)); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1850 | if (!a) { | 
|  | 1851 | return NULL; | 
|  | 1852 | } | 
|  | 1853 | a->key = key; | 
|  | 1854 | a->value = value; | 
|  | 1855 | return a; | 
|  | 1856 | } | 
|  | 1857 |  | 
|  | 1858 | /* Extracts all keys from an asdl_seq* of KeyValuePair*'s */ | 
| Pablo Galindo | a5634c4 | 2020-09-16 19:42:00 +0100 | [diff] [blame] | 1859 | asdl_expr_seq * | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1860 | _PyPegen_get_keys(Parser *p, asdl_seq *seq) | 
|  | 1861 | { | 
| Pablo Galindo | ee40e4b | 2020-04-23 03:43:08 +0100 | [diff] [blame] | 1862 | Py_ssize_t len = asdl_seq_LEN(seq); | 
| Pablo Galindo | a5634c4 | 2020-09-16 19:42:00 +0100 | [diff] [blame] | 1863 | asdl_expr_seq *new_seq = _Py_asdl_expr_seq_new(len, p->arena); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1864 | if (!new_seq) { | 
|  | 1865 | return NULL; | 
|  | 1866 | } | 
|  | 1867 | for (Py_ssize_t i = 0; i < len; i++) { | 
| Pablo Galindo | a5634c4 | 2020-09-16 19:42:00 +0100 | [diff] [blame] | 1868 | KeyValuePair *pair = asdl_seq_GET_UNTYPED(seq, i); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1869 | asdl_seq_SET(new_seq, i, pair->key); | 
|  | 1870 | } | 
|  | 1871 | return new_seq; | 
|  | 1872 | } | 
|  | 1873 |  | 
|  | 1874 | /* Extracts all values from an asdl_seq* of KeyValuePair*'s */ | 
| Pablo Galindo | a5634c4 | 2020-09-16 19:42:00 +0100 | [diff] [blame] | 1875 | asdl_expr_seq * | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1876 | _PyPegen_get_values(Parser *p, asdl_seq *seq) | 
|  | 1877 | { | 
| Pablo Galindo | ee40e4b | 2020-04-23 03:43:08 +0100 | [diff] [blame] | 1878 | Py_ssize_t len = asdl_seq_LEN(seq); | 
| Pablo Galindo | a5634c4 | 2020-09-16 19:42:00 +0100 | [diff] [blame] | 1879 | asdl_expr_seq *new_seq = _Py_asdl_expr_seq_new(len, p->arena); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1880 | if (!new_seq) { | 
|  | 1881 | return NULL; | 
|  | 1882 | } | 
|  | 1883 | for (Py_ssize_t i = 0; i < len; i++) { | 
| Pablo Galindo | a5634c4 | 2020-09-16 19:42:00 +0100 | [diff] [blame] | 1884 | KeyValuePair *pair = asdl_seq_GET_UNTYPED(seq, i); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1885 | asdl_seq_SET(new_seq, i, pair->value); | 
|  | 1886 | } | 
|  | 1887 | return new_seq; | 
|  | 1888 | } | 
|  | 1889 |  | 
| Nick Coghlan | 1e7b858 | 2021-04-29 15:58:44 +1000 | [diff] [blame] | 1890 | /* Constructs a KeyPatternPair that is used when parsing mapping & class patterns */ | 
|  | 1891 | KeyPatternPair * | 
|  | 1892 | _PyPegen_key_pattern_pair(Parser *p, expr_ty key, pattern_ty pattern) | 
|  | 1893 | { | 
|  | 1894 | KeyPatternPair *a = _PyArena_Malloc(p->arena, sizeof(KeyPatternPair)); | 
|  | 1895 | if (!a) { | 
|  | 1896 | return NULL; | 
|  | 1897 | } | 
|  | 1898 | a->key = key; | 
|  | 1899 | a->pattern = pattern; | 
|  | 1900 | return a; | 
|  | 1901 | } | 
|  | 1902 |  | 
|  | 1903 | /* Extracts all keys from an asdl_seq* of KeyPatternPair*'s */ | 
|  | 1904 | asdl_expr_seq * | 
|  | 1905 | _PyPegen_get_pattern_keys(Parser *p, asdl_seq *seq) | 
|  | 1906 | { | 
|  | 1907 | Py_ssize_t len = asdl_seq_LEN(seq); | 
|  | 1908 | asdl_expr_seq *new_seq = _Py_asdl_expr_seq_new(len, p->arena); | 
|  | 1909 | if (!new_seq) { | 
|  | 1910 | return NULL; | 
|  | 1911 | } | 
|  | 1912 | for (Py_ssize_t i = 0; i < len; i++) { | 
|  | 1913 | KeyPatternPair *pair = asdl_seq_GET_UNTYPED(seq, i); | 
|  | 1914 | asdl_seq_SET(new_seq, i, pair->key); | 
|  | 1915 | } | 
|  | 1916 | return new_seq; | 
|  | 1917 | } | 
|  | 1918 |  | 
|  | 1919 | /* Extracts all patterns from an asdl_seq* of KeyPatternPair*'s */ | 
|  | 1920 | asdl_pattern_seq * | 
|  | 1921 | _PyPegen_get_patterns(Parser *p, asdl_seq *seq) | 
|  | 1922 | { | 
|  | 1923 | Py_ssize_t len = asdl_seq_LEN(seq); | 
|  | 1924 | asdl_pattern_seq *new_seq = _Py_asdl_pattern_seq_new(len, p->arena); | 
|  | 1925 | if (!new_seq) { | 
|  | 1926 | return NULL; | 
|  | 1927 | } | 
|  | 1928 | for (Py_ssize_t i = 0; i < len; i++) { | 
|  | 1929 | KeyPatternPair *pair = asdl_seq_GET_UNTYPED(seq, i); | 
|  | 1930 | asdl_seq_SET(new_seq, i, pair->pattern); | 
|  | 1931 | } | 
|  | 1932 | return new_seq; | 
|  | 1933 | } | 
|  | 1934 |  | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1935 | /* Constructs a NameDefaultPair */ | 
|  | 1936 | NameDefaultPair * | 
| Guido van Rossum | c001c09 | 2020-04-30 12:12:19 -0700 | [diff] [blame] | 1937 | _PyPegen_name_default_pair(Parser *p, arg_ty arg, expr_ty value, Token *tc) | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1938 | { | 
| Victor Stinner | 8370e07 | 2021-03-24 02:23:01 +0100 | [diff] [blame] | 1939 | NameDefaultPair *a = _PyArena_Malloc(p->arena, sizeof(NameDefaultPair)); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1940 | if (!a) { | 
|  | 1941 | return NULL; | 
|  | 1942 | } | 
| Guido van Rossum | c001c09 | 2020-04-30 12:12:19 -0700 | [diff] [blame] | 1943 | a->arg = _PyPegen_add_type_comment_to_arg(p, arg, tc); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1944 | a->value = value; | 
|  | 1945 | return a; | 
|  | 1946 | } | 
|  | 1947 |  | 
|  | 1948 | /* Constructs a SlashWithDefault */ | 
|  | 1949 | SlashWithDefault * | 
| Pablo Galindo | a5634c4 | 2020-09-16 19:42:00 +0100 | [diff] [blame] | 1950 | _PyPegen_slash_with_default(Parser *p, asdl_arg_seq *plain_names, asdl_seq *names_with_defaults) | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1951 | { | 
| Victor Stinner | 8370e07 | 2021-03-24 02:23:01 +0100 | [diff] [blame] | 1952 | SlashWithDefault *a = _PyArena_Malloc(p->arena, sizeof(SlashWithDefault)); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1953 | if (!a) { | 
|  | 1954 | return NULL; | 
|  | 1955 | } | 
|  | 1956 | a->plain_names = plain_names; | 
|  | 1957 | a->names_with_defaults = names_with_defaults; | 
|  | 1958 | return a; | 
|  | 1959 | } | 
|  | 1960 |  | 
|  | 1961 | /* Constructs a StarEtc */ | 
|  | 1962 | StarEtc * | 
|  | 1963 | _PyPegen_star_etc(Parser *p, arg_ty vararg, asdl_seq *kwonlyargs, arg_ty kwarg) | 
|  | 1964 | { | 
| Victor Stinner | 8370e07 | 2021-03-24 02:23:01 +0100 | [diff] [blame] | 1965 | StarEtc *a = _PyArena_Malloc(p->arena, sizeof(StarEtc)); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1966 | if (!a) { | 
|  | 1967 | return NULL; | 
|  | 1968 | } | 
|  | 1969 | a->vararg = vararg; | 
|  | 1970 | a->kwonlyargs = kwonlyargs; | 
|  | 1971 | a->kwarg = kwarg; | 
|  | 1972 | return a; | 
|  | 1973 | } | 
|  | 1974 |  | 
|  | 1975 | asdl_seq * | 
|  | 1976 | _PyPegen_join_sequences(Parser *p, asdl_seq *a, asdl_seq *b) | 
|  | 1977 | { | 
| Pablo Galindo | ee40e4b | 2020-04-23 03:43:08 +0100 | [diff] [blame] | 1978 | Py_ssize_t first_len = asdl_seq_LEN(a); | 
|  | 1979 | Py_ssize_t second_len = asdl_seq_LEN(b); | 
| Pablo Galindo | a5634c4 | 2020-09-16 19:42:00 +0100 | [diff] [blame] | 1980 | asdl_seq *new_seq = (asdl_seq*)_Py_asdl_generic_seq_new(first_len + second_len, p->arena); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1981 | if (!new_seq) { | 
|  | 1982 | return NULL; | 
|  | 1983 | } | 
|  | 1984 |  | 
|  | 1985 | int k = 0; | 
|  | 1986 | for (Py_ssize_t i = 0; i < first_len; i++) { | 
| Pablo Galindo | a5634c4 | 2020-09-16 19:42:00 +0100 | [diff] [blame] | 1987 | asdl_seq_SET_UNTYPED(new_seq, k++, asdl_seq_GET_UNTYPED(a, i)); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1988 | } | 
|  | 1989 | for (Py_ssize_t i = 0; i < second_len; i++) { | 
| Pablo Galindo | a5634c4 | 2020-09-16 19:42:00 +0100 | [diff] [blame] | 1990 | asdl_seq_SET_UNTYPED(new_seq, k++, asdl_seq_GET_UNTYPED(b, i)); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1991 | } | 
|  | 1992 |  | 
|  | 1993 | return new_seq; | 
|  | 1994 | } | 
|  | 1995 |  | 
| Pablo Galindo | a5634c4 | 2020-09-16 19:42:00 +0100 | [diff] [blame] | 1996 | static asdl_arg_seq* | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 1997 | _get_names(Parser *p, asdl_seq *names_with_defaults) | 
|  | 1998 | { | 
| Pablo Galindo | ee40e4b | 2020-04-23 03:43:08 +0100 | [diff] [blame] | 1999 | Py_ssize_t len = asdl_seq_LEN(names_with_defaults); | 
| Pablo Galindo | a5634c4 | 2020-09-16 19:42:00 +0100 | [diff] [blame] | 2000 | asdl_arg_seq *seq = _Py_asdl_arg_seq_new(len, p->arena); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 2001 | if (!seq) { | 
|  | 2002 | return NULL; | 
|  | 2003 | } | 
|  | 2004 | for (Py_ssize_t i = 0; i < len; i++) { | 
| Pablo Galindo | a5634c4 | 2020-09-16 19:42:00 +0100 | [diff] [blame] | 2005 | NameDefaultPair *pair = asdl_seq_GET_UNTYPED(names_with_defaults, i); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 2006 | asdl_seq_SET(seq, i, pair->arg); | 
|  | 2007 | } | 
|  | 2008 | return seq; | 
|  | 2009 | } | 
|  | 2010 |  | 
| Pablo Galindo | a5634c4 | 2020-09-16 19:42:00 +0100 | [diff] [blame] | 2011 | static asdl_expr_seq * | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 2012 | _get_defaults(Parser *p, asdl_seq *names_with_defaults) | 
|  | 2013 | { | 
| Pablo Galindo | ee40e4b | 2020-04-23 03:43:08 +0100 | [diff] [blame] | 2014 | Py_ssize_t len = asdl_seq_LEN(names_with_defaults); | 
| Pablo Galindo | a5634c4 | 2020-09-16 19:42:00 +0100 | [diff] [blame] | 2015 | asdl_expr_seq *seq = _Py_asdl_expr_seq_new(len, p->arena); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 2016 | if (!seq) { | 
|  | 2017 | return NULL; | 
|  | 2018 | } | 
|  | 2019 | for (Py_ssize_t i = 0; i < len; i++) { | 
| Pablo Galindo | a5634c4 | 2020-09-16 19:42:00 +0100 | [diff] [blame] | 2020 | NameDefaultPair *pair = asdl_seq_GET_UNTYPED(names_with_defaults, i); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 2021 | asdl_seq_SET(seq, i, pair->value); | 
|  | 2022 | } | 
|  | 2023 | return seq; | 
|  | 2024 | } | 
|  | 2025 |  | 
| Pablo Galindo | 4f642da | 2021-04-09 00:48:53 +0100 | [diff] [blame] | 2026 | static int | 
|  | 2027 | _make_posonlyargs(Parser *p, | 
|  | 2028 | asdl_arg_seq *slash_without_default, | 
|  | 2029 | SlashWithDefault *slash_with_default, | 
|  | 2030 | asdl_arg_seq **posonlyargs) { | 
|  | 2031 | if (slash_without_default != NULL) { | 
|  | 2032 | *posonlyargs = slash_without_default; | 
|  | 2033 | } | 
|  | 2034 | else if (slash_with_default != NULL) { | 
|  | 2035 | asdl_arg_seq *slash_with_default_names = | 
|  | 2036 | _get_names(p, slash_with_default->names_with_defaults); | 
|  | 2037 | if (!slash_with_default_names) { | 
|  | 2038 | return -1; | 
|  | 2039 | } | 
|  | 2040 | *posonlyargs = (asdl_arg_seq*)_PyPegen_join_sequences( | 
|  | 2041 | p, | 
|  | 2042 | (asdl_seq*)slash_with_default->plain_names, | 
|  | 2043 | (asdl_seq*)slash_with_default_names); | 
|  | 2044 | } | 
|  | 2045 | else { | 
|  | 2046 | *posonlyargs = _Py_asdl_arg_seq_new(0, p->arena); | 
|  | 2047 | } | 
|  | 2048 | return *posonlyargs == NULL ? -1 : 0; | 
|  | 2049 | } | 
|  | 2050 |  | 
|  | 2051 | static int | 
|  | 2052 | _make_posargs(Parser *p, | 
|  | 2053 | asdl_arg_seq *plain_names, | 
|  | 2054 | asdl_seq *names_with_default, | 
|  | 2055 | asdl_arg_seq **posargs) { | 
|  | 2056 | if (plain_names != NULL && names_with_default != NULL) { | 
|  | 2057 | asdl_arg_seq *names_with_default_names = _get_names(p, names_with_default); | 
|  | 2058 | if (!names_with_default_names) { | 
|  | 2059 | return -1; | 
|  | 2060 | } | 
|  | 2061 | *posargs = (asdl_arg_seq*)_PyPegen_join_sequences( | 
|  | 2062 | p,(asdl_seq*)plain_names, (asdl_seq*)names_with_default_names); | 
|  | 2063 | } | 
|  | 2064 | else if (plain_names == NULL && names_with_default != NULL) { | 
|  | 2065 | *posargs = _get_names(p, names_with_default); | 
|  | 2066 | } | 
|  | 2067 | else if (plain_names != NULL && names_with_default == NULL) { | 
|  | 2068 | *posargs = plain_names; | 
|  | 2069 | } | 
|  | 2070 | else { | 
|  | 2071 | *posargs = _Py_asdl_arg_seq_new(0, p->arena); | 
|  | 2072 | } | 
|  | 2073 | return *posargs == NULL ? -1 : 0; | 
|  | 2074 | } | 
|  | 2075 |  | 
|  | 2076 | static int | 
|  | 2077 | _make_posdefaults(Parser *p, | 
|  | 2078 | SlashWithDefault *slash_with_default, | 
|  | 2079 | asdl_seq *names_with_default, | 
|  | 2080 | asdl_expr_seq **posdefaults) { | 
|  | 2081 | if (slash_with_default != NULL && names_with_default != NULL) { | 
|  | 2082 | asdl_expr_seq *slash_with_default_values = | 
|  | 2083 | _get_defaults(p, slash_with_default->names_with_defaults); | 
|  | 2084 | if (!slash_with_default_values) { | 
|  | 2085 | return -1; | 
|  | 2086 | } | 
|  | 2087 | asdl_expr_seq *names_with_default_values = _get_defaults(p, names_with_default); | 
|  | 2088 | if (!names_with_default_values) { | 
|  | 2089 | return -1; | 
|  | 2090 | } | 
|  | 2091 | *posdefaults = (asdl_expr_seq*)_PyPegen_join_sequences( | 
|  | 2092 | p, | 
|  | 2093 | (asdl_seq*)slash_with_default_values, | 
|  | 2094 | (asdl_seq*)names_with_default_values); | 
|  | 2095 | } | 
|  | 2096 | else if (slash_with_default == NULL && names_with_default != NULL) { | 
|  | 2097 | *posdefaults = _get_defaults(p, names_with_default); | 
|  | 2098 | } | 
|  | 2099 | else if (slash_with_default != NULL && names_with_default == NULL) { | 
|  | 2100 | *posdefaults = _get_defaults(p, slash_with_default->names_with_defaults); | 
|  | 2101 | } | 
|  | 2102 | else { | 
|  | 2103 | *posdefaults = _Py_asdl_expr_seq_new(0, p->arena); | 
|  | 2104 | } | 
|  | 2105 | return *posdefaults == NULL ? -1 : 0; | 
|  | 2106 | } | 
|  | 2107 |  | 
|  | 2108 | static int | 
|  | 2109 | _make_kwargs(Parser *p, StarEtc *star_etc, | 
|  | 2110 | asdl_arg_seq **kwonlyargs, | 
|  | 2111 | asdl_expr_seq **kwdefaults) { | 
|  | 2112 | if (star_etc != NULL && star_etc->kwonlyargs != NULL) { | 
|  | 2113 | *kwonlyargs = _get_names(p, star_etc->kwonlyargs); | 
|  | 2114 | } | 
|  | 2115 | else { | 
|  | 2116 | *kwonlyargs = _Py_asdl_arg_seq_new(0, p->arena); | 
|  | 2117 | } | 
|  | 2118 |  | 
|  | 2119 | if (*kwonlyargs == NULL) { | 
|  | 2120 | return -1; | 
|  | 2121 | } | 
|  | 2122 |  | 
|  | 2123 | if (star_etc != NULL && star_etc->kwonlyargs != NULL) { | 
|  | 2124 | *kwdefaults = _get_defaults(p, star_etc->kwonlyargs); | 
|  | 2125 | } | 
|  | 2126 | else { | 
|  | 2127 | *kwdefaults = _Py_asdl_expr_seq_new(0, p->arena); | 
|  | 2128 | } | 
|  | 2129 |  | 
|  | 2130 | if (*kwdefaults == NULL) { | 
|  | 2131 | return -1; | 
|  | 2132 | } | 
|  | 2133 |  | 
|  | 2134 | return 0; | 
|  | 2135 | } | 
|  | 2136 |  | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 2137 | /* Constructs an arguments_ty object out of all the parsed constructs in the parameters rule */ | 
|  | 2138 | arguments_ty | 
| Pablo Galindo | a5634c4 | 2020-09-16 19:42:00 +0100 | [diff] [blame] | 2139 | _PyPegen_make_arguments(Parser *p, asdl_arg_seq *slash_without_default, | 
|  | 2140 | SlashWithDefault *slash_with_default, asdl_arg_seq *plain_names, | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 2141 | asdl_seq *names_with_default, StarEtc *star_etc) | 
|  | 2142 | { | 
| Pablo Galindo | a5634c4 | 2020-09-16 19:42:00 +0100 | [diff] [blame] | 2143 | asdl_arg_seq *posonlyargs; | 
| Pablo Galindo | 4f642da | 2021-04-09 00:48:53 +0100 | [diff] [blame] | 2144 | if (_make_posonlyargs(p, slash_without_default, slash_with_default, &posonlyargs) == -1) { | 
|  | 2145 | return NULL; | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 2146 | } | 
|  | 2147 |  | 
| Pablo Galindo | a5634c4 | 2020-09-16 19:42:00 +0100 | [diff] [blame] | 2148 | asdl_arg_seq *posargs; | 
| Pablo Galindo | 4f642da | 2021-04-09 00:48:53 +0100 | [diff] [blame] | 2149 | if (_make_posargs(p, plain_names, names_with_default, &posargs) == -1) { | 
|  | 2150 | return NULL; | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 2151 | } | 
|  | 2152 |  | 
| Pablo Galindo | a5634c4 | 2020-09-16 19:42:00 +0100 | [diff] [blame] | 2153 | asdl_expr_seq *posdefaults; | 
| Pablo Galindo | 4f642da | 2021-04-09 00:48:53 +0100 | [diff] [blame] | 2154 | if (_make_posdefaults(p,slash_with_default, names_with_default, &posdefaults) == -1) { | 
|  | 2155 | return NULL; | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 2156 | } | 
|  | 2157 |  | 
|  | 2158 | arg_ty vararg = NULL; | 
|  | 2159 | if (star_etc != NULL && star_etc->vararg != NULL) { | 
|  | 2160 | vararg = star_etc->vararg; | 
|  | 2161 | } | 
|  | 2162 |  | 
| Pablo Galindo | a5634c4 | 2020-09-16 19:42:00 +0100 | [diff] [blame] | 2163 | asdl_arg_seq *kwonlyargs; | 
| Pablo Galindo | a5634c4 | 2020-09-16 19:42:00 +0100 | [diff] [blame] | 2164 | asdl_expr_seq *kwdefaults; | 
| Pablo Galindo | 4f642da | 2021-04-09 00:48:53 +0100 | [diff] [blame] | 2165 | if (_make_kwargs(p, star_etc, &kwonlyargs, &kwdefaults) == -1) { | 
|  | 2166 | return NULL; | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 2167 | } | 
|  | 2168 |  | 
|  | 2169 | arg_ty kwarg = NULL; | 
|  | 2170 | if (star_etc != NULL && star_etc->kwarg != NULL) { | 
|  | 2171 | kwarg = star_etc->kwarg; | 
|  | 2172 | } | 
|  | 2173 |  | 
| Victor Stinner | d27f8d2 | 2021-04-07 21:34:22 +0200 | [diff] [blame] | 2174 | return _PyAST_arguments(posonlyargs, posargs, vararg, kwonlyargs, | 
|  | 2175 | kwdefaults, kwarg, posdefaults, p->arena); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 2176 | } | 
|  | 2177 |  | 
| Pablo Galindo | 4f642da | 2021-04-09 00:48:53 +0100 | [diff] [blame] | 2178 |  | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 2179 | /* Constructs an empty arguments_ty object, that gets used when a function accepts no | 
|  | 2180 | * arguments. */ | 
|  | 2181 | arguments_ty | 
|  | 2182 | _PyPegen_empty_arguments(Parser *p) | 
|  | 2183 | { | 
| Pablo Galindo | a5634c4 | 2020-09-16 19:42:00 +0100 | [diff] [blame] | 2184 | asdl_arg_seq *posonlyargs = _Py_asdl_arg_seq_new(0, p->arena); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 2185 | if (!posonlyargs) { | 
|  | 2186 | return NULL; | 
|  | 2187 | } | 
| Pablo Galindo | a5634c4 | 2020-09-16 19:42:00 +0100 | [diff] [blame] | 2188 | asdl_arg_seq *posargs = _Py_asdl_arg_seq_new(0, p->arena); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 2189 | if (!posargs) { | 
|  | 2190 | return NULL; | 
|  | 2191 | } | 
| Pablo Galindo | a5634c4 | 2020-09-16 19:42:00 +0100 | [diff] [blame] | 2192 | asdl_expr_seq *posdefaults = _Py_asdl_expr_seq_new(0, p->arena); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 2193 | if (!posdefaults) { | 
|  | 2194 | return NULL; | 
|  | 2195 | } | 
| Pablo Galindo | a5634c4 | 2020-09-16 19:42:00 +0100 | [diff] [blame] | 2196 | asdl_arg_seq *kwonlyargs = _Py_asdl_arg_seq_new(0, p->arena); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 2197 | if (!kwonlyargs) { | 
|  | 2198 | return NULL; | 
|  | 2199 | } | 
| Pablo Galindo | a5634c4 | 2020-09-16 19:42:00 +0100 | [diff] [blame] | 2200 | asdl_expr_seq *kwdefaults = _Py_asdl_expr_seq_new(0, p->arena); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 2201 | if (!kwdefaults) { | 
|  | 2202 | return NULL; | 
|  | 2203 | } | 
|  | 2204 |  | 
| Victor Stinner | d27f8d2 | 2021-04-07 21:34:22 +0200 | [diff] [blame] | 2205 | return _PyAST_arguments(posonlyargs, posargs, NULL, kwonlyargs, | 
|  | 2206 | kwdefaults, NULL, posdefaults, p->arena); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 2207 | } | 
|  | 2208 |  | 
|  | 2209 | /* Encapsulates the value of an operator_ty into an AugOperator struct */ | 
|  | 2210 | AugOperator * | 
|  | 2211 | _PyPegen_augoperator(Parser *p, operator_ty kind) | 
|  | 2212 | { | 
| Victor Stinner | 8370e07 | 2021-03-24 02:23:01 +0100 | [diff] [blame] | 2213 | AugOperator *a = _PyArena_Malloc(p->arena, sizeof(AugOperator)); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 2214 | if (!a) { | 
|  | 2215 | return NULL; | 
|  | 2216 | } | 
|  | 2217 | a->kind = kind; | 
|  | 2218 | return a; | 
|  | 2219 | } | 
|  | 2220 |  | 
|  | 2221 | /* Construct a FunctionDef equivalent to function_def, but with decorators */ | 
|  | 2222 | stmt_ty | 
| Pablo Galindo | a5634c4 | 2020-09-16 19:42:00 +0100 | [diff] [blame] | 2223 | _PyPegen_function_def_decorators(Parser *p, asdl_expr_seq *decorators, stmt_ty function_def) | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 2224 | { | 
|  | 2225 | assert(function_def != NULL); | 
|  | 2226 | if (function_def->kind == AsyncFunctionDef_kind) { | 
| Victor Stinner | d27f8d2 | 2021-04-07 21:34:22 +0200 | [diff] [blame] | 2227 | return _PyAST_AsyncFunctionDef( | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 2228 | function_def->v.FunctionDef.name, function_def->v.FunctionDef.args, | 
|  | 2229 | function_def->v.FunctionDef.body, decorators, function_def->v.FunctionDef.returns, | 
|  | 2230 | function_def->v.FunctionDef.type_comment, function_def->lineno, | 
|  | 2231 | function_def->col_offset, function_def->end_lineno, function_def->end_col_offset, | 
|  | 2232 | p->arena); | 
|  | 2233 | } | 
|  | 2234 |  | 
| Victor Stinner | d27f8d2 | 2021-04-07 21:34:22 +0200 | [diff] [blame] | 2235 | return _PyAST_FunctionDef( | 
|  | 2236 | function_def->v.FunctionDef.name, function_def->v.FunctionDef.args, | 
|  | 2237 | function_def->v.FunctionDef.body, decorators, | 
|  | 2238 | function_def->v.FunctionDef.returns, | 
|  | 2239 | function_def->v.FunctionDef.type_comment, function_def->lineno, | 
|  | 2240 | function_def->col_offset, function_def->end_lineno, | 
|  | 2241 | function_def->end_col_offset, p->arena); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 2242 | } | 
|  | 2243 |  | 
|  | 2244 | /* Construct a ClassDef equivalent to class_def, but with decorators */ | 
|  | 2245 | stmt_ty | 
| Pablo Galindo | a5634c4 | 2020-09-16 19:42:00 +0100 | [diff] [blame] | 2246 | _PyPegen_class_def_decorators(Parser *p, asdl_expr_seq *decorators, stmt_ty class_def) | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 2247 | { | 
|  | 2248 | assert(class_def != NULL); | 
| Victor Stinner | d27f8d2 | 2021-04-07 21:34:22 +0200 | [diff] [blame] | 2249 | return _PyAST_ClassDef( | 
|  | 2250 | class_def->v.ClassDef.name, class_def->v.ClassDef.bases, | 
|  | 2251 | class_def->v.ClassDef.keywords, class_def->v.ClassDef.body, decorators, | 
|  | 2252 | class_def->lineno, class_def->col_offset, class_def->end_lineno, | 
|  | 2253 | class_def->end_col_offset, p->arena); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 2254 | } | 
|  | 2255 |  | 
|  | 2256 | /* Construct a KeywordOrStarred */ | 
|  | 2257 | KeywordOrStarred * | 
|  | 2258 | _PyPegen_keyword_or_starred(Parser *p, void *element, int is_keyword) | 
|  | 2259 | { | 
| Victor Stinner | 8370e07 | 2021-03-24 02:23:01 +0100 | [diff] [blame] | 2260 | KeywordOrStarred *a = _PyArena_Malloc(p->arena, sizeof(KeywordOrStarred)); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 2261 | if (!a) { | 
|  | 2262 | return NULL; | 
|  | 2263 | } | 
|  | 2264 | a->element = element; | 
|  | 2265 | a->is_keyword = is_keyword; | 
|  | 2266 | return a; | 
|  | 2267 | } | 
|  | 2268 |  | 
|  | 2269 | /* Get the number of starred expressions in an asdl_seq* of KeywordOrStarred*s */ | 
|  | 2270 | static int | 
|  | 2271 | _seq_number_of_starred_exprs(asdl_seq *seq) | 
|  | 2272 | { | 
|  | 2273 | int n = 0; | 
|  | 2274 | for (Py_ssize_t i = 0, l = asdl_seq_LEN(seq); i < l; i++) { | 
| Pablo Galindo | a5634c4 | 2020-09-16 19:42:00 +0100 | [diff] [blame] | 2275 | KeywordOrStarred *k = asdl_seq_GET_UNTYPED(seq, i); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 2276 | if (!k->is_keyword) { | 
|  | 2277 | n++; | 
|  | 2278 | } | 
|  | 2279 | } | 
|  | 2280 | return n; | 
|  | 2281 | } | 
|  | 2282 |  | 
|  | 2283 | /* Extract the starred expressions of an asdl_seq* of KeywordOrStarred*s */ | 
| Pablo Galindo | a5634c4 | 2020-09-16 19:42:00 +0100 | [diff] [blame] | 2284 | asdl_expr_seq * | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 2285 | _PyPegen_seq_extract_starred_exprs(Parser *p, asdl_seq *kwargs) | 
|  | 2286 | { | 
|  | 2287 | int new_len = _seq_number_of_starred_exprs(kwargs); | 
|  | 2288 | if (new_len == 0) { | 
|  | 2289 | return NULL; | 
|  | 2290 | } | 
| Pablo Galindo | a5634c4 | 2020-09-16 19:42:00 +0100 | [diff] [blame] | 2291 | asdl_expr_seq *new_seq = _Py_asdl_expr_seq_new(new_len, p->arena); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 2292 | if (!new_seq) { | 
|  | 2293 | return NULL; | 
|  | 2294 | } | 
|  | 2295 |  | 
|  | 2296 | int idx = 0; | 
|  | 2297 | for (Py_ssize_t i = 0, len = asdl_seq_LEN(kwargs); i < len; i++) { | 
| Pablo Galindo | a5634c4 | 2020-09-16 19:42:00 +0100 | [diff] [blame] | 2298 | KeywordOrStarred *k = asdl_seq_GET_UNTYPED(kwargs, i); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 2299 | if (!k->is_keyword) { | 
|  | 2300 | asdl_seq_SET(new_seq, idx++, k->element); | 
|  | 2301 | } | 
|  | 2302 | } | 
|  | 2303 | return new_seq; | 
|  | 2304 | } | 
|  | 2305 |  | 
|  | 2306 | /* Return a new asdl_seq* with only the keywords in kwargs */ | 
| Pablo Galindo | a5634c4 | 2020-09-16 19:42:00 +0100 | [diff] [blame] | 2307 | asdl_keyword_seq* | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 2308 | _PyPegen_seq_delete_starred_exprs(Parser *p, asdl_seq *kwargs) | 
|  | 2309 | { | 
| Pablo Galindo | ee40e4b | 2020-04-23 03:43:08 +0100 | [diff] [blame] | 2310 | Py_ssize_t len = asdl_seq_LEN(kwargs); | 
|  | 2311 | Py_ssize_t new_len = len - _seq_number_of_starred_exprs(kwargs); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 2312 | if (new_len == 0) { | 
|  | 2313 | return NULL; | 
|  | 2314 | } | 
| Pablo Galindo | a5634c4 | 2020-09-16 19:42:00 +0100 | [diff] [blame] | 2315 | asdl_keyword_seq *new_seq = _Py_asdl_keyword_seq_new(new_len, p->arena); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 2316 | if (!new_seq) { | 
|  | 2317 | return NULL; | 
|  | 2318 | } | 
|  | 2319 |  | 
|  | 2320 | int idx = 0; | 
|  | 2321 | for (Py_ssize_t i = 0; i < len; i++) { | 
| Pablo Galindo | a5634c4 | 2020-09-16 19:42:00 +0100 | [diff] [blame] | 2322 | KeywordOrStarred *k = asdl_seq_GET_UNTYPED(kwargs, i); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 2323 | if (k->is_keyword) { | 
|  | 2324 | asdl_seq_SET(new_seq, idx++, k->element); | 
|  | 2325 | } | 
|  | 2326 | } | 
|  | 2327 | return new_seq; | 
|  | 2328 | } | 
|  | 2329 |  | 
|  | 2330 | expr_ty | 
|  | 2331 | _PyPegen_concatenate_strings(Parser *p, asdl_seq *strings) | 
|  | 2332 | { | 
| Pablo Galindo | ee40e4b | 2020-04-23 03:43:08 +0100 | [diff] [blame] | 2333 | Py_ssize_t len = asdl_seq_LEN(strings); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 2334 | assert(len > 0); | 
|  | 2335 |  | 
| Pablo Galindo | a5634c4 | 2020-09-16 19:42:00 +0100 | [diff] [blame] | 2336 | Token *first = asdl_seq_GET_UNTYPED(strings, 0); | 
|  | 2337 | Token *last = asdl_seq_GET_UNTYPED(strings, len - 1); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 2338 |  | 
|  | 2339 | int bytesmode = 0; | 
|  | 2340 | PyObject *bytes_str = NULL; | 
|  | 2341 |  | 
|  | 2342 | FstringParser state; | 
|  | 2343 | _PyPegen_FstringParser_Init(&state); | 
|  | 2344 |  | 
|  | 2345 | for (Py_ssize_t i = 0; i < len; i++) { | 
| Pablo Galindo | a5634c4 | 2020-09-16 19:42:00 +0100 | [diff] [blame] | 2346 | Token *t = asdl_seq_GET_UNTYPED(strings, i); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 2347 |  | 
|  | 2348 | int this_bytesmode; | 
|  | 2349 | int this_rawmode; | 
|  | 2350 | PyObject *s; | 
|  | 2351 | const char *fstr; | 
|  | 2352 | Py_ssize_t fstrlen = -1; | 
|  | 2353 |  | 
| Lysandros Nikolaou | 2f37c35 | 2020-05-07 13:37:51 +0300 | [diff] [blame] | 2354 | if (_PyPegen_parsestr(p, &this_bytesmode, &this_rawmode, &s, &fstr, &fstrlen, t) != 0) { | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 2355 | goto error; | 
|  | 2356 | } | 
|  | 2357 |  | 
|  | 2358 | /* Check that we are not mixing bytes with unicode. */ | 
|  | 2359 | if (i != 0 && bytesmode != this_bytesmode) { | 
|  | 2360 | RAISE_SYNTAX_ERROR("cannot mix bytes and nonbytes literals"); | 
|  | 2361 | Py_XDECREF(s); | 
|  | 2362 | goto error; | 
|  | 2363 | } | 
|  | 2364 | bytesmode = this_bytesmode; | 
|  | 2365 |  | 
|  | 2366 | if (fstr != NULL) { | 
|  | 2367 | assert(s == NULL && !bytesmode); | 
|  | 2368 |  | 
|  | 2369 | int result = _PyPegen_FstringParser_ConcatFstring(p, &state, &fstr, fstr + fstrlen, | 
|  | 2370 | this_rawmode, 0, first, t, last); | 
|  | 2371 | if (result < 0) { | 
|  | 2372 | goto error; | 
|  | 2373 | } | 
|  | 2374 | } | 
|  | 2375 | else { | 
|  | 2376 | /* String or byte string. */ | 
|  | 2377 | assert(s != NULL && fstr == NULL); | 
|  | 2378 | assert(bytesmode ? PyBytes_CheckExact(s) : PyUnicode_CheckExact(s)); | 
|  | 2379 |  | 
|  | 2380 | if (bytesmode) { | 
|  | 2381 | if (i == 0) { | 
|  | 2382 | bytes_str = s; | 
|  | 2383 | } | 
|  | 2384 | else { | 
|  | 2385 | PyBytes_ConcatAndDel(&bytes_str, s); | 
|  | 2386 | if (!bytes_str) { | 
|  | 2387 | goto error; | 
|  | 2388 | } | 
|  | 2389 | } | 
|  | 2390 | } | 
|  | 2391 | else { | 
|  | 2392 | /* This is a regular string. Concatenate it. */ | 
|  | 2393 | if (_PyPegen_FstringParser_ConcatAndDel(&state, s) < 0) { | 
|  | 2394 | goto error; | 
|  | 2395 | } | 
|  | 2396 | } | 
|  | 2397 | } | 
|  | 2398 | } | 
|  | 2399 |  | 
|  | 2400 | if (bytesmode) { | 
| Victor Stinner | 8370e07 | 2021-03-24 02:23:01 +0100 | [diff] [blame] | 2401 | if (_PyArena_AddPyObject(p->arena, bytes_str) < 0) { | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 2402 | goto error; | 
|  | 2403 | } | 
| Victor Stinner | d27f8d2 | 2021-04-07 21:34:22 +0200 | [diff] [blame] | 2404 | return _PyAST_Constant(bytes_str, NULL, first->lineno, | 
|  | 2405 | first->col_offset, last->end_lineno, | 
|  | 2406 | last->end_col_offset, p->arena); | 
| Pablo Galindo | c5fc156 | 2020-04-22 23:29:27 +0100 | [diff] [blame] | 2407 | } | 
|  | 2408 |  | 
|  | 2409 | return _PyPegen_FstringParser_Finish(p, &state, first, last); | 
|  | 2410 |  | 
|  | 2411 | error: | 
|  | 2412 | Py_XDECREF(bytes_str); | 
|  | 2413 | _PyPegen_FstringParser_Dealloc(&state); | 
|  | 2414 | if (PyErr_Occurred()) { | 
|  | 2415 | raise_decode_error(p); | 
|  | 2416 | } | 
|  | 2417 | return NULL; | 
|  | 2418 | } | 
| Guido van Rossum | c001c09 | 2020-04-30 12:12:19 -0700 | [diff] [blame] | 2419 |  | 
| Nick Coghlan | 1e7b858 | 2021-04-29 15:58:44 +1000 | [diff] [blame] | 2420 | expr_ty | 
|  | 2421 | _PyPegen_ensure_imaginary(Parser *p, expr_ty exp) | 
|  | 2422 | { | 
|  | 2423 | if (exp->kind != Constant_kind || !PyComplex_CheckExact(exp->v.Constant.value)) { | 
| Brandt Bucher | dbe60ee | 2021-04-29 17:19:28 -0700 | [diff] [blame] | 2424 | RAISE_SYNTAX_ERROR_KNOWN_LOCATION(exp, "imaginary number required in complex literal"); | 
|  | 2425 | return NULL; | 
|  | 2426 | } | 
|  | 2427 | return exp; | 
|  | 2428 | } | 
|  | 2429 |  | 
|  | 2430 | expr_ty | 
|  | 2431 | _PyPegen_ensure_real(Parser *p, expr_ty exp) | 
|  | 2432 | { | 
|  | 2433 | if (exp->kind != Constant_kind || PyComplex_CheckExact(exp->v.Constant.value)) { | 
|  | 2434 | RAISE_SYNTAX_ERROR_KNOWN_LOCATION(exp, "real number required in complex literal"); | 
| Nick Coghlan | 1e7b858 | 2021-04-29 15:58:44 +1000 | [diff] [blame] | 2435 | return NULL; | 
|  | 2436 | } | 
|  | 2437 | return exp; | 
|  | 2438 | } | 
|  | 2439 |  | 
| Guido van Rossum | c001c09 | 2020-04-30 12:12:19 -0700 | [diff] [blame] | 2440 | mod_ty | 
| Pablo Galindo | a5634c4 | 2020-09-16 19:42:00 +0100 | [diff] [blame] | 2441 | _PyPegen_make_module(Parser *p, asdl_stmt_seq *a) { | 
|  | 2442 | asdl_type_ignore_seq *type_ignores = NULL; | 
| Guido van Rossum | c001c09 | 2020-04-30 12:12:19 -0700 | [diff] [blame] | 2443 | Py_ssize_t num = p->type_ignore_comments.num_items; | 
|  | 2444 | if (num > 0) { | 
|  | 2445 | // Turn the raw (comment, lineno) pairs into TypeIgnore objects in the arena | 
| Pablo Galindo | a5634c4 | 2020-09-16 19:42:00 +0100 | [diff] [blame] | 2446 | type_ignores = _Py_asdl_type_ignore_seq_new(num, p->arena); | 
| Guido van Rossum | c001c09 | 2020-04-30 12:12:19 -0700 | [diff] [blame] | 2447 | if (type_ignores == NULL) { | 
|  | 2448 | return NULL; | 
|  | 2449 | } | 
|  | 2450 | for (int i = 0; i < num; i++) { | 
|  | 2451 | PyObject *tag = _PyPegen_new_type_comment(p, p->type_ignore_comments.items[i].comment); | 
|  | 2452 | if (tag == NULL) { | 
|  | 2453 | return NULL; | 
|  | 2454 | } | 
| Victor Stinner | d27f8d2 | 2021-04-07 21:34:22 +0200 | [diff] [blame] | 2455 | type_ignore_ty ti = _PyAST_TypeIgnore(p->type_ignore_comments.items[i].lineno, | 
|  | 2456 | tag, p->arena); | 
| Guido van Rossum | c001c09 | 2020-04-30 12:12:19 -0700 | [diff] [blame] | 2457 | if (ti == NULL) { | 
|  | 2458 | return NULL; | 
|  | 2459 | } | 
|  | 2460 | asdl_seq_SET(type_ignores, i, ti); | 
|  | 2461 | } | 
|  | 2462 | } | 
| Victor Stinner | d27f8d2 | 2021-04-07 21:34:22 +0200 | [diff] [blame] | 2463 | return _PyAST_Module(a, type_ignores, p->arena); | 
| Guido van Rossum | c001c09 | 2020-04-30 12:12:19 -0700 | [diff] [blame] | 2464 | } | 
| Pablo Galindo | 16ab070 | 2020-05-15 02:04:52 +0100 | [diff] [blame] | 2465 |  | 
|  | 2466 | // Error reporting helpers | 
|  | 2467 |  | 
|  | 2468 | expr_ty | 
| Lysandros Nikolaou | 01ece63 | 2020-06-19 02:10:43 +0300 | [diff] [blame] | 2469 | _PyPegen_get_invalid_target(expr_ty e, TARGETS_TYPE targets_type) | 
| Pablo Galindo | 16ab070 | 2020-05-15 02:04:52 +0100 | [diff] [blame] | 2470 | { | 
|  | 2471 | if (e == NULL) { | 
|  | 2472 | return NULL; | 
|  | 2473 | } | 
|  | 2474 |  | 
|  | 2475 | #define VISIT_CONTAINER(CONTAINER, TYPE) do { \ | 
| Pablo Galindo | 58bafe4 | 2021-04-09 01:17:31 +0100 | [diff] [blame] | 2476 | Py_ssize_t len = asdl_seq_LEN((CONTAINER)->v.TYPE.elts);\ | 
| Pablo Galindo | 16ab070 | 2020-05-15 02:04:52 +0100 | [diff] [blame] | 2477 | for (Py_ssize_t i = 0; i < len; i++) {\ | 
| Pablo Galindo | 58bafe4 | 2021-04-09 01:17:31 +0100 | [diff] [blame] | 2478 | expr_ty other = asdl_seq_GET((CONTAINER)->v.TYPE.elts, i);\ | 
| Lysandros Nikolaou | 01ece63 | 2020-06-19 02:10:43 +0300 | [diff] [blame] | 2479 | expr_ty child = _PyPegen_get_invalid_target(other, targets_type);\ | 
| Pablo Galindo | 16ab070 | 2020-05-15 02:04:52 +0100 | [diff] [blame] | 2480 | if (child != NULL) {\ | 
|  | 2481 | return child;\ | 
|  | 2482 | }\ | 
|  | 2483 | }\ | 
|  | 2484 | } while (0) | 
|  | 2485 |  | 
|  | 2486 | // We only need to visit List and Tuple nodes recursively as those | 
|  | 2487 | // are the only ones that can contain valid names in targets when | 
|  | 2488 | // they are parsed as expressions. Any other kind of expression | 
|  | 2489 | // that is a container (like Sets or Dicts) is directly invalid and | 
|  | 2490 | // we don't need to visit it recursively. | 
|  | 2491 |  | 
|  | 2492 | switch (e->kind) { | 
| Lysandros Nikolaou | 01ece63 | 2020-06-19 02:10:43 +0300 | [diff] [blame] | 2493 | case List_kind: | 
| Pablo Galindo | 16ab070 | 2020-05-15 02:04:52 +0100 | [diff] [blame] | 2494 | VISIT_CONTAINER(e, List); | 
|  | 2495 | return NULL; | 
| Lysandros Nikolaou | 01ece63 | 2020-06-19 02:10:43 +0300 | [diff] [blame] | 2496 | case Tuple_kind: | 
| Pablo Galindo | 16ab070 | 2020-05-15 02:04:52 +0100 | [diff] [blame] | 2497 | VISIT_CONTAINER(e, Tuple); | 
|  | 2498 | return NULL; | 
| Pablo Galindo | 16ab070 | 2020-05-15 02:04:52 +0100 | [diff] [blame] | 2499 | case Starred_kind: | 
| Lysandros Nikolaou | 01ece63 | 2020-06-19 02:10:43 +0300 | [diff] [blame] | 2500 | if (targets_type == DEL_TARGETS) { | 
|  | 2501 | return e; | 
|  | 2502 | } | 
|  | 2503 | return _PyPegen_get_invalid_target(e->v.Starred.value, targets_type); | 
|  | 2504 | case Compare_kind: | 
|  | 2505 | // This is needed, because the `a in b` in `for a in b` gets parsed | 
|  | 2506 | // as a comparison, and so we need to search the left side of the comparison | 
|  | 2507 | // for invalid targets. | 
|  | 2508 | if (targets_type == FOR_TARGETS) { | 
|  | 2509 | cmpop_ty cmpop = (cmpop_ty) asdl_seq_GET(e->v.Compare.ops, 0); | 
|  | 2510 | if (cmpop == In) { | 
|  | 2511 | return _PyPegen_get_invalid_target(e->v.Compare.left, targets_type); | 
|  | 2512 | } | 
|  | 2513 | return NULL; | 
|  | 2514 | } | 
|  | 2515 | return e; | 
| Pablo Galindo | 16ab070 | 2020-05-15 02:04:52 +0100 | [diff] [blame] | 2516 | case Name_kind: | 
|  | 2517 | case Subscript_kind: | 
|  | 2518 | case Attribute_kind: | 
|  | 2519 | return NULL; | 
|  | 2520 | default: | 
|  | 2521 | return e; | 
|  | 2522 | } | 
| Lysandros Nikolaou | 75b863a | 2020-05-18 22:14:47 +0300 | [diff] [blame] | 2523 | } | 
|  | 2524 |  | 
|  | 2525 | void *_PyPegen_arguments_parsing_error(Parser *p, expr_ty e) { | 
|  | 2526 | int kwarg_unpacking = 0; | 
|  | 2527 | for (Py_ssize_t i = 0, l = asdl_seq_LEN(e->v.Call.keywords); i < l; i++) { | 
|  | 2528 | keyword_ty keyword = asdl_seq_GET(e->v.Call.keywords, i); | 
|  | 2529 | if (!keyword->arg) { | 
|  | 2530 | kwarg_unpacking = 1; | 
|  | 2531 | } | 
|  | 2532 | } | 
|  | 2533 |  | 
|  | 2534 | const char *msg = NULL; | 
|  | 2535 | if (kwarg_unpacking) { | 
|  | 2536 | msg = "positional argument follows keyword argument unpacking"; | 
|  | 2537 | } else { | 
|  | 2538 | msg = "positional argument follows keyword argument"; | 
|  | 2539 | } | 
|  | 2540 |  | 
|  | 2541 | return RAISE_SYNTAX_ERROR(msg); | 
|  | 2542 | } | 
| Lysandros Nikolaou | ae14583 | 2020-05-22 03:56:52 +0300 | [diff] [blame] | 2543 |  | 
| Miss Islington (bot) | 9e209d4 | 2021-09-27 07:05:20 -0700 | [diff] [blame] | 2544 |  | 
|  | 2545 | static inline expr_ty | 
|  | 2546 | _PyPegen_get_last_comprehension_item(comprehension_ty comprehension) { | 
|  | 2547 | if (comprehension->ifs == NULL || asdl_seq_LEN(comprehension->ifs) == 0) { | 
|  | 2548 | return comprehension->iter; | 
|  | 2549 | } | 
|  | 2550 | return PyPegen_last_item(comprehension->ifs, expr_ty); | 
|  | 2551 | } | 
|  | 2552 |  | 
| Lysandros Nikolaou | ae14583 | 2020-05-22 03:56:52 +0300 | [diff] [blame] | 2553 | void * | 
| Miss Islington (bot) | 9e209d4 | 2021-09-27 07:05:20 -0700 | [diff] [blame] | 2554 | _PyPegen_nonparen_genexp_in_call(Parser *p, expr_ty args, asdl_comprehension_seq *comprehensions) | 
| Lysandros Nikolaou | ae14583 | 2020-05-22 03:56:52 +0300 | [diff] [blame] | 2555 | { | 
|  | 2556 | /* The rule that calls this function is 'args for_if_clauses'. | 
|  | 2557 | For the input f(L, x for x in y), L and x are in args and | 
|  | 2558 | the for is parsed as a for_if_clause. We have to check if | 
|  | 2559 | len <= 1, so that input like dict((a, b) for a, b in x) | 
|  | 2560 | gets successfully parsed and then we pass the last | 
|  | 2561 | argument (x in the above example) as the location of the | 
|  | 2562 | error */ | 
|  | 2563 | Py_ssize_t len = asdl_seq_LEN(args->v.Call.args); | 
|  | 2564 | if (len <= 1) { | 
|  | 2565 | return NULL; | 
|  | 2566 | } | 
|  | 2567 |  | 
| Miss Islington (bot) | 9e209d4 | 2021-09-27 07:05:20 -0700 | [diff] [blame] | 2568 | comprehension_ty last_comprehension = PyPegen_last_item(comprehensions, comprehension_ty); | 
|  | 2569 |  | 
|  | 2570 | return RAISE_SYNTAX_ERROR_KNOWN_RANGE( | 
| Lysandros Nikolaou | ae14583 | 2020-05-22 03:56:52 +0300 | [diff] [blame] | 2571 | (expr_ty) asdl_seq_GET(args->v.Call.args, len - 1), | 
| Miss Islington (bot) | 9e209d4 | 2021-09-27 07:05:20 -0700 | [diff] [blame] | 2572 | _PyPegen_get_last_comprehension_item(last_comprehension), | 
| Lysandros Nikolaou | ae14583 | 2020-05-22 03:56:52 +0300 | [diff] [blame] | 2573 | "Generator expression must be parenthesized" | 
|  | 2574 | ); | 
|  | 2575 | } | 
| Pablo Galindo | 4a97b15 | 2020-09-02 17:44:19 +0100 | [diff] [blame] | 2576 |  | 
|  | 2577 |  | 
| Pablo Galindo | a5634c4 | 2020-09-16 19:42:00 +0100 | [diff] [blame] | 2578 | expr_ty _PyPegen_collect_call_seqs(Parser *p, asdl_expr_seq *a, asdl_seq *b, | 
| Pablo Galindo | 315a61f | 2020-09-03 15:29:32 +0100 | [diff] [blame] | 2579 | int lineno, int col_offset, int end_lineno, | 
|  | 2580 | int end_col_offset, PyArena *arena) { | 
| Pablo Galindo | 4a97b15 | 2020-09-02 17:44:19 +0100 | [diff] [blame] | 2581 | Py_ssize_t args_len = asdl_seq_LEN(a); | 
|  | 2582 | Py_ssize_t total_len = args_len; | 
|  | 2583 |  | 
|  | 2584 | if (b == NULL) { | 
| Victor Stinner | d27f8d2 | 2021-04-07 21:34:22 +0200 | [diff] [blame] | 2585 | return _PyAST_Call(_PyPegen_dummy_name(p), a, NULL, lineno, col_offset, | 
| Pablo Galindo | 315a61f | 2020-09-03 15:29:32 +0100 | [diff] [blame] | 2586 | end_lineno, end_col_offset, arena); | 
| Pablo Galindo | 4a97b15 | 2020-09-02 17:44:19 +0100 | [diff] [blame] | 2587 |  | 
|  | 2588 | } | 
|  | 2589 |  | 
| Pablo Galindo | a5634c4 | 2020-09-16 19:42:00 +0100 | [diff] [blame] | 2590 | asdl_expr_seq *starreds = _PyPegen_seq_extract_starred_exprs(p, b); | 
|  | 2591 | asdl_keyword_seq *keywords = _PyPegen_seq_delete_starred_exprs(p, b); | 
| Pablo Galindo | 4a97b15 | 2020-09-02 17:44:19 +0100 | [diff] [blame] | 2592 |  | 
|  | 2593 | if (starreds) { | 
|  | 2594 | total_len += asdl_seq_LEN(starreds); | 
|  | 2595 | } | 
|  | 2596 |  | 
| Pablo Galindo | a5634c4 | 2020-09-16 19:42:00 +0100 | [diff] [blame] | 2597 | asdl_expr_seq *args = _Py_asdl_expr_seq_new(total_len, arena); | 
| Pablo Galindo | 4a97b15 | 2020-09-02 17:44:19 +0100 | [diff] [blame] | 2598 |  | 
|  | 2599 | Py_ssize_t i = 0; | 
|  | 2600 | for (i = 0; i < args_len; i++) { | 
|  | 2601 | asdl_seq_SET(args, i, asdl_seq_GET(a, i)); | 
|  | 2602 | } | 
|  | 2603 | for (; i < total_len; i++) { | 
|  | 2604 | asdl_seq_SET(args, i, asdl_seq_GET(starreds, i - args_len)); | 
|  | 2605 | } | 
|  | 2606 |  | 
| Victor Stinner | d27f8d2 | 2021-04-07 21:34:22 +0200 | [diff] [blame] | 2607 | return _PyAST_Call(_PyPegen_dummy_name(p), args, keywords, lineno, | 
|  | 2608 | col_offset, end_lineno, end_col_offset, arena); | 
| Pablo Galindo | 4a97b15 | 2020-09-02 17:44:19 +0100 | [diff] [blame] | 2609 | } |