1 | n/a | /* parsermodule.c |
---|
2 | n/a | * |
---|
3 | n/a | * Copyright 1995-1996 by Fred L. Drake, Jr. and Virginia Polytechnic |
---|
4 | n/a | * Institute and State University, Blacksburg, Virginia, USA. |
---|
5 | n/a | * Portions copyright 1991-1995 by Stichting Mathematisch Centrum, |
---|
6 | n/a | * Amsterdam, The Netherlands. Copying is permitted under the terms |
---|
7 | n/a | * associated with the main Python distribution, with the additional |
---|
8 | n/a | * restriction that this additional notice be included and maintained |
---|
9 | n/a | * on all distributed copies. |
---|
10 | n/a | * |
---|
11 | n/a | * This module serves to replace the original parser module written |
---|
12 | n/a | * by Guido. The functionality is not matched precisely, but the |
---|
13 | n/a | * original may be implemented on top of this. This is desirable |
---|
14 | n/a | * since the source of the text to be parsed is now divorced from |
---|
15 | n/a | * this interface. |
---|
16 | n/a | * |
---|
17 | n/a | * Unlike the prior interface, the ability to give a parse tree |
---|
18 | n/a | * produced by Python code as a tuple to the compiler is enabled by |
---|
19 | n/a | * this module. See the documentation for more details. |
---|
20 | n/a | * |
---|
21 | n/a | * I've added some annotations that help with the lint code-checking |
---|
22 | n/a | * program, but they're not complete by a long shot. The real errors |
---|
23 | n/a | * that lint detects are gone, but there are still warnings with |
---|
24 | n/a | * Py_[X]DECREF() and Py_[X]INCREF() macros. The lint annotations |
---|
25 | n/a | * look like "NOTE(...)". |
---|
26 | n/a | * |
---|
27 | n/a | * To debug parser errors like |
---|
28 | n/a | * "parser.ParserError: Expected node type 12, got 333." |
---|
29 | n/a | * decode symbol numbers using the automatically-generated files |
---|
30 | n/a | * Lib/symbol.h and Include/token.h. |
---|
31 | n/a | */ |
---|
32 | n/a | |
---|
33 | n/a | #include "Python.h" /* general Python API */ |
---|
34 | n/a | #include "Python-ast.h" /* mod_ty */ |
---|
35 | n/a | #include "graminit.h" /* symbols defined in the grammar */ |
---|
36 | n/a | #include "node.h" /* internal parser structure */ |
---|
37 | n/a | #include "errcode.h" /* error codes for PyNode_*() */ |
---|
38 | n/a | #include "token.h" /* token definitions */ |
---|
39 | n/a | #include "grammar.h" |
---|
40 | n/a | #include "parsetok.h" |
---|
41 | n/a | /* ISTERMINAL() / ISNONTERMINAL() */ |
---|
42 | n/a | #undef Yield |
---|
43 | n/a | #include "ast.h" |
---|
44 | n/a | |
---|
45 | n/a | extern grammar _PyParser_Grammar; /* From graminit.c */ |
---|
46 | n/a | |
---|
47 | n/a | #ifdef lint |
---|
48 | n/a | #include <note.h> |
---|
49 | n/a | #else |
---|
50 | n/a | #define NOTE(x) |
---|
51 | n/a | #endif |
---|
52 | n/a | |
---|
53 | n/a | /* String constants used to initialize module attributes. |
---|
54 | n/a | * |
---|
55 | n/a | */ |
---|
56 | n/a | static const char parser_copyright_string[] = |
---|
57 | n/a | "Copyright 1995-1996 by Virginia Polytechnic Institute & State\n\ |
---|
58 | n/a | University, Blacksburg, Virginia, USA, and Fred L. Drake, Jr., Reston,\n\ |
---|
59 | n/a | Virginia, USA. Portions copyright 1991-1995 by Stichting Mathematisch\n\ |
---|
60 | n/a | Centrum, Amsterdam, The Netherlands."; |
---|
61 | n/a | |
---|
62 | n/a | |
---|
63 | n/a | PyDoc_STRVAR(parser_doc_string, |
---|
64 | n/a | "This is an interface to Python's internal parser."); |
---|
65 | n/a | |
---|
66 | n/a | static const char parser_version_string[] = "0.5"; |
---|
67 | n/a | |
---|
68 | n/a | |
---|
69 | n/a | typedef PyObject* (*SeqMaker) (Py_ssize_t length); |
---|
70 | n/a | typedef int (*SeqInserter) (PyObject* sequence, |
---|
71 | n/a | Py_ssize_t index, |
---|
72 | n/a | PyObject* element); |
---|
73 | n/a | |
---|
74 | n/a | /* The function below is copyrighted by Stichting Mathematisch Centrum. The |
---|
75 | n/a | * original copyright statement is included below, and continues to apply |
---|
76 | n/a | * in full to the function immediately following. All other material is |
---|
77 | n/a | * original, copyrighted by Fred L. Drake, Jr. and Virginia Polytechnic |
---|
78 | n/a | * Institute and State University. Changes were made to comply with the |
---|
79 | n/a | * new naming conventions. Added arguments to provide support for creating |
---|
80 | n/a | * lists as well as tuples, and optionally including the line numbers. |
---|
81 | n/a | */ |
---|
82 | n/a | |
---|
83 | n/a | |
---|
84 | n/a | static PyObject* |
---|
85 | n/a | node2tuple(node *n, /* node to convert */ |
---|
86 | n/a | SeqMaker mkseq, /* create sequence */ |
---|
87 | n/a | SeqInserter addelem, /* func. to add elem. in seq. */ |
---|
88 | n/a | int lineno, /* include line numbers? */ |
---|
89 | n/a | int col_offset) /* include column offsets? */ |
---|
90 | n/a | { |
---|
91 | n/a | PyObject *result = NULL, *w; |
---|
92 | n/a | |
---|
93 | n/a | if (n == NULL) { |
---|
94 | n/a | Py_RETURN_NONE; |
---|
95 | n/a | } |
---|
96 | n/a | |
---|
97 | n/a | if (ISNONTERMINAL(TYPE(n))) { |
---|
98 | n/a | int i; |
---|
99 | n/a | |
---|
100 | n/a | result = mkseq(1 + NCH(n) + (TYPE(n) == encoding_decl)); |
---|
101 | n/a | if (result == NULL) |
---|
102 | n/a | goto error; |
---|
103 | n/a | |
---|
104 | n/a | w = PyLong_FromLong(TYPE(n)); |
---|
105 | n/a | if (w == NULL) |
---|
106 | n/a | goto error; |
---|
107 | n/a | (void) addelem(result, 0, w); |
---|
108 | n/a | |
---|
109 | n/a | for (i = 0; i < NCH(n); i++) { |
---|
110 | n/a | w = node2tuple(CHILD(n, i), mkseq, addelem, lineno, col_offset); |
---|
111 | n/a | if (w == NULL) |
---|
112 | n/a | goto error; |
---|
113 | n/a | (void) addelem(result, i+1, w); |
---|
114 | n/a | } |
---|
115 | n/a | |
---|
116 | n/a | if (TYPE(n) == encoding_decl) { |
---|
117 | n/a | w = PyUnicode_FromString(STR(n)); |
---|
118 | n/a | if (w == NULL) |
---|
119 | n/a | goto error; |
---|
120 | n/a | (void) addelem(result, i+1, w); |
---|
121 | n/a | } |
---|
122 | n/a | } |
---|
123 | n/a | else if (ISTERMINAL(TYPE(n))) { |
---|
124 | n/a | result = mkseq(2 + lineno + col_offset); |
---|
125 | n/a | if (result == NULL) |
---|
126 | n/a | goto error; |
---|
127 | n/a | |
---|
128 | n/a | w = PyLong_FromLong(TYPE(n)); |
---|
129 | n/a | if (w == NULL) |
---|
130 | n/a | goto error; |
---|
131 | n/a | (void) addelem(result, 0, w); |
---|
132 | n/a | |
---|
133 | n/a | w = PyUnicode_FromString(STR(n)); |
---|
134 | n/a | if (w == NULL) |
---|
135 | n/a | goto error; |
---|
136 | n/a | (void) addelem(result, 1, w); |
---|
137 | n/a | |
---|
138 | n/a | if (lineno == 1) { |
---|
139 | n/a | w = PyLong_FromLong(n->n_lineno); |
---|
140 | n/a | if (w == NULL) |
---|
141 | n/a | goto error; |
---|
142 | n/a | (void) addelem(result, 2, w); |
---|
143 | n/a | } |
---|
144 | n/a | |
---|
145 | n/a | if (col_offset == 1) { |
---|
146 | n/a | w = PyLong_FromLong(n->n_col_offset); |
---|
147 | n/a | if (w == NULL) |
---|
148 | n/a | goto error; |
---|
149 | n/a | (void) addelem(result, 3, w); |
---|
150 | n/a | } |
---|
151 | n/a | } |
---|
152 | n/a | else { |
---|
153 | n/a | PyErr_SetString(PyExc_SystemError, |
---|
154 | n/a | "unrecognized parse tree node type"); |
---|
155 | n/a | return ((PyObject*) NULL); |
---|
156 | n/a | } |
---|
157 | n/a | return result; |
---|
158 | n/a | |
---|
159 | n/a | error: |
---|
160 | n/a | Py_XDECREF(result); |
---|
161 | n/a | return NULL; |
---|
162 | n/a | } |
---|
163 | n/a | /* |
---|
164 | n/a | * End of material copyrighted by Stichting Mathematisch Centrum. |
---|
165 | n/a | */ |
---|
166 | n/a | |
---|
167 | n/a | |
---|
168 | n/a | |
---|
169 | n/a | /* There are two types of intermediate objects we're interested in: |
---|
170 | n/a | * 'eval' and 'exec' types. These constants can be used in the st_type |
---|
171 | n/a | * field of the object type to identify which any given object represents. |
---|
172 | n/a | * These should probably go in an external header to allow other extensions |
---|
173 | n/a | * to use them, but then, we really should be using C++ too. ;-) |
---|
174 | n/a | */ |
---|
175 | n/a | |
---|
176 | n/a | #define PyST_EXPR 1 |
---|
177 | n/a | #define PyST_SUITE 2 |
---|
178 | n/a | |
---|
179 | n/a | |
---|
180 | n/a | /* These are the internal objects and definitions required to implement the |
---|
181 | n/a | * ST type. Most of the internal names are more reminiscent of the 'old' |
---|
182 | n/a | * naming style, but the code uses the new naming convention. |
---|
183 | n/a | */ |
---|
184 | n/a | |
---|
185 | n/a | static PyObject* |
---|
186 | n/a | parser_error = 0; |
---|
187 | n/a | |
---|
188 | n/a | |
---|
189 | n/a | typedef struct { |
---|
190 | n/a | PyObject_HEAD /* standard object header */ |
---|
191 | n/a | node* st_node; /* the node* returned by the parser */ |
---|
192 | n/a | int st_type; /* EXPR or SUITE ? */ |
---|
193 | n/a | PyCompilerFlags st_flags; /* Parser and compiler flags */ |
---|
194 | n/a | } PyST_Object; |
---|
195 | n/a | |
---|
196 | n/a | |
---|
197 | n/a | static void parser_free(PyST_Object *st); |
---|
198 | n/a | static PyObject* parser_sizeof(PyST_Object *, void *); |
---|
199 | n/a | static PyObject* parser_richcompare(PyObject *left, PyObject *right, int op); |
---|
200 | n/a | static PyObject* parser_compilest(PyST_Object *, PyObject *, PyObject *); |
---|
201 | n/a | static PyObject* parser_isexpr(PyST_Object *, PyObject *, PyObject *); |
---|
202 | n/a | static PyObject* parser_issuite(PyST_Object *, PyObject *, PyObject *); |
---|
203 | n/a | static PyObject* parser_st2list(PyST_Object *, PyObject *, PyObject *); |
---|
204 | n/a | static PyObject* parser_st2tuple(PyST_Object *, PyObject *, PyObject *); |
---|
205 | n/a | |
---|
206 | n/a | #define PUBLIC_METHOD_TYPE (METH_VARARGS|METH_KEYWORDS) |
---|
207 | n/a | |
---|
208 | n/a | static PyMethodDef parser_methods[] = { |
---|
209 | n/a | {"compile", (PyCFunction)parser_compilest, PUBLIC_METHOD_TYPE, |
---|
210 | n/a | PyDoc_STR("Compile this ST object into a code object.")}, |
---|
211 | n/a | {"isexpr", (PyCFunction)parser_isexpr, PUBLIC_METHOD_TYPE, |
---|
212 | n/a | PyDoc_STR("Determines if this ST object was created from an expression.")}, |
---|
213 | n/a | {"issuite", (PyCFunction)parser_issuite, PUBLIC_METHOD_TYPE, |
---|
214 | n/a | PyDoc_STR("Determines if this ST object was created from a suite.")}, |
---|
215 | n/a | {"tolist", (PyCFunction)parser_st2list, PUBLIC_METHOD_TYPE, |
---|
216 | n/a | PyDoc_STR("Creates a list-tree representation of this ST.")}, |
---|
217 | n/a | {"totuple", (PyCFunction)parser_st2tuple, PUBLIC_METHOD_TYPE, |
---|
218 | n/a | PyDoc_STR("Creates a tuple-tree representation of this ST.")}, |
---|
219 | n/a | {"__sizeof__", (PyCFunction)parser_sizeof, METH_NOARGS, |
---|
220 | n/a | PyDoc_STR("Returns size in memory, in bytes.")}, |
---|
221 | n/a | {NULL, NULL, 0, NULL} |
---|
222 | n/a | }; |
---|
223 | n/a | |
---|
224 | n/a | static |
---|
225 | n/a | PyTypeObject PyST_Type = { |
---|
226 | n/a | PyVarObject_HEAD_INIT(NULL, 0) |
---|
227 | n/a | "parser.st", /* tp_name */ |
---|
228 | n/a | (int) sizeof(PyST_Object), /* tp_basicsize */ |
---|
229 | n/a | 0, /* tp_itemsize */ |
---|
230 | n/a | (destructor)parser_free, /* tp_dealloc */ |
---|
231 | n/a | 0, /* tp_print */ |
---|
232 | n/a | 0, /* tp_getattr */ |
---|
233 | n/a | 0, /* tp_setattr */ |
---|
234 | n/a | 0, /* tp_reserved */ |
---|
235 | n/a | 0, /* tp_repr */ |
---|
236 | n/a | 0, /* tp_as_number */ |
---|
237 | n/a | 0, /* tp_as_sequence */ |
---|
238 | n/a | 0, /* tp_as_mapping */ |
---|
239 | n/a | 0, /* tp_hash */ |
---|
240 | n/a | 0, /* tp_call */ |
---|
241 | n/a | 0, /* tp_str */ |
---|
242 | n/a | 0, /* tp_getattro */ |
---|
243 | n/a | 0, /* tp_setattro */ |
---|
244 | n/a | |
---|
245 | n/a | /* Functions to access object as input/output buffer */ |
---|
246 | n/a | 0, /* tp_as_buffer */ |
---|
247 | n/a | |
---|
248 | n/a | Py_TPFLAGS_DEFAULT, /* tp_flags */ |
---|
249 | n/a | |
---|
250 | n/a | /* __doc__ */ |
---|
251 | n/a | "Intermediate representation of a Python parse tree.", |
---|
252 | n/a | 0, /* tp_traverse */ |
---|
253 | n/a | 0, /* tp_clear */ |
---|
254 | n/a | parser_richcompare, /* tp_richcompare */ |
---|
255 | n/a | 0, /* tp_weaklistoffset */ |
---|
256 | n/a | 0, /* tp_iter */ |
---|
257 | n/a | 0, /* tp_iternext */ |
---|
258 | n/a | parser_methods, /* tp_methods */ |
---|
259 | n/a | }; /* PyST_Type */ |
---|
260 | n/a | |
---|
261 | n/a | |
---|
262 | n/a | /* PyST_Type isn't subclassable, so just check ob_type */ |
---|
263 | n/a | #define PyST_Object_Check(v) ((v)->ob_type == &PyST_Type) |
---|
264 | n/a | |
---|
265 | n/a | static int |
---|
266 | n/a | parser_compare_nodes(node *left, node *right) |
---|
267 | n/a | { |
---|
268 | n/a | int j; |
---|
269 | n/a | |
---|
270 | n/a | if (TYPE(left) < TYPE(right)) |
---|
271 | n/a | return (-1); |
---|
272 | n/a | |
---|
273 | n/a | if (TYPE(right) < TYPE(left)) |
---|
274 | n/a | return (1); |
---|
275 | n/a | |
---|
276 | n/a | if (ISTERMINAL(TYPE(left))) |
---|
277 | n/a | return (strcmp(STR(left), STR(right))); |
---|
278 | n/a | |
---|
279 | n/a | if (NCH(left) < NCH(right)) |
---|
280 | n/a | return (-1); |
---|
281 | n/a | |
---|
282 | n/a | if (NCH(right) < NCH(left)) |
---|
283 | n/a | return (1); |
---|
284 | n/a | |
---|
285 | n/a | for (j = 0; j < NCH(left); ++j) { |
---|
286 | n/a | int v = parser_compare_nodes(CHILD(left, j), CHILD(right, j)); |
---|
287 | n/a | |
---|
288 | n/a | if (v != 0) |
---|
289 | n/a | return (v); |
---|
290 | n/a | } |
---|
291 | n/a | return (0); |
---|
292 | n/a | } |
---|
293 | n/a | |
---|
294 | n/a | /* parser_richcompare(PyObject* left, PyObject* right, int op) |
---|
295 | n/a | * |
---|
296 | n/a | * Comparison function used by the Python operators ==, !=, <, >, <=, >= |
---|
297 | n/a | * This really just wraps a call to parser_compare_nodes() with some easy |
---|
298 | n/a | * checks and protection code. |
---|
299 | n/a | * |
---|
300 | n/a | */ |
---|
301 | n/a | |
---|
302 | n/a | #define TEST_COND(cond) ((cond) ? Py_True : Py_False) |
---|
303 | n/a | |
---|
304 | n/a | static PyObject * |
---|
305 | n/a | parser_richcompare(PyObject *left, PyObject *right, int op) |
---|
306 | n/a | { |
---|
307 | n/a | int result; |
---|
308 | n/a | PyObject *v; |
---|
309 | n/a | |
---|
310 | n/a | /* neither argument should be NULL, unless something's gone wrong */ |
---|
311 | n/a | if (left == NULL || right == NULL) { |
---|
312 | n/a | PyErr_BadInternalCall(); |
---|
313 | n/a | return NULL; |
---|
314 | n/a | } |
---|
315 | n/a | |
---|
316 | n/a | /* both arguments should be instances of PyST_Object */ |
---|
317 | n/a | if (!PyST_Object_Check(left) || !PyST_Object_Check(right)) { |
---|
318 | n/a | v = Py_NotImplemented; |
---|
319 | n/a | goto finished; |
---|
320 | n/a | } |
---|
321 | n/a | |
---|
322 | n/a | if (left == right) |
---|
323 | n/a | /* if arguments are identical, they're equal */ |
---|
324 | n/a | result = 0; |
---|
325 | n/a | else |
---|
326 | n/a | result = parser_compare_nodes(((PyST_Object *)left)->st_node, |
---|
327 | n/a | ((PyST_Object *)right)->st_node); |
---|
328 | n/a | |
---|
329 | n/a | /* Convert return value to a Boolean */ |
---|
330 | n/a | switch (op) { |
---|
331 | n/a | case Py_EQ: |
---|
332 | n/a | v = TEST_COND(result == 0); |
---|
333 | n/a | break; |
---|
334 | n/a | case Py_NE: |
---|
335 | n/a | v = TEST_COND(result != 0); |
---|
336 | n/a | break; |
---|
337 | n/a | case Py_LE: |
---|
338 | n/a | v = TEST_COND(result <= 0); |
---|
339 | n/a | break; |
---|
340 | n/a | case Py_GE: |
---|
341 | n/a | v = TEST_COND(result >= 0); |
---|
342 | n/a | break; |
---|
343 | n/a | case Py_LT: |
---|
344 | n/a | v = TEST_COND(result < 0); |
---|
345 | n/a | break; |
---|
346 | n/a | case Py_GT: |
---|
347 | n/a | v = TEST_COND(result > 0); |
---|
348 | n/a | break; |
---|
349 | n/a | default: |
---|
350 | n/a | PyErr_BadArgument(); |
---|
351 | n/a | return NULL; |
---|
352 | n/a | } |
---|
353 | n/a | finished: |
---|
354 | n/a | Py_INCREF(v); |
---|
355 | n/a | return v; |
---|
356 | n/a | } |
---|
357 | n/a | |
---|
358 | n/a | /* parser_newstobject(node* st) |
---|
359 | n/a | * |
---|
360 | n/a | * Allocates a new Python object representing an ST. This is simply the |
---|
361 | n/a | * 'wrapper' object that holds a node* and allows it to be passed around in |
---|
362 | n/a | * Python code. |
---|
363 | n/a | * |
---|
364 | n/a | */ |
---|
365 | n/a | static PyObject* |
---|
366 | n/a | parser_newstobject(node *st, int type) |
---|
367 | n/a | { |
---|
368 | n/a | PyST_Object* o = PyObject_New(PyST_Object, &PyST_Type); |
---|
369 | n/a | |
---|
370 | n/a | if (o != 0) { |
---|
371 | n/a | o->st_node = st; |
---|
372 | n/a | o->st_type = type; |
---|
373 | n/a | o->st_flags.cf_flags = 0; |
---|
374 | n/a | } |
---|
375 | n/a | else { |
---|
376 | n/a | PyNode_Free(st); |
---|
377 | n/a | } |
---|
378 | n/a | return ((PyObject*)o); |
---|
379 | n/a | } |
---|
380 | n/a | |
---|
381 | n/a | |
---|
382 | n/a | /* void parser_free(PyST_Object* st) |
---|
383 | n/a | * |
---|
384 | n/a | * This is called by a del statement that reduces the reference count to 0. |
---|
385 | n/a | * |
---|
386 | n/a | */ |
---|
387 | n/a | static void |
---|
388 | n/a | parser_free(PyST_Object *st) |
---|
389 | n/a | { |
---|
390 | n/a | PyNode_Free(st->st_node); |
---|
391 | n/a | PyObject_Del(st); |
---|
392 | n/a | } |
---|
393 | n/a | |
---|
394 | n/a | static PyObject * |
---|
395 | n/a | parser_sizeof(PyST_Object *st, void *unused) |
---|
396 | n/a | { |
---|
397 | n/a | Py_ssize_t res; |
---|
398 | n/a | |
---|
399 | n/a | res = _PyObject_SIZE(Py_TYPE(st)) + _PyNode_SizeOf(st->st_node); |
---|
400 | n/a | return PyLong_FromSsize_t(res); |
---|
401 | n/a | } |
---|
402 | n/a | |
---|
403 | n/a | |
---|
404 | n/a | /* parser_st2tuple(PyObject* self, PyObject* args, PyObject* kw) |
---|
405 | n/a | * |
---|
406 | n/a | * This provides conversion from a node* to a tuple object that can be |
---|
407 | n/a | * returned to the Python-level caller. The ST object is not modified. |
---|
408 | n/a | * |
---|
409 | n/a | */ |
---|
410 | n/a | static PyObject* |
---|
411 | n/a | parser_st2tuple(PyST_Object *self, PyObject *args, PyObject *kw) |
---|
412 | n/a | { |
---|
413 | n/a | int line_info = 0; |
---|
414 | n/a | int col_info = 0; |
---|
415 | n/a | PyObject *res = 0; |
---|
416 | n/a | int ok; |
---|
417 | n/a | |
---|
418 | n/a | static char *keywords[] = {"st", "line_info", "col_info", NULL}; |
---|
419 | n/a | |
---|
420 | n/a | if (self == NULL || PyModule_Check(self)) { |
---|
421 | n/a | ok = PyArg_ParseTupleAndKeywords(args, kw, "O!|pp:st2tuple", keywords, |
---|
422 | n/a | &PyST_Type, &self, &line_info, |
---|
423 | n/a | &col_info); |
---|
424 | n/a | } |
---|
425 | n/a | else |
---|
426 | n/a | ok = PyArg_ParseTupleAndKeywords(args, kw, "|pp:totuple", &keywords[1], |
---|
427 | n/a | &line_info, &col_info); |
---|
428 | n/a | if (ok != 0) { |
---|
429 | n/a | /* |
---|
430 | n/a | * Convert ST into a tuple representation. Use Guido's function, |
---|
431 | n/a | * since it's known to work already. |
---|
432 | n/a | */ |
---|
433 | n/a | res = node2tuple(((PyST_Object*)self)->st_node, |
---|
434 | n/a | PyTuple_New, PyTuple_SetItem, line_info, col_info); |
---|
435 | n/a | } |
---|
436 | n/a | return (res); |
---|
437 | n/a | } |
---|
438 | n/a | |
---|
439 | n/a | |
---|
440 | n/a | /* parser_st2list(PyObject* self, PyObject* args, PyObject* kw) |
---|
441 | n/a | * |
---|
442 | n/a | * This provides conversion from a node* to a list object that can be |
---|
443 | n/a | * returned to the Python-level caller. The ST object is not modified. |
---|
444 | n/a | * |
---|
445 | n/a | */ |
---|
446 | n/a | static PyObject* |
---|
447 | n/a | parser_st2list(PyST_Object *self, PyObject *args, PyObject *kw) |
---|
448 | n/a | { |
---|
449 | n/a | int line_info = 0; |
---|
450 | n/a | int col_info = 0; |
---|
451 | n/a | PyObject *res = 0; |
---|
452 | n/a | int ok; |
---|
453 | n/a | |
---|
454 | n/a | static char *keywords[] = {"st", "line_info", "col_info", NULL}; |
---|
455 | n/a | |
---|
456 | n/a | if (self == NULL || PyModule_Check(self)) |
---|
457 | n/a | ok = PyArg_ParseTupleAndKeywords(args, kw, "O!|pp:st2list", keywords, |
---|
458 | n/a | &PyST_Type, &self, &line_info, |
---|
459 | n/a | &col_info); |
---|
460 | n/a | else |
---|
461 | n/a | ok = PyArg_ParseTupleAndKeywords(args, kw, "|pp:tolist", &keywords[1], |
---|
462 | n/a | &line_info, &col_info); |
---|
463 | n/a | if (ok) { |
---|
464 | n/a | /* |
---|
465 | n/a | * Convert ST into a tuple representation. Use Guido's function, |
---|
466 | n/a | * since it's known to work already. |
---|
467 | n/a | */ |
---|
468 | n/a | res = node2tuple(self->st_node, |
---|
469 | n/a | PyList_New, PyList_SetItem, line_info, col_info); |
---|
470 | n/a | } |
---|
471 | n/a | return (res); |
---|
472 | n/a | } |
---|
473 | n/a | |
---|
474 | n/a | |
---|
475 | n/a | /* parser_compilest(PyObject* self, PyObject* args) |
---|
476 | n/a | * |
---|
477 | n/a | * This function creates code objects from the parse tree represented by |
---|
478 | n/a | * the passed-in data object. An optional file name is passed in as well. |
---|
479 | n/a | * |
---|
480 | n/a | */ |
---|
481 | n/a | static PyObject* |
---|
482 | n/a | parser_compilest(PyST_Object *self, PyObject *args, PyObject *kw) |
---|
483 | n/a | { |
---|
484 | n/a | PyObject* res = NULL; |
---|
485 | n/a | PyArena* arena = NULL; |
---|
486 | n/a | mod_ty mod; |
---|
487 | n/a | PyObject* filename = NULL; |
---|
488 | n/a | int ok; |
---|
489 | n/a | |
---|
490 | n/a | static char *keywords[] = {"st", "filename", NULL}; |
---|
491 | n/a | |
---|
492 | n/a | if (self == NULL || PyModule_Check(self)) |
---|
493 | n/a | ok = PyArg_ParseTupleAndKeywords(args, kw, "O!|O&:compilest", keywords, |
---|
494 | n/a | &PyST_Type, &self, |
---|
495 | n/a | PyUnicode_FSDecoder, &filename); |
---|
496 | n/a | else |
---|
497 | n/a | ok = PyArg_ParseTupleAndKeywords(args, kw, "|O&:compile", &keywords[1], |
---|
498 | n/a | PyUnicode_FSDecoder, &filename); |
---|
499 | n/a | if (!ok) |
---|
500 | n/a | goto error; |
---|
501 | n/a | |
---|
502 | n/a | if (filename == NULL) { |
---|
503 | n/a | filename = PyUnicode_FromString("<syntax-tree>"); |
---|
504 | n/a | if (filename == NULL) |
---|
505 | n/a | goto error; |
---|
506 | n/a | } |
---|
507 | n/a | |
---|
508 | n/a | arena = PyArena_New(); |
---|
509 | n/a | if (!arena) |
---|
510 | n/a | goto error; |
---|
511 | n/a | |
---|
512 | n/a | mod = PyAST_FromNodeObject(self->st_node, &self->st_flags, |
---|
513 | n/a | filename, arena); |
---|
514 | n/a | if (!mod) |
---|
515 | n/a | goto error; |
---|
516 | n/a | |
---|
517 | n/a | res = (PyObject *)PyAST_CompileObject(mod, filename, |
---|
518 | n/a | &self->st_flags, -1, arena); |
---|
519 | n/a | error: |
---|
520 | n/a | Py_XDECREF(filename); |
---|
521 | n/a | if (arena != NULL) |
---|
522 | n/a | PyArena_Free(arena); |
---|
523 | n/a | return res; |
---|
524 | n/a | } |
---|
525 | n/a | |
---|
526 | n/a | |
---|
527 | n/a | /* PyObject* parser_isexpr(PyObject* self, PyObject* args) |
---|
528 | n/a | * PyObject* parser_issuite(PyObject* self, PyObject* args) |
---|
529 | n/a | * |
---|
530 | n/a | * Checks the passed-in ST object to determine if it is an expression or |
---|
531 | n/a | * a statement suite, respectively. The return is a Python truth value. |
---|
532 | n/a | * |
---|
533 | n/a | */ |
---|
534 | n/a | static PyObject* |
---|
535 | n/a | parser_isexpr(PyST_Object *self, PyObject *args, PyObject *kw) |
---|
536 | n/a | { |
---|
537 | n/a | PyObject* res = 0; |
---|
538 | n/a | int ok; |
---|
539 | n/a | |
---|
540 | n/a | static char *keywords[] = {"st", NULL}; |
---|
541 | n/a | |
---|
542 | n/a | if (self == NULL || PyModule_Check(self)) |
---|
543 | n/a | ok = PyArg_ParseTupleAndKeywords(args, kw, "O!:isexpr", keywords, |
---|
544 | n/a | &PyST_Type, &self); |
---|
545 | n/a | else |
---|
546 | n/a | ok = PyArg_ParseTupleAndKeywords(args, kw, ":isexpr", &keywords[1]); |
---|
547 | n/a | |
---|
548 | n/a | if (ok) { |
---|
549 | n/a | /* Check to see if the ST represents an expression or not. */ |
---|
550 | n/a | res = (self->st_type == PyST_EXPR) ? Py_True : Py_False; |
---|
551 | n/a | Py_INCREF(res); |
---|
552 | n/a | } |
---|
553 | n/a | return (res); |
---|
554 | n/a | } |
---|
555 | n/a | |
---|
556 | n/a | |
---|
557 | n/a | static PyObject* |
---|
558 | n/a | parser_issuite(PyST_Object *self, PyObject *args, PyObject *kw) |
---|
559 | n/a | { |
---|
560 | n/a | PyObject* res = 0; |
---|
561 | n/a | int ok; |
---|
562 | n/a | |
---|
563 | n/a | static char *keywords[] = {"st", NULL}; |
---|
564 | n/a | |
---|
565 | n/a | if (self == NULL || PyModule_Check(self)) |
---|
566 | n/a | ok = PyArg_ParseTupleAndKeywords(args, kw, "O!:issuite", keywords, |
---|
567 | n/a | &PyST_Type, &self); |
---|
568 | n/a | else |
---|
569 | n/a | ok = PyArg_ParseTupleAndKeywords(args, kw, ":issuite", &keywords[1]); |
---|
570 | n/a | |
---|
571 | n/a | if (ok) { |
---|
572 | n/a | /* Check to see if the ST represents an expression or not. */ |
---|
573 | n/a | res = (self->st_type == PyST_EXPR) ? Py_False : Py_True; |
---|
574 | n/a | Py_INCREF(res); |
---|
575 | n/a | } |
---|
576 | n/a | return (res); |
---|
577 | n/a | } |
---|
578 | n/a | |
---|
579 | n/a | |
---|
580 | n/a | /* err_string(const char* message) |
---|
581 | n/a | * |
---|
582 | n/a | * Sets the error string for an exception of type ParserError. |
---|
583 | n/a | * |
---|
584 | n/a | */ |
---|
585 | n/a | static void |
---|
586 | n/a | err_string(const char *message) |
---|
587 | n/a | { |
---|
588 | n/a | PyErr_SetString(parser_error, message); |
---|
589 | n/a | } |
---|
590 | n/a | |
---|
591 | n/a | |
---|
592 | n/a | /* PyObject* parser_do_parse(PyObject* args, int type) |
---|
593 | n/a | * |
---|
594 | n/a | * Internal function to actually execute the parse and return the result if |
---|
595 | n/a | * successful or set an exception if not. |
---|
596 | n/a | * |
---|
597 | n/a | */ |
---|
598 | n/a | static PyObject* |
---|
599 | n/a | parser_do_parse(PyObject *args, PyObject *kw, const char *argspec, int type) |
---|
600 | n/a | { |
---|
601 | n/a | char* string = 0; |
---|
602 | n/a | PyObject* res = 0; |
---|
603 | n/a | int flags = 0; |
---|
604 | n/a | perrdetail err; |
---|
605 | n/a | |
---|
606 | n/a | static char *keywords[] = {"source", NULL}; |
---|
607 | n/a | |
---|
608 | n/a | if (PyArg_ParseTupleAndKeywords(args, kw, argspec, keywords, &string)) { |
---|
609 | n/a | node* n = PyParser_ParseStringFlagsFilenameEx(string, NULL, |
---|
610 | n/a | &_PyParser_Grammar, |
---|
611 | n/a | (type == PyST_EXPR) |
---|
612 | n/a | ? eval_input : file_input, |
---|
613 | n/a | &err, &flags); |
---|
614 | n/a | |
---|
615 | n/a | if (n) { |
---|
616 | n/a | res = parser_newstobject(n, type); |
---|
617 | n/a | if (res) |
---|
618 | n/a | ((PyST_Object *)res)->st_flags.cf_flags = flags & PyCF_MASK; |
---|
619 | n/a | } |
---|
620 | n/a | else { |
---|
621 | n/a | PyParser_SetError(&err); |
---|
622 | n/a | } |
---|
623 | n/a | PyParser_ClearError(&err); |
---|
624 | n/a | } |
---|
625 | n/a | return (res); |
---|
626 | n/a | } |
---|
627 | n/a | |
---|
628 | n/a | |
---|
629 | n/a | /* PyObject* parser_expr(PyObject* self, PyObject* args) |
---|
630 | n/a | * PyObject* parser_suite(PyObject* self, PyObject* args) |
---|
631 | n/a | * |
---|
632 | n/a | * External interfaces to the parser itself. Which is called determines if |
---|
633 | n/a | * the parser attempts to recognize an expression ('eval' form) or statement |
---|
634 | n/a | * suite ('exec' form). The real work is done by parser_do_parse() above. |
---|
635 | n/a | * |
---|
636 | n/a | */ |
---|
637 | n/a | static PyObject* |
---|
638 | n/a | parser_expr(PyST_Object *self, PyObject *args, PyObject *kw) |
---|
639 | n/a | { |
---|
640 | n/a | NOTE(ARGUNUSED(self)) |
---|
641 | n/a | return (parser_do_parse(args, kw, "s:expr", PyST_EXPR)); |
---|
642 | n/a | } |
---|
643 | n/a | |
---|
644 | n/a | |
---|
645 | n/a | static PyObject* |
---|
646 | n/a | parser_suite(PyST_Object *self, PyObject *args, PyObject *kw) |
---|
647 | n/a | { |
---|
648 | n/a | NOTE(ARGUNUSED(self)) |
---|
649 | n/a | return (parser_do_parse(args, kw, "s:suite", PyST_SUITE)); |
---|
650 | n/a | } |
---|
651 | n/a | |
---|
652 | n/a | |
---|
653 | n/a | |
---|
654 | n/a | /* This is the messy part of the code. Conversion from a tuple to an ST |
---|
655 | n/a | * object requires that the input tuple be valid without having to rely on |
---|
656 | n/a | * catching an exception from the compiler. This is done to allow the |
---|
657 | n/a | * compiler itself to remain fast, since most of its input will come from |
---|
658 | n/a | * the parser directly, and therefore be known to be syntactically correct. |
---|
659 | n/a | * This validation is done to ensure that we don't core dump the compile |
---|
660 | n/a | * phase, returning an exception instead. |
---|
661 | n/a | * |
---|
662 | n/a | * Two aspects can be broken out in this code: creating a node tree from |
---|
663 | n/a | * the tuple passed in, and verifying that it is indeed valid. It may be |
---|
664 | n/a | * advantageous to expand the number of ST types to include funcdefs and |
---|
665 | n/a | * lambdadefs to take advantage of the optimizer, recognizing those STs |
---|
666 | n/a | * here. They are not necessary, and not quite as useful in a raw form. |
---|
667 | n/a | * For now, let's get expressions and suites working reliably. |
---|
668 | n/a | */ |
---|
669 | n/a | |
---|
670 | n/a | |
---|
671 | n/a | static node* build_node_tree(PyObject *tuple); |
---|
672 | n/a | |
---|
673 | n/a | static int |
---|
674 | n/a | validate_node(node *tree) |
---|
675 | n/a | { |
---|
676 | n/a | int type = TYPE(tree); |
---|
677 | n/a | int nch = NCH(tree); |
---|
678 | n/a | dfa *nt_dfa; |
---|
679 | n/a | state *dfa_state; |
---|
680 | n/a | int pos, arc; |
---|
681 | n/a | |
---|
682 | n/a | assert(ISNONTERMINAL(type)); |
---|
683 | n/a | type -= NT_OFFSET; |
---|
684 | n/a | if (type >= _PyParser_Grammar.g_ndfas) { |
---|
685 | n/a | PyErr_Format(parser_error, "Unrecognized node type %d.", TYPE(tree)); |
---|
686 | n/a | return 0; |
---|
687 | n/a | } |
---|
688 | n/a | nt_dfa = &_PyParser_Grammar.g_dfa[type]; |
---|
689 | n/a | REQ(tree, nt_dfa->d_type); |
---|
690 | n/a | |
---|
691 | n/a | /* Run the DFA for this nonterminal. */ |
---|
692 | n/a | dfa_state = &nt_dfa->d_state[nt_dfa->d_initial]; |
---|
693 | n/a | for (pos = 0; pos < nch; ++pos) { |
---|
694 | n/a | node *ch = CHILD(tree, pos); |
---|
695 | n/a | int ch_type = TYPE(ch); |
---|
696 | n/a | for (arc = 0; arc < dfa_state->s_narcs; ++arc) { |
---|
697 | n/a | short a_label = dfa_state->s_arc[arc].a_lbl; |
---|
698 | n/a | assert(a_label < _PyParser_Grammar.g_ll.ll_nlabels); |
---|
699 | n/a | if (_PyParser_Grammar.g_ll.ll_label[a_label].lb_type == ch_type) { |
---|
700 | n/a | /* The child is acceptable; if non-terminal, validate it recursively. */ |
---|
701 | n/a | if (ISNONTERMINAL(ch_type) && !validate_node(ch)) |
---|
702 | n/a | return 0; |
---|
703 | n/a | |
---|
704 | n/a | /* Update the state, and move on to the next child. */ |
---|
705 | n/a | dfa_state = &nt_dfa->d_state[dfa_state->s_arc[arc].a_arrow]; |
---|
706 | n/a | goto arc_found; |
---|
707 | n/a | } |
---|
708 | n/a | } |
---|
709 | n/a | /* What would this state have accepted? */ |
---|
710 | n/a | { |
---|
711 | n/a | short a_label = dfa_state->s_arc->a_lbl; |
---|
712 | n/a | int next_type; |
---|
713 | n/a | if (!a_label) /* Wouldn't accept any more children */ |
---|
714 | n/a | goto illegal_num_children; |
---|
715 | n/a | |
---|
716 | n/a | next_type = _PyParser_Grammar.g_ll.ll_label[a_label].lb_type; |
---|
717 | n/a | if (ISNONTERMINAL(next_type)) |
---|
718 | n/a | PyErr_Format(parser_error, "Expected node type %d, got %d.", |
---|
719 | n/a | next_type, ch_type); |
---|
720 | n/a | else |
---|
721 | n/a | PyErr_Format(parser_error, "Illegal terminal: expected %s.", |
---|
722 | n/a | _PyParser_TokenNames[next_type]); |
---|
723 | n/a | return 0; |
---|
724 | n/a | } |
---|
725 | n/a | |
---|
726 | n/a | arc_found: |
---|
727 | n/a | continue; |
---|
728 | n/a | } |
---|
729 | n/a | /* Are we in a final state? If so, return 1 for successful validation. */ |
---|
730 | n/a | for (arc = 0; arc < dfa_state->s_narcs; ++arc) { |
---|
731 | n/a | if (!dfa_state->s_arc[arc].a_lbl) { |
---|
732 | n/a | return 1; |
---|
733 | n/a | } |
---|
734 | n/a | } |
---|
735 | n/a | |
---|
736 | n/a | illegal_num_children: |
---|
737 | n/a | PyErr_Format(parser_error, |
---|
738 | n/a | "Illegal number of children for %s node.", nt_dfa->d_name); |
---|
739 | n/a | return 0; |
---|
740 | n/a | } |
---|
741 | n/a | |
---|
742 | n/a | /* PyObject* parser_tuple2st(PyObject* self, PyObject* args) |
---|
743 | n/a | * |
---|
744 | n/a | * This is the public function, called from the Python code. It receives a |
---|
745 | n/a | * single tuple object from the caller, and creates an ST object if the |
---|
746 | n/a | * tuple can be validated. It does this by checking the first code of the |
---|
747 | n/a | * tuple, and, if acceptable, builds the internal representation. If this |
---|
748 | n/a | * step succeeds, the internal representation is validated as fully as |
---|
749 | n/a | * possible with the recursive validate_node() routine defined above. |
---|
750 | n/a | * |
---|
751 | n/a | * This function must be changed if support is to be added for PyST_FRAGMENT |
---|
752 | n/a | * ST objects. |
---|
753 | n/a | * |
---|
754 | n/a | */ |
---|
755 | n/a | static PyObject* |
---|
756 | n/a | parser_tuple2st(PyST_Object *self, PyObject *args, PyObject *kw) |
---|
757 | n/a | { |
---|
758 | n/a | NOTE(ARGUNUSED(self)) |
---|
759 | n/a | PyObject *st = 0; |
---|
760 | n/a | PyObject *tuple; |
---|
761 | n/a | node *tree; |
---|
762 | n/a | |
---|
763 | n/a | static char *keywords[] = {"sequence", NULL}; |
---|
764 | n/a | |
---|
765 | n/a | if (!PyArg_ParseTupleAndKeywords(args, kw, "O:sequence2st", keywords, |
---|
766 | n/a | &tuple)) |
---|
767 | n/a | return (0); |
---|
768 | n/a | if (!PySequence_Check(tuple)) { |
---|
769 | n/a | PyErr_SetString(PyExc_ValueError, |
---|
770 | n/a | "sequence2st() requires a single sequence argument"); |
---|
771 | n/a | return (0); |
---|
772 | n/a | } |
---|
773 | n/a | /* |
---|
774 | n/a | * Convert the tree to the internal form before checking it. |
---|
775 | n/a | */ |
---|
776 | n/a | tree = build_node_tree(tuple); |
---|
777 | n/a | if (tree != 0) { |
---|
778 | n/a | node *validation_root = tree; |
---|
779 | n/a | int tree_type = 0; |
---|
780 | n/a | switch (TYPE(tree)) { |
---|
781 | n/a | case eval_input: |
---|
782 | n/a | /* Might be an eval form. */ |
---|
783 | n/a | tree_type = PyST_EXPR; |
---|
784 | n/a | break; |
---|
785 | n/a | case encoding_decl: |
---|
786 | n/a | /* This looks like an encoding_decl so far. */ |
---|
787 | n/a | if (NCH(tree) != 1) |
---|
788 | n/a | err_string("Error Parsing encoding_decl"); |
---|
789 | n/a | validation_root = CHILD(tree, 0); |
---|
790 | n/a | /* Fall through */ |
---|
791 | n/a | case file_input: |
---|
792 | n/a | /* This looks like an exec form so far. */ |
---|
793 | n/a | |
---|
794 | n/a | tree_type = PyST_SUITE; |
---|
795 | n/a | break; |
---|
796 | n/a | default: |
---|
797 | n/a | /* This is a fragment, at best. */ |
---|
798 | n/a | PyNode_Free(tree); |
---|
799 | n/a | err_string("parse tree does not use a valid start symbol"); |
---|
800 | n/a | return (0); |
---|
801 | n/a | } |
---|
802 | n/a | |
---|
803 | n/a | if (validate_node(validation_root)) |
---|
804 | n/a | st = parser_newstobject(tree, tree_type); |
---|
805 | n/a | else |
---|
806 | n/a | PyNode_Free(tree); |
---|
807 | n/a | } |
---|
808 | n/a | /* Make sure we raise an exception on all errors. We should never |
---|
809 | n/a | * get this, but we'd do well to be sure something is done. |
---|
810 | n/a | */ |
---|
811 | n/a | if (st == NULL && !PyErr_Occurred()) |
---|
812 | n/a | err_string("unspecified ST error occurred"); |
---|
813 | n/a | |
---|
814 | n/a | return st; |
---|
815 | n/a | } |
---|
816 | n/a | |
---|
817 | n/a | |
---|
818 | n/a | /* node* build_node_children() |
---|
819 | n/a | * |
---|
820 | n/a | * Iterate across the children of the current non-terminal node and build |
---|
821 | n/a | * their structures. If successful, return the root of this portion of |
---|
822 | n/a | * the tree, otherwise, 0. Any required exception will be specified already, |
---|
823 | n/a | * and no memory will have been deallocated. |
---|
824 | n/a | * |
---|
825 | n/a | */ |
---|
826 | n/a | static node* |
---|
827 | n/a | build_node_children(PyObject *tuple, node *root, int *line_num) |
---|
828 | n/a | { |
---|
829 | n/a | Py_ssize_t len = PyObject_Size(tuple); |
---|
830 | n/a | Py_ssize_t i; |
---|
831 | n/a | int err; |
---|
832 | n/a | |
---|
833 | n/a | for (i = 1; i < len; ++i) { |
---|
834 | n/a | /* elem must always be a sequence, however simple */ |
---|
835 | n/a | PyObject* elem = PySequence_GetItem(tuple, i); |
---|
836 | n/a | int ok = elem != NULL; |
---|
837 | n/a | int type = 0; |
---|
838 | n/a | char *strn = 0; |
---|
839 | n/a | |
---|
840 | n/a | if (ok) |
---|
841 | n/a | ok = PySequence_Check(elem); |
---|
842 | n/a | if (ok) { |
---|
843 | n/a | PyObject *temp = PySequence_GetItem(elem, 0); |
---|
844 | n/a | if (temp == NULL) |
---|
845 | n/a | ok = 0; |
---|
846 | n/a | else { |
---|
847 | n/a | ok = PyLong_Check(temp); |
---|
848 | n/a | if (ok) { |
---|
849 | n/a | type = _PyLong_AsInt(temp); |
---|
850 | n/a | if (type == -1 && PyErr_Occurred()) { |
---|
851 | n/a | Py_DECREF(temp); |
---|
852 | n/a | Py_DECREF(elem); |
---|
853 | n/a | return 0; |
---|
854 | n/a | } |
---|
855 | n/a | } |
---|
856 | n/a | Py_DECREF(temp); |
---|
857 | n/a | } |
---|
858 | n/a | } |
---|
859 | n/a | if (!ok) { |
---|
860 | n/a | PyObject *err = Py_BuildValue("Os", elem, |
---|
861 | n/a | "Illegal node construct."); |
---|
862 | n/a | PyErr_SetObject(parser_error, err); |
---|
863 | n/a | Py_XDECREF(err); |
---|
864 | n/a | Py_XDECREF(elem); |
---|
865 | n/a | return (0); |
---|
866 | n/a | } |
---|
867 | n/a | if (ISTERMINAL(type)) { |
---|
868 | n/a | Py_ssize_t len = PyObject_Size(elem); |
---|
869 | n/a | PyObject *temp; |
---|
870 | n/a | const char *temp_str; |
---|
871 | n/a | |
---|
872 | n/a | if ((len != 2) && (len != 3)) { |
---|
873 | n/a | err_string("terminal nodes must have 2 or 3 entries"); |
---|
874 | n/a | return 0; |
---|
875 | n/a | } |
---|
876 | n/a | temp = PySequence_GetItem(elem, 1); |
---|
877 | n/a | if (temp == NULL) |
---|
878 | n/a | return 0; |
---|
879 | n/a | if (!PyUnicode_Check(temp)) { |
---|
880 | n/a | PyErr_Format(parser_error, |
---|
881 | n/a | "second item in terminal node must be a string," |
---|
882 | n/a | " found %s", |
---|
883 | n/a | Py_TYPE(temp)->tp_name); |
---|
884 | n/a | Py_DECREF(temp); |
---|
885 | n/a | Py_DECREF(elem); |
---|
886 | n/a | return 0; |
---|
887 | n/a | } |
---|
888 | n/a | if (len == 3) { |
---|
889 | n/a | PyObject *o = PySequence_GetItem(elem, 2); |
---|
890 | n/a | if (o != NULL) { |
---|
891 | n/a | if (PyLong_Check(o)) { |
---|
892 | n/a | int num = _PyLong_AsInt(o); |
---|
893 | n/a | if (num == -1 && PyErr_Occurred()) { |
---|
894 | n/a | Py_DECREF(o); |
---|
895 | n/a | Py_DECREF(temp); |
---|
896 | n/a | Py_DECREF(elem); |
---|
897 | n/a | return 0; |
---|
898 | n/a | } |
---|
899 | n/a | *line_num = num; |
---|
900 | n/a | } |
---|
901 | n/a | else { |
---|
902 | n/a | PyErr_Format(parser_error, |
---|
903 | n/a | "third item in terminal node must be an" |
---|
904 | n/a | " integer, found %s", |
---|
905 | n/a | Py_TYPE(temp)->tp_name); |
---|
906 | n/a | Py_DECREF(o); |
---|
907 | n/a | Py_DECREF(temp); |
---|
908 | n/a | Py_DECREF(elem); |
---|
909 | n/a | return 0; |
---|
910 | n/a | } |
---|
911 | n/a | Py_DECREF(o); |
---|
912 | n/a | } |
---|
913 | n/a | } |
---|
914 | n/a | temp_str = PyUnicode_AsUTF8AndSize(temp, &len); |
---|
915 | n/a | if (temp_str == NULL) { |
---|
916 | n/a | Py_DECREF(temp); |
---|
917 | n/a | Py_XDECREF(elem); |
---|
918 | n/a | return 0; |
---|
919 | n/a | } |
---|
920 | n/a | strn = (char *)PyObject_MALLOC(len + 1); |
---|
921 | n/a | if (strn == NULL) { |
---|
922 | n/a | Py_DECREF(temp); |
---|
923 | n/a | Py_XDECREF(elem); |
---|
924 | n/a | PyErr_NoMemory(); |
---|
925 | n/a | return 0; |
---|
926 | n/a | } |
---|
927 | n/a | (void) memcpy(strn, temp_str, len + 1); |
---|
928 | n/a | Py_DECREF(temp); |
---|
929 | n/a | } |
---|
930 | n/a | else if (!ISNONTERMINAL(type)) { |
---|
931 | n/a | /* |
---|
932 | n/a | * It has to be one or the other; this is an error. |
---|
933 | n/a | * Raise an exception. |
---|
934 | n/a | */ |
---|
935 | n/a | PyObject *err = Py_BuildValue("os", elem, "unknown node type."); |
---|
936 | n/a | PyErr_SetObject(parser_error, err); |
---|
937 | n/a | Py_XDECREF(err); |
---|
938 | n/a | Py_XDECREF(elem); |
---|
939 | n/a | return (0); |
---|
940 | n/a | } |
---|
941 | n/a | err = PyNode_AddChild(root, type, strn, *line_num, 0); |
---|
942 | n/a | if (err == E_NOMEM) { |
---|
943 | n/a | Py_XDECREF(elem); |
---|
944 | n/a | PyObject_FREE(strn); |
---|
945 | n/a | return (node *) PyErr_NoMemory(); |
---|
946 | n/a | } |
---|
947 | n/a | if (err == E_OVERFLOW) { |
---|
948 | n/a | Py_XDECREF(elem); |
---|
949 | n/a | PyObject_FREE(strn); |
---|
950 | n/a | PyErr_SetString(PyExc_ValueError, |
---|
951 | n/a | "unsupported number of child nodes"); |
---|
952 | n/a | return NULL; |
---|
953 | n/a | } |
---|
954 | n/a | |
---|
955 | n/a | if (ISNONTERMINAL(type)) { |
---|
956 | n/a | node* new_child = CHILD(root, i - 1); |
---|
957 | n/a | |
---|
958 | n/a | if (new_child != build_node_children(elem, new_child, line_num)) { |
---|
959 | n/a | Py_XDECREF(elem); |
---|
960 | n/a | return (0); |
---|
961 | n/a | } |
---|
962 | n/a | } |
---|
963 | n/a | else if (type == NEWLINE) { /* It's true: we increment the */ |
---|
964 | n/a | ++(*line_num); /* line number *after* the newline! */ |
---|
965 | n/a | } |
---|
966 | n/a | Py_XDECREF(elem); |
---|
967 | n/a | } |
---|
968 | n/a | return root; |
---|
969 | n/a | } |
---|
970 | n/a | |
---|
971 | n/a | |
---|
972 | n/a | static node* |
---|
973 | n/a | build_node_tree(PyObject *tuple) |
---|
974 | n/a | { |
---|
975 | n/a | node* res = 0; |
---|
976 | n/a | PyObject *temp = PySequence_GetItem(tuple, 0); |
---|
977 | n/a | long num = -1; |
---|
978 | n/a | |
---|
979 | n/a | if (temp != NULL) |
---|
980 | n/a | num = PyLong_AsLong(temp); |
---|
981 | n/a | Py_XDECREF(temp); |
---|
982 | n/a | if (ISTERMINAL(num)) { |
---|
983 | n/a | /* |
---|
984 | n/a | * The tuple is simple, but it doesn't start with a start symbol. |
---|
985 | n/a | * Raise an exception now and be done with it. |
---|
986 | n/a | */ |
---|
987 | n/a | tuple = Py_BuildValue("Os", tuple, |
---|
988 | n/a | "Illegal syntax-tree; cannot start with terminal symbol."); |
---|
989 | n/a | PyErr_SetObject(parser_error, tuple); |
---|
990 | n/a | Py_XDECREF(tuple); |
---|
991 | n/a | } |
---|
992 | n/a | else if (ISNONTERMINAL(num)) { |
---|
993 | n/a | /* |
---|
994 | n/a | * Not efficient, but that can be handled later. |
---|
995 | n/a | */ |
---|
996 | n/a | int line_num = 0; |
---|
997 | n/a | PyObject *encoding = NULL; |
---|
998 | n/a | |
---|
999 | n/a | if (num == encoding_decl) { |
---|
1000 | n/a | encoding = PySequence_GetItem(tuple, 2); |
---|
1001 | n/a | /* tuple isn't borrowed anymore here, need to DECREF */ |
---|
1002 | n/a | tuple = PySequence_GetSlice(tuple, 0, 2); |
---|
1003 | n/a | if (tuple == NULL) |
---|
1004 | n/a | return NULL; |
---|
1005 | n/a | } |
---|
1006 | n/a | res = PyNode_New(num); |
---|
1007 | n/a | if (res != NULL) { |
---|
1008 | n/a | if (res != build_node_children(tuple, res, &line_num)) { |
---|
1009 | n/a | PyNode_Free(res); |
---|
1010 | n/a | res = NULL; |
---|
1011 | n/a | } |
---|
1012 | n/a | if (res && encoding) { |
---|
1013 | n/a | Py_ssize_t len; |
---|
1014 | n/a | const char *temp; |
---|
1015 | n/a | temp = PyUnicode_AsUTF8AndSize(encoding, &len); |
---|
1016 | n/a | if (temp == NULL) { |
---|
1017 | n/a | Py_DECREF(res); |
---|
1018 | n/a | Py_DECREF(encoding); |
---|
1019 | n/a | Py_DECREF(tuple); |
---|
1020 | n/a | return NULL; |
---|
1021 | n/a | } |
---|
1022 | n/a | res->n_str = (char *)PyObject_MALLOC(len + 1); |
---|
1023 | n/a | if (res->n_str == NULL) { |
---|
1024 | n/a | Py_DECREF(res); |
---|
1025 | n/a | Py_DECREF(encoding); |
---|
1026 | n/a | Py_DECREF(tuple); |
---|
1027 | n/a | PyErr_NoMemory(); |
---|
1028 | n/a | return NULL; |
---|
1029 | n/a | } |
---|
1030 | n/a | (void) memcpy(res->n_str, temp, len + 1); |
---|
1031 | n/a | Py_DECREF(encoding); |
---|
1032 | n/a | Py_DECREF(tuple); |
---|
1033 | n/a | } |
---|
1034 | n/a | } |
---|
1035 | n/a | } |
---|
1036 | n/a | else { |
---|
1037 | n/a | /* The tuple is illegal -- if the number is neither TERMINAL nor |
---|
1038 | n/a | * NONTERMINAL, we can't use it. Not sure the implementation |
---|
1039 | n/a | * allows this condition, but the API doesn't preclude it. |
---|
1040 | n/a | */ |
---|
1041 | n/a | PyObject *err = Py_BuildValue("os", tuple, |
---|
1042 | n/a | "Illegal component tuple."); |
---|
1043 | n/a | PyErr_SetObject(parser_error, err); |
---|
1044 | n/a | Py_XDECREF(err); |
---|
1045 | n/a | } |
---|
1046 | n/a | |
---|
1047 | n/a | return (res); |
---|
1048 | n/a | } |
---|
1049 | n/a | |
---|
1050 | n/a | |
---|
1051 | n/a | static PyObject* |
---|
1052 | n/a | pickle_constructor = NULL; |
---|
1053 | n/a | |
---|
1054 | n/a | |
---|
1055 | n/a | static PyObject* |
---|
1056 | n/a | parser__pickler(PyObject *self, PyObject *args) |
---|
1057 | n/a | { |
---|
1058 | n/a | NOTE(ARGUNUSED(self)) |
---|
1059 | n/a | PyObject *result = NULL; |
---|
1060 | n/a | PyObject *st = NULL; |
---|
1061 | n/a | PyObject *empty_dict = NULL; |
---|
1062 | n/a | |
---|
1063 | n/a | if (PyArg_ParseTuple(args, "O!:_pickler", &PyST_Type, &st)) { |
---|
1064 | n/a | PyObject *newargs; |
---|
1065 | n/a | PyObject *tuple; |
---|
1066 | n/a | |
---|
1067 | n/a | if ((empty_dict = PyDict_New()) == NULL) |
---|
1068 | n/a | goto finally; |
---|
1069 | n/a | if ((newargs = Py_BuildValue("Oi", st, 1)) == NULL) |
---|
1070 | n/a | goto finally; |
---|
1071 | n/a | tuple = parser_st2tuple((PyST_Object*)NULL, newargs, empty_dict); |
---|
1072 | n/a | if (tuple != NULL) { |
---|
1073 | n/a | result = Py_BuildValue("O(O)", pickle_constructor, tuple); |
---|
1074 | n/a | Py_DECREF(tuple); |
---|
1075 | n/a | } |
---|
1076 | n/a | Py_DECREF(empty_dict); |
---|
1077 | n/a | Py_DECREF(newargs); |
---|
1078 | n/a | } |
---|
1079 | n/a | finally: |
---|
1080 | n/a | Py_XDECREF(empty_dict); |
---|
1081 | n/a | |
---|
1082 | n/a | return (result); |
---|
1083 | n/a | } |
---|
1084 | n/a | |
---|
1085 | n/a | |
---|
1086 | n/a | /* Functions exported by this module. Most of this should probably |
---|
1087 | n/a | * be converted into an ST object with methods, but that is better |
---|
1088 | n/a | * done directly in Python, allowing subclasses to be created directly. |
---|
1089 | n/a | * We'd really have to write a wrapper around it all anyway to allow |
---|
1090 | n/a | * inheritance. |
---|
1091 | n/a | */ |
---|
1092 | n/a | static PyMethodDef parser_functions[] = { |
---|
1093 | n/a | {"compilest", (PyCFunction)parser_compilest, PUBLIC_METHOD_TYPE, |
---|
1094 | n/a | PyDoc_STR("Compiles an ST object into a code object.")}, |
---|
1095 | n/a | {"expr", (PyCFunction)parser_expr, PUBLIC_METHOD_TYPE, |
---|
1096 | n/a | PyDoc_STR("Creates an ST object from an expression.")}, |
---|
1097 | n/a | {"isexpr", (PyCFunction)parser_isexpr, PUBLIC_METHOD_TYPE, |
---|
1098 | n/a | PyDoc_STR("Determines if an ST object was created from an expression.")}, |
---|
1099 | n/a | {"issuite", (PyCFunction)parser_issuite, PUBLIC_METHOD_TYPE, |
---|
1100 | n/a | PyDoc_STR("Determines if an ST object was created from a suite.")}, |
---|
1101 | n/a | {"suite", (PyCFunction)parser_suite, PUBLIC_METHOD_TYPE, |
---|
1102 | n/a | PyDoc_STR("Creates an ST object from a suite.")}, |
---|
1103 | n/a | {"sequence2st", (PyCFunction)parser_tuple2st, PUBLIC_METHOD_TYPE, |
---|
1104 | n/a | PyDoc_STR("Creates an ST object from a tree representation.")}, |
---|
1105 | n/a | {"st2tuple", (PyCFunction)parser_st2tuple, PUBLIC_METHOD_TYPE, |
---|
1106 | n/a | PyDoc_STR("Creates a tuple-tree representation of an ST.")}, |
---|
1107 | n/a | {"st2list", (PyCFunction)parser_st2list, PUBLIC_METHOD_TYPE, |
---|
1108 | n/a | PyDoc_STR("Creates a list-tree representation of an ST.")}, |
---|
1109 | n/a | {"tuple2st", (PyCFunction)parser_tuple2st, PUBLIC_METHOD_TYPE, |
---|
1110 | n/a | PyDoc_STR("Creates an ST object from a tree representation.")}, |
---|
1111 | n/a | |
---|
1112 | n/a | /* private stuff: support pickle module */ |
---|
1113 | n/a | {"_pickler", (PyCFunction)parser__pickler, METH_VARARGS, |
---|
1114 | n/a | PyDoc_STR("Returns the pickle magic to allow ST objects to be pickled.")}, |
---|
1115 | n/a | |
---|
1116 | n/a | {NULL, NULL, 0, NULL} |
---|
1117 | n/a | }; |
---|
1118 | n/a | |
---|
1119 | n/a | |
---|
1120 | n/a | |
---|
1121 | n/a | static struct PyModuleDef parsermodule = { |
---|
1122 | n/a | PyModuleDef_HEAD_INIT, |
---|
1123 | n/a | "parser", |
---|
1124 | n/a | NULL, |
---|
1125 | n/a | -1, |
---|
1126 | n/a | parser_functions, |
---|
1127 | n/a | NULL, |
---|
1128 | n/a | NULL, |
---|
1129 | n/a | NULL, |
---|
1130 | n/a | NULL |
---|
1131 | n/a | }; |
---|
1132 | n/a | |
---|
1133 | n/a | PyMODINIT_FUNC PyInit_parser(void); /* supply a prototype */ |
---|
1134 | n/a | |
---|
1135 | n/a | PyMODINIT_FUNC |
---|
1136 | n/a | PyInit_parser(void) |
---|
1137 | n/a | { |
---|
1138 | n/a | PyObject *module, *copyreg; |
---|
1139 | n/a | |
---|
1140 | n/a | if (PyType_Ready(&PyST_Type) < 0) |
---|
1141 | n/a | return NULL; |
---|
1142 | n/a | module = PyModule_Create(&parsermodule); |
---|
1143 | n/a | if (module == NULL) |
---|
1144 | n/a | return NULL; |
---|
1145 | n/a | |
---|
1146 | n/a | if (parser_error == 0) |
---|
1147 | n/a | parser_error = PyErr_NewException("parser.ParserError", NULL, NULL); |
---|
1148 | n/a | |
---|
1149 | n/a | if (parser_error == 0) |
---|
1150 | n/a | return NULL; |
---|
1151 | n/a | /* CAUTION: The code next used to skip bumping the refcount on |
---|
1152 | n/a | * parser_error. That's a disaster if PyInit_parser() gets called more |
---|
1153 | n/a | * than once. By incref'ing, we ensure that each module dict that |
---|
1154 | n/a | * gets created owns its reference to the shared parser_error object, |
---|
1155 | n/a | * and the file static parser_error vrbl owns a reference too. |
---|
1156 | n/a | */ |
---|
1157 | n/a | Py_INCREF(parser_error); |
---|
1158 | n/a | if (PyModule_AddObject(module, "ParserError", parser_error) != 0) |
---|
1159 | n/a | return NULL; |
---|
1160 | n/a | |
---|
1161 | n/a | Py_INCREF(&PyST_Type); |
---|
1162 | n/a | PyModule_AddObject(module, "STType", (PyObject*)&PyST_Type); |
---|
1163 | n/a | |
---|
1164 | n/a | PyModule_AddStringConstant(module, "__copyright__", |
---|
1165 | n/a | parser_copyright_string); |
---|
1166 | n/a | PyModule_AddStringConstant(module, "__doc__", |
---|
1167 | n/a | parser_doc_string); |
---|
1168 | n/a | PyModule_AddStringConstant(module, "__version__", |
---|
1169 | n/a | parser_version_string); |
---|
1170 | n/a | |
---|
1171 | n/a | /* Register to support pickling. |
---|
1172 | n/a | * If this fails, the import of this module will fail because an |
---|
1173 | n/a | * exception will be raised here; should we clear the exception? |
---|
1174 | n/a | */ |
---|
1175 | n/a | copyreg = PyImport_ImportModuleNoBlock("copyreg"); |
---|
1176 | n/a | if (copyreg != NULL) { |
---|
1177 | n/a | PyObject *func, *pickler; |
---|
1178 | n/a | _Py_IDENTIFIER(pickle); |
---|
1179 | n/a | _Py_IDENTIFIER(sequence2st); |
---|
1180 | n/a | _Py_IDENTIFIER(_pickler); |
---|
1181 | n/a | |
---|
1182 | n/a | func = _PyObject_GetAttrId(copyreg, &PyId_pickle); |
---|
1183 | n/a | pickle_constructor = _PyObject_GetAttrId(module, &PyId_sequence2st); |
---|
1184 | n/a | pickler = _PyObject_GetAttrId(module, &PyId__pickler); |
---|
1185 | n/a | Py_XINCREF(pickle_constructor); |
---|
1186 | n/a | if ((func != NULL) && (pickle_constructor != NULL) |
---|
1187 | n/a | && (pickler != NULL)) { |
---|
1188 | n/a | PyObject *res; |
---|
1189 | n/a | |
---|
1190 | n/a | res = PyObject_CallFunctionObjArgs(func, &PyST_Type, pickler, |
---|
1191 | n/a | pickle_constructor, NULL); |
---|
1192 | n/a | Py_XDECREF(res); |
---|
1193 | n/a | } |
---|
1194 | n/a | Py_XDECREF(func); |
---|
1195 | n/a | Py_XDECREF(pickle_constructor); |
---|
1196 | n/a | Py_XDECREF(pickler); |
---|
1197 | n/a | Py_DECREF(copyreg); |
---|
1198 | n/a | } |
---|
1199 | n/a | return module; |
---|
1200 | n/a | } |
---|