blob: d15af41581d7c7c077204b7fdcf573bc3992417d [file] [log] [blame]
Damien George04b91472014-05-03 23:27:38 +01001/*
2 * This file is part of the Micro Python project, http://micropython.org/
3 *
4 * The MIT License (MIT)
5 *
Damien George4735c452015-04-21 16:43:18 +00006 * Copyright (c) 2013-2015 Damien P. George
Damien George04b91472014-05-03 23:27:38 +01007 *
8 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 * of this software and associated documentation files (the "Software"), to deal
10 * in the Software without restriction, including without limitation the rights
11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 * copies of the Software, and to permit persons to whom the Software is
13 * furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 * THE SOFTWARE.
25 */
26
xbeefe34222014-03-16 00:14:26 -070027#include <stdbool.h>
Damien429d7192013-10-04 19:53:11 +010028#include <stdint.h>
29#include <stdio.h>
Damien George7dbf74c2016-01-08 13:42:00 +000030#include <unistd.h> // for ssize_t
Damien429d7192013-10-04 19:53:11 +010031#include <assert.h>
Damien George5042bce2014-05-25 22:06:06 +010032#include <string.h>
Damien429d7192013-10-04 19:53:11 +010033
Damien George0bfc7632015-02-07 18:33:58 +000034#include "py/nlr.h"
Damien George51dfcb42015-01-01 20:27:54 +000035#include "py/lexer.h"
36#include "py/parse.h"
37#include "py/parsenum.h"
Damien George22b22652016-01-07 14:40:35 +000038#include "py/runtime0.h"
Damien George64f2b212015-10-08 14:58:15 +010039#include "py/runtime.h"
Damien George22b22652016-01-07 14:40:35 +000040#include "py/objint.h"
Damien George64f2b212015-10-08 14:58:15 +010041#include "py/builtin.h"
Damien429d7192013-10-04 19:53:11 +010042
Damien Georgedd5353a2015-12-18 12:35:44 +000043#if MICROPY_ENABLE_COMPILER
44
Damien429d7192013-10-04 19:53:11 +010045#define RULE_ACT_ARG_MASK (0x0f)
Damien Georgeb47ea4e2014-12-20 18:37:50 +000046#define RULE_ACT_KIND_MASK (0x30)
47#define RULE_ACT_ALLOW_IDENT (0x40)
48#define RULE_ACT_ADD_BLANK (0x80)
Damien429d7192013-10-04 19:53:11 +010049#define RULE_ACT_OR (0x10)
50#define RULE_ACT_AND (0x20)
51#define RULE_ACT_LIST (0x30)
52
Damien429d7192013-10-04 19:53:11 +010053#define RULE_ARG_KIND_MASK (0xf000)
54#define RULE_ARG_ARG_MASK (0x0fff)
55#define RULE_ARG_TOK (0x1000)
56#define RULE_ARG_RULE (0x2000)
Damien George4735c452015-04-21 16:43:18 +000057#define RULE_ARG_OPT_RULE (0x3000)
Damien429d7192013-10-04 19:53:11 +010058
59// (un)comment to use rule names; for debugging
60//#define USE_RULE_NAME (1)
61
62typedef struct _rule_t {
63 byte rule_id;
64 byte act;
65#ifdef USE_RULE_NAME
66 const char *rule_name;
67#endif
68 uint16_t arg[];
69} rule_t;
70
71enum {
Damien George71019ae2017-02-15 10:58:05 +110072// define rules with a compile function
Damien George00208ce2014-01-23 00:00:53 +000073#define DEF_RULE(rule, comp, kind, ...) RULE_##rule,
Damien George71019ae2017-02-15 10:58:05 +110074#define DEF_RULE_NC(rule, kind, ...)
Damien George51dfcb42015-01-01 20:27:54 +000075#include "py/grammar.h"
Damien429d7192013-10-04 19:53:11 +010076#undef DEF_RULE
Damien George71019ae2017-02-15 10:58:05 +110077#undef DEF_RULE_NC
Damien George5042bce2014-05-25 22:06:06 +010078 RULE_string, // special node for non-interned string
Damien George4c81ba82015-01-13 16:21:23 +000079 RULE_bytes, // special node for non-interned bytes
Damien George7d414a12015-02-08 01:57:40 +000080 RULE_const_object, // special node for a constant, generic Python object
Damien George71019ae2017-02-15 10:58:05 +110081
82// define rules without a compile function
83#define DEF_RULE(rule, comp, kind, ...)
84#define DEF_RULE_NC(rule, kind, ...) RULE_##rule,
85#include "py/grammar.h"
86#undef DEF_RULE
87#undef DEF_RULE_NC
Damien429d7192013-10-04 19:53:11 +010088};
89
90#define or(n) (RULE_ACT_OR | n)
91#define and(n) (RULE_ACT_AND | n)
Damien George0c1de1c2016-04-14 13:23:50 +010092#define and_ident(n) (RULE_ACT_AND | n | RULE_ACT_ALLOW_IDENT)
93#define and_blank(n) (RULE_ACT_AND | n | RULE_ACT_ADD_BLANK)
Damien429d7192013-10-04 19:53:11 +010094#define one_or_more (RULE_ACT_LIST | 2)
95#define list (RULE_ACT_LIST | 1)
96#define list_with_end (RULE_ACT_LIST | 3)
Damiend99b0522013-12-21 18:17:45 +000097#define tok(t) (RULE_ARG_TOK | MP_TOKEN_##t)
Damien429d7192013-10-04 19:53:11 +010098#define rule(r) (RULE_ARG_RULE | RULE_##r)
Damien429d7192013-10-04 19:53:11 +010099#define opt_rule(r) (RULE_ARG_OPT_RULE | RULE_##r)
100#ifdef USE_RULE_NAME
Damien George00208ce2014-01-23 00:00:53 +0000101#define DEF_RULE(rule, comp, kind, ...) static const rule_t rule_##rule = { RULE_##rule, kind, #rule, { __VA_ARGS__ } };
Damien George71019ae2017-02-15 10:58:05 +1100102#define DEF_RULE_NC(rule, kind, ...) static const rule_t rule_##rule = { RULE_##rule, kind, #rule, { __VA_ARGS__ } };
Damien429d7192013-10-04 19:53:11 +0100103#else
Damien George00208ce2014-01-23 00:00:53 +0000104#define DEF_RULE(rule, comp, kind, ...) static const rule_t rule_##rule = { RULE_##rule, kind, { __VA_ARGS__ } };
Damien George71019ae2017-02-15 10:58:05 +1100105#define DEF_RULE_NC(rule, kind, ...) static const rule_t rule_##rule = { RULE_##rule, kind, { __VA_ARGS__ } };
Damien429d7192013-10-04 19:53:11 +0100106#endif
Damien George51dfcb42015-01-01 20:27:54 +0000107#include "py/grammar.h"
Damien429d7192013-10-04 19:53:11 +0100108#undef or
109#undef and
110#undef list
111#undef list_with_end
112#undef tok
113#undef rule
Damien429d7192013-10-04 19:53:11 +0100114#undef opt_rule
115#undef one_or_more
116#undef DEF_RULE
Damien George71019ae2017-02-15 10:58:05 +1100117#undef DEF_RULE_NC
Damien429d7192013-10-04 19:53:11 +0100118
Damien George3ff16ff2016-05-20 12:38:15 +0100119STATIC const rule_t *const rules[] = {
Damien George71019ae2017-02-15 10:58:05 +1100120// define rules with a compile function
Damien George00208ce2014-01-23 00:00:53 +0000121#define DEF_RULE(rule, comp, kind, ...) &rule_##rule,
Damien George71019ae2017-02-15 10:58:05 +1100122#define DEF_RULE_NC(rule, kind, ...)
Damien George51dfcb42015-01-01 20:27:54 +0000123#include "py/grammar.h"
Damien429d7192013-10-04 19:53:11 +0100124#undef DEF_RULE
Damien George71019ae2017-02-15 10:58:05 +1100125#undef DEF_RULE_NC
126 NULL, // RULE_string
127 NULL, // RULE_bytes
128 NULL, // RULE_const_object
129
130// define rules without a compile function
131#define DEF_RULE(rule, comp, kind, ...)
132#define DEF_RULE_NC(rule, kind, ...) &rule_##rule,
133#include "py/grammar.h"
134#undef DEF_RULE
135#undef DEF_RULE_NC
Damien429d7192013-10-04 19:53:11 +0100136};
137
138typedef struct _rule_stack_t {
Damien George16a6a472015-12-17 13:06:05 +0000139 size_t src_line : 8 * sizeof(size_t) - 8; // maximum bits storing source line number
140 size_t rule_id : 8; // this must be large enough to fit largest rule number
141 size_t arg_i; // this dictates the maximum nodes in a "list" of things
Damien429d7192013-10-04 19:53:11 +0100142} rule_stack_t;
143
Damien George58e0f4a2015-09-23 10:50:43 +0100144typedef struct _mp_parse_chunk_t {
Damien George16a6a472015-12-17 13:06:05 +0000145 size_t alloc;
Damien George58e0f4a2015-09-23 10:50:43 +0100146 union {
Damien George16a6a472015-12-17 13:06:05 +0000147 size_t used;
Damien George58e0f4a2015-09-23 10:50:43 +0100148 struct _mp_parse_chunk_t *next;
149 } union_;
150 byte data[];
151} mp_parse_chunk_t;
152
Damien George64f2b212015-10-08 14:58:15 +0100153typedef enum {
154 PARSE_ERROR_NONE = 0,
155 PARSE_ERROR_MEMORY,
156 PARSE_ERROR_CONST,
157} parse_error_t;
158
Damien429d7192013-10-04 19:53:11 +0100159typedef struct _parser_t {
Damien George64f2b212015-10-08 14:58:15 +0100160 parse_error_t parse_error;
Damien George58ba4c32014-04-10 14:27:31 +0000161
Damien George16a6a472015-12-17 13:06:05 +0000162 size_t rule_stack_alloc;
163 size_t rule_stack_top;
Damien429d7192013-10-04 19:53:11 +0100164 rule_stack_t *rule_stack;
165
Damien George16a6a472015-12-17 13:06:05 +0000166 size_t result_stack_alloc;
167 size_t result_stack_top;
Damiend99b0522013-12-21 18:17:45 +0000168 mp_parse_node_t *result_stack;
Damien George08335002014-01-18 23:24:36 +0000169
170 mp_lexer_t *lexer;
Damien George58e0f4a2015-09-23 10:50:43 +0100171
172 mp_parse_tree_t tree;
173 mp_parse_chunk_t *cur_chunk;
Damien429d7192013-10-04 19:53:11 +0100174
Damien George64f2b212015-10-08 14:58:15 +0100175 #if MICROPY_COMP_CONST
176 mp_map_t consts;
177 #endif
178} parser_t;
Damien George58ba4c32014-04-10 14:27:31 +0000179
Damien George58e0f4a2015-09-23 10:50:43 +0100180STATIC void *parser_alloc(parser_t *parser, size_t num_bytes) {
181 // use a custom memory allocator to store parse nodes sequentially in large chunks
182
183 mp_parse_chunk_t *chunk = parser->cur_chunk;
184
185 if (chunk != NULL && chunk->union_.used + num_bytes > chunk->alloc) {
186 // not enough room at end of previously allocated chunk so try to grow
187 mp_parse_chunk_t *new_data = (mp_parse_chunk_t*)m_renew_maybe(byte, chunk,
188 sizeof(mp_parse_chunk_t) + chunk->alloc,
189 sizeof(mp_parse_chunk_t) + chunk->alloc + num_bytes, false);
190 if (new_data == NULL) {
191 // could not grow existing memory; shrink it to fit previous
Damien Georged6c558c2016-02-23 13:44:29 +0000192 (void)m_renew_maybe(byte, chunk, sizeof(mp_parse_chunk_t) + chunk->alloc,
193 sizeof(mp_parse_chunk_t) + chunk->union_.used, false);
Damien George58e0f4a2015-09-23 10:50:43 +0100194 chunk->alloc = chunk->union_.used;
195 chunk->union_.next = parser->tree.chunk;
196 parser->tree.chunk = chunk;
197 chunk = NULL;
198 } else {
199 // could grow existing memory
200 chunk->alloc += num_bytes;
201 }
202 }
203
204 if (chunk == NULL) {
205 // no previous chunk, allocate a new chunk
206 size_t alloc = MICROPY_ALLOC_PARSE_CHUNK_INIT;
207 if (alloc < num_bytes) {
208 alloc = num_bytes;
209 }
210 chunk = (mp_parse_chunk_t*)m_new(byte, sizeof(mp_parse_chunk_t) + alloc);
211 chunk->alloc = alloc;
212 chunk->union_.used = 0;
213 parser->cur_chunk = chunk;
214 }
215
216 byte *ret = chunk->data + chunk->union_.used;
217 chunk->union_.used += num_bytes;
218 return ret;
219}
220
Damien George16a6a472015-12-17 13:06:05 +0000221STATIC void push_rule(parser_t *parser, size_t src_line, const rule_t *rule, size_t arg_i) {
Damien George64f2b212015-10-08 14:58:15 +0100222 if (parser->parse_error) {
Damien George58ba4c32014-04-10 14:27:31 +0000223 return;
224 }
Damien429d7192013-10-04 19:53:11 +0100225 if (parser->rule_stack_top >= parser->rule_stack_alloc) {
Damien Georgeade9a052015-06-13 21:53:22 +0100226 rule_stack_t *rs = m_renew_maybe(rule_stack_t, parser->rule_stack, parser->rule_stack_alloc, parser->rule_stack_alloc + MICROPY_ALLOC_PARSE_RULE_INC, true);
Damien George58ba4c32014-04-10 14:27:31 +0000227 if (rs == NULL) {
Damien George64f2b212015-10-08 14:58:15 +0100228 parser->parse_error = PARSE_ERROR_MEMORY;
Damien George58ba4c32014-04-10 14:27:31 +0000229 return;
230 }
231 parser->rule_stack = rs;
Damien George58ebde42014-05-21 20:32:59 +0100232 parser->rule_stack_alloc += MICROPY_ALLOC_PARSE_RULE_INC;
Damien429d7192013-10-04 19:53:11 +0100233 }
Damien George08335002014-01-18 23:24:36 +0000234 rule_stack_t *rs = &parser->rule_stack[parser->rule_stack_top++];
235 rs->src_line = src_line;
236 rs->rule_id = rule->rule_id;
237 rs->arg_i = arg_i;
Damien429d7192013-10-04 19:53:11 +0100238}
239
Damien George16a6a472015-12-17 13:06:05 +0000240STATIC void push_rule_from_arg(parser_t *parser, size_t arg) {
Damien429d7192013-10-04 19:53:11 +0100241 assert((arg & RULE_ARG_KIND_MASK) == RULE_ARG_RULE || (arg & RULE_ARG_KIND_MASK) == RULE_ARG_OPT_RULE);
Damien George16a6a472015-12-17 13:06:05 +0000242 size_t rule_id = arg & RULE_ARG_ARG_MASK;
Damien Georgea4c52c52014-12-05 19:35:18 +0000243 push_rule(parser, parser->lexer->tok_line, rules[rule_id], 0);
Damien429d7192013-10-04 19:53:11 +0100244}
245
Damien George16a6a472015-12-17 13:06:05 +0000246STATIC void pop_rule(parser_t *parser, const rule_t **rule, size_t *arg_i, size_t *src_line) {
Damien George64f2b212015-10-08 14:58:15 +0100247 assert(!parser->parse_error);
Damien429d7192013-10-04 19:53:11 +0100248 parser->rule_stack_top -= 1;
249 *rule = rules[parser->rule_stack[parser->rule_stack_top].rule_id];
250 *arg_i = parser->rule_stack[parser->rule_stack_top].arg_i;
Damien George08335002014-01-18 23:24:36 +0000251 *src_line = parser->rule_stack[parser->rule_stack_top].src_line;
Damien429d7192013-10-04 19:53:11 +0100252}
253
Damien Georgeb0cbfb02016-11-13 15:32:05 +1100254bool mp_parse_node_is_const_false(mp_parse_node_t pn) {
255 return MP_PARSE_NODE_IS_TOKEN_KIND(pn, MP_TOKEN_KW_FALSE)
256 || (MP_PARSE_NODE_IS_SMALL_INT(pn) && MP_PARSE_NODE_LEAF_SMALL_INT(pn) == 0);
257}
258
259bool mp_parse_node_is_const_true(mp_parse_node_t pn) {
260 return MP_PARSE_NODE_IS_TOKEN_KIND(pn, MP_TOKEN_KW_TRUE)
261 || (MP_PARSE_NODE_IS_SMALL_INT(pn) && MP_PARSE_NODE_LEAF_SMALL_INT(pn) != 0);
262}
263
Damien George22b22652016-01-07 14:40:35 +0000264bool mp_parse_node_get_int_maybe(mp_parse_node_t pn, mp_obj_t *o) {
265 if (MP_PARSE_NODE_IS_SMALL_INT(pn)) {
266 *o = MP_OBJ_NEW_SMALL_INT(MP_PARSE_NODE_LEAF_SMALL_INT(pn));
267 return true;
268 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, RULE_const_object)) {
269 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
270 #if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_D
271 // nodes are 32-bit pointers, but need to extract 64-bit object
272 *o = (uint64_t)pns->nodes[0] | ((uint64_t)pns->nodes[1] << 32);
273 #else
274 *o = (mp_obj_t)pns->nodes[0];
275 #endif
276 return MP_OBJ_IS_INT(*o);
277 } else {
278 return false;
279 }
280}
281
Damien George16a6a472015-12-17 13:06:05 +0000282int mp_parse_node_extract_list(mp_parse_node_t *pn, size_t pn_kind, mp_parse_node_t **nodes) {
Damien Georgedfe944c2015-02-13 02:29:46 +0000283 if (MP_PARSE_NODE_IS_NULL(*pn)) {
284 *nodes = NULL;
285 return 0;
286 } else if (MP_PARSE_NODE_IS_LEAF(*pn)) {
287 *nodes = pn;
288 return 1;
289 } else {
290 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)(*pn);
291 if (MP_PARSE_NODE_STRUCT_KIND(pns) != pn_kind) {
292 *nodes = pn;
293 return 1;
294 } else {
295 *nodes = pns->nodes;
296 return MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
297 }
298 }
299}
300
Damien Georgecbd2f742014-01-19 11:48:48 +0000301#if MICROPY_DEBUG_PRINTERS
Damien George16a6a472015-12-17 13:06:05 +0000302void mp_parse_node_print(mp_parse_node_t pn, size_t indent) {
Damien George08335002014-01-18 23:24:36 +0000303 if (MP_PARSE_NODE_IS_STRUCT(pn)) {
304 printf("[% 4d] ", (int)((mp_parse_node_struct_t*)pn)->source_line);
305 } else {
306 printf(" ");
307 }
Damien George16a6a472015-12-17 13:06:05 +0000308 for (size_t i = 0; i < indent; i++) {
Damien429d7192013-10-04 19:53:11 +0100309 printf(" ");
310 }
Damiend99b0522013-12-21 18:17:45 +0000311 if (MP_PARSE_NODE_IS_NULL(pn)) {
Damien429d7192013-10-04 19:53:11 +0100312 printf("NULL\n");
Paul Sokolovsky56e5ef22014-02-22 16:39:45 +0200313 } else if (MP_PARSE_NODE_IS_SMALL_INT(pn)) {
Damien George40f3c022014-07-03 13:25:24 +0100314 mp_int_t arg = MP_PARSE_NODE_LEAF_SMALL_INT(pn);
Paul Sokolovsky56e5ef22014-02-22 16:39:45 +0200315 printf("int(" INT_FMT ")\n", arg);
Damiend99b0522013-12-21 18:17:45 +0000316 } else if (MP_PARSE_NODE_IS_LEAF(pn)) {
Damien George16a6a472015-12-17 13:06:05 +0000317 uintptr_t arg = MP_PARSE_NODE_LEAF_ARG(pn);
Damiend99b0522013-12-21 18:17:45 +0000318 switch (MP_PARSE_NODE_LEAF_KIND(pn)) {
319 case MP_PARSE_NODE_ID: printf("id(%s)\n", qstr_str(arg)); break;
Damiend99b0522013-12-21 18:17:45 +0000320 case MP_PARSE_NODE_STRING: printf("str(%s)\n", qstr_str(arg)); break;
321 case MP_PARSE_NODE_BYTES: printf("bytes(%s)\n", qstr_str(arg)); break;
Damien George86e94232017-01-17 17:00:55 +1100322 default:
323 assert(MP_PARSE_NODE_LEAF_KIND(pn) == MP_PARSE_NODE_TOKEN);
324 printf("tok(%u)\n", (uint)arg); break;
Damien429d7192013-10-04 19:53:11 +0100325 }
326 } else {
Damien George5042bce2014-05-25 22:06:06 +0100327 // node must be a mp_parse_node_struct_t
Damien Georgeb829b5c2014-01-25 13:51:19 +0000328 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
Damien George5042bce2014-05-25 22:06:06 +0100329 if (MP_PARSE_NODE_STRUCT_KIND(pns) == RULE_string) {
330 printf("literal str(%.*s)\n", (int)pns->nodes[1], (char*)pns->nodes[0]);
Damien George4c81ba82015-01-13 16:21:23 +0000331 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == RULE_bytes) {
332 printf("literal bytes(%.*s)\n", (int)pns->nodes[1], (char*)pns->nodes[0]);
Damien George7d414a12015-02-08 01:57:40 +0000333 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == RULE_const_object) {
Damien Georgeb8cfb0d2015-11-27 17:09:11 +0000334 #if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_D
335 printf("literal const(%016llx)\n", (uint64_t)pns->nodes[0] | ((uint64_t)pns->nodes[1] << 32));
336 #else
Damien George7d414a12015-02-08 01:57:40 +0000337 printf("literal const(%p)\n", (mp_obj_t)pns->nodes[0]);
Damien Georgeb8cfb0d2015-11-27 17:09:11 +0000338 #endif
Damien George5042bce2014-05-25 22:06:06 +0100339 } else {
Damien George16a6a472015-12-17 13:06:05 +0000340 size_t n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +0100341#ifdef USE_RULE_NAME
Damien George16a6a472015-12-17 13:06:05 +0000342 printf("%s(%u) (n=%u)\n", rules[MP_PARSE_NODE_STRUCT_KIND(pns)]->rule_name, (uint)MP_PARSE_NODE_STRUCT_KIND(pns), (uint)n);
Damien429d7192013-10-04 19:53:11 +0100343#else
Damien George16a6a472015-12-17 13:06:05 +0000344 printf("rule(%u) (n=%u)\n", (uint)MP_PARSE_NODE_STRUCT_KIND(pns), (uint)n);
Damien429d7192013-10-04 19:53:11 +0100345#endif
Damien George16a6a472015-12-17 13:06:05 +0000346 for (size_t i = 0; i < n; i++) {
Damien George5042bce2014-05-25 22:06:06 +0100347 mp_parse_node_print(pns->nodes[i], indent + 2);
348 }
Damien429d7192013-10-04 19:53:11 +0100349 }
350 }
351}
Damien Georgecbd2f742014-01-19 11:48:48 +0000352#endif // MICROPY_DEBUG_PRINTERS
Damien429d7192013-10-04 19:53:11 +0100353
354/*
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200355STATIC void result_stack_show(parser_t *parser) {
Damien429d7192013-10-04 19:53:11 +0100356 printf("result stack, most recent first\n");
Damien George16a6a472015-12-17 13:06:05 +0000357 for (ssize_t i = parser->result_stack_top - 1; i >= 0; i--) {
Damien Georgecbd2f742014-01-19 11:48:48 +0000358 mp_parse_node_print(parser->result_stack[i], 0);
Damien429d7192013-10-04 19:53:11 +0100359 }
360}
361*/
362
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200363STATIC mp_parse_node_t pop_result(parser_t *parser) {
Damien George64f2b212015-10-08 14:58:15 +0100364 if (parser->parse_error) {
Damien George58ba4c32014-04-10 14:27:31 +0000365 return MP_PARSE_NODE_NULL;
366 }
Damien429d7192013-10-04 19:53:11 +0100367 assert(parser->result_stack_top > 0);
368 return parser->result_stack[--parser->result_stack_top];
369}
370
Damien George16a6a472015-12-17 13:06:05 +0000371STATIC mp_parse_node_t peek_result(parser_t *parser, size_t pos) {
Damien George64f2b212015-10-08 14:58:15 +0100372 if (parser->parse_error) {
Damien George58ba4c32014-04-10 14:27:31 +0000373 return MP_PARSE_NODE_NULL;
374 }
Damien429d7192013-10-04 19:53:11 +0100375 assert(parser->result_stack_top > pos);
376 return parser->result_stack[parser->result_stack_top - 1 - pos];
377}
378
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200379STATIC void push_result_node(parser_t *parser, mp_parse_node_t pn) {
Damien George64f2b212015-10-08 14:58:15 +0100380 if (parser->parse_error) {
Damien George58ba4c32014-04-10 14:27:31 +0000381 return;
382 }
Damien George69a818d2014-01-12 13:55:24 +0000383 if (parser->result_stack_top >= parser->result_stack_alloc) {
Damien Georgeade9a052015-06-13 21:53:22 +0100384 mp_parse_node_t *stack = m_renew_maybe(mp_parse_node_t, parser->result_stack, parser->result_stack_alloc, parser->result_stack_alloc + MICROPY_ALLOC_PARSE_RESULT_INC, true);
Damien George50912e72015-01-20 11:55:10 +0000385 if (stack == NULL) {
Damien George64f2b212015-10-08 14:58:15 +0100386 parser->parse_error = PARSE_ERROR_MEMORY;
Damien George58ba4c32014-04-10 14:27:31 +0000387 return;
388 }
Damien George50912e72015-01-20 11:55:10 +0000389 parser->result_stack = stack;
Damien George58ebde42014-05-21 20:32:59 +0100390 parser->result_stack_alloc += MICROPY_ALLOC_PARSE_RESULT_INC;
Damien George69a818d2014-01-12 13:55:24 +0000391 }
Damien429d7192013-10-04 19:53:11 +0100392 parser->result_stack[parser->result_stack_top++] = pn;
393}
394
Damien George16a6a472015-12-17 13:06:05 +0000395STATIC mp_parse_node_t make_node_string_bytes(parser_t *parser, size_t src_line, size_t rule_kind, const char *str, size_t len) {
Damien George58e0f4a2015-09-23 10:50:43 +0100396 mp_parse_node_struct_t *pn = parser_alloc(parser, sizeof(mp_parse_node_struct_t) + sizeof(mp_parse_node_t) * 2);
Damien George5042bce2014-05-25 22:06:06 +0100397 if (pn == NULL) {
Damien George64f2b212015-10-08 14:58:15 +0100398 parser->parse_error = PARSE_ERROR_MEMORY;
Damien George7d414a12015-02-08 01:57:40 +0000399 return MP_PARSE_NODE_NULL;
Damien George5042bce2014-05-25 22:06:06 +0100400 }
401 pn->source_line = src_line;
Damien George4c81ba82015-01-13 16:21:23 +0000402 pn->kind_num_nodes = rule_kind | (2 << 8);
Damien George5042bce2014-05-25 22:06:06 +0100403 char *p = m_new(char, len);
404 memcpy(p, str, len);
Damien George999cedb2015-11-27 17:01:44 +0000405 pn->nodes[0] = (uintptr_t)p;
Damien George5042bce2014-05-25 22:06:06 +0100406 pn->nodes[1] = len;
Damien George7d414a12015-02-08 01:57:40 +0000407 return (mp_parse_node_t)pn;
408}
409
Damien George16a6a472015-12-17 13:06:05 +0000410STATIC mp_parse_node_t make_node_const_object(parser_t *parser, size_t src_line, mp_obj_t obj) {
Damien George999cedb2015-11-27 17:01:44 +0000411 mp_parse_node_struct_t *pn = parser_alloc(parser, sizeof(mp_parse_node_struct_t) + sizeof(mp_obj_t));
Damien George7d414a12015-02-08 01:57:40 +0000412 if (pn == NULL) {
Damien George64f2b212015-10-08 14:58:15 +0100413 parser->parse_error = PARSE_ERROR_MEMORY;
Damien George7d414a12015-02-08 01:57:40 +0000414 return MP_PARSE_NODE_NULL;
415 }
416 pn->source_line = src_line;
Damien Georgeb8cfb0d2015-11-27 17:09:11 +0000417 #if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_D
418 // nodes are 32-bit pointers, but need to store 64-bit object
419 pn->kind_num_nodes = RULE_const_object | (2 << 8);
420 pn->nodes[0] = (uint64_t)obj;
421 pn->nodes[1] = (uint64_t)obj >> 32;
422 #else
Damien George7d414a12015-02-08 01:57:40 +0000423 pn->kind_num_nodes = RULE_const_object | (1 << 8);
Damien George16a6a472015-12-17 13:06:05 +0000424 pn->nodes[0] = (uintptr_t)obj;
Damien Georgeb8cfb0d2015-11-27 17:09:11 +0000425 #endif
Damien George7d414a12015-02-08 01:57:40 +0000426 return (mp_parse_node_t)pn;
Damien George5042bce2014-05-25 22:06:06 +0100427}
Paul Sokolovsky9e76b112014-05-08 22:43:46 +0300428
Damien George6d310a52016-09-23 17:23:16 +1000429STATIC void push_result_token(parser_t *parser, const rule_t *rule) {
Damiend99b0522013-12-21 18:17:45 +0000430 mp_parse_node_t pn;
Damien Georgea4c52c52014-12-05 19:35:18 +0000431 mp_lexer_t *lex = parser->lexer;
432 if (lex->tok_kind == MP_TOKEN_NAME) {
Damien George64f2b212015-10-08 14:58:15 +0100433 qstr id = qstr_from_strn(lex->vstr.buf, lex->vstr.len);
434 #if MICROPY_COMP_CONST
Damien George6d310a52016-09-23 17:23:16 +1000435 // if name is a standalone identifier, look it up in the table of dynamic constants
436 mp_map_elem_t *elem;
437 if (rule->rule_id == RULE_atom
438 && (elem = mp_map_lookup(&parser->consts, MP_OBJ_NEW_QSTR(id), MP_MAP_LOOKUP)) != NULL) {
Damien Georgeed9c93f2016-11-13 15:35:11 +1100439 pn = mp_parse_node_new_small_int(MP_OBJ_SMALL_INT_VALUE(elem->value));
Damien George6d310a52016-09-23 17:23:16 +1000440 } else {
Damien George64f2b212015-10-08 14:58:15 +0100441 pn = mp_parse_node_new_leaf(MP_PARSE_NODE_ID, id);
442 }
Damien George6d310a52016-09-23 17:23:16 +1000443 #else
444 (void)rule;
445 pn = mp_parse_node_new_leaf(MP_PARSE_NODE_ID, id);
446 #endif
Damien George7d414a12015-02-08 01:57:40 +0000447 } else if (lex->tok_kind == MP_TOKEN_INTEGER) {
448 mp_obj_t o = mp_parse_num_integer(lex->vstr.buf, lex->vstr.len, 0, lex);
449 if (MP_OBJ_IS_SMALL_INT(o)) {
Damien Georgeed9c93f2016-11-13 15:35:11 +1100450 pn = mp_parse_node_new_small_int(MP_OBJ_SMALL_INT_VALUE(o));
Damien429d7192013-10-04 19:53:11 +0100451 } else {
Damien George7d414a12015-02-08 01:57:40 +0000452 pn = make_node_const_object(parser, lex->tok_line, o);
Damien429d7192013-10-04 19:53:11 +0100453 }
Damien George7d414a12015-02-08 01:57:40 +0000454 } else if (lex->tok_kind == MP_TOKEN_FLOAT_OR_IMAG) {
455 mp_obj_t o = mp_parse_num_decimal(lex->vstr.buf, lex->vstr.len, true, false, lex);
456 pn = make_node_const_object(parser, lex->tok_line, o);
Damien George4c81ba82015-01-13 16:21:23 +0000457 } else if (lex->tok_kind == MP_TOKEN_STRING || lex->tok_kind == MP_TOKEN_BYTES) {
458 // Don't automatically intern all strings/bytes. doc strings (which are usually large)
Damien George5042bce2014-05-25 22:06:06 +0100459 // will be discarded by the compiler, and so we shouldn't intern them.
460 qstr qst = MP_QSTR_NULL;
Damien Georgea4c52c52014-12-05 19:35:18 +0000461 if (lex->vstr.len <= MICROPY_ALLOC_PARSE_INTERN_STRING_LEN) {
Damien George5042bce2014-05-25 22:06:06 +0100462 // intern short strings
Damien Georgea4c52c52014-12-05 19:35:18 +0000463 qst = qstr_from_strn(lex->vstr.buf, lex->vstr.len);
Damien George5042bce2014-05-25 22:06:06 +0100464 } else {
465 // check if this string is already interned
Damien Georgea4c52c52014-12-05 19:35:18 +0000466 qst = qstr_find_strn(lex->vstr.buf, lex->vstr.len);
Damien George5042bce2014-05-25 22:06:06 +0100467 }
468 if (qst != MP_QSTR_NULL) {
469 // qstr exists, make a leaf node
Damien George4c81ba82015-01-13 16:21:23 +0000470 pn = mp_parse_node_new_leaf(lex->tok_kind == MP_TOKEN_STRING ? MP_PARSE_NODE_STRING : MP_PARSE_NODE_BYTES, qst);
Damien George5042bce2014-05-25 22:06:06 +0100471 } else {
Damien George4c81ba82015-01-13 16:21:23 +0000472 // not interned, make a node holding a pointer to the string/bytes data
Damien George7d414a12015-02-08 01:57:40 +0000473 pn = make_node_string_bytes(parser, lex->tok_line, lex->tok_kind == MP_TOKEN_STRING ? RULE_string : RULE_bytes, lex->vstr.buf, lex->vstr.len);
Damien George5042bce2014-05-25 22:06:06 +0100474 }
Damien429d7192013-10-04 19:53:11 +0100475 } else {
Damien Georgea4c52c52014-12-05 19:35:18 +0000476 pn = mp_parse_node_new_leaf(MP_PARSE_NODE_TOKEN, lex->tok_kind);
Damien429d7192013-10-04 19:53:11 +0100477 }
478 push_result_node(parser, pn);
479}
480
Damien George64f2b212015-10-08 14:58:15 +0100481#if MICROPY_COMP_MODULE_CONST
Damien Georgecbf76742015-11-27 13:38:15 +0000482STATIC const mp_rom_map_elem_t mp_constants_table[] = {
Damien Georgee36ff982016-05-10 23:23:50 +0100483 #if MICROPY_PY_UERRNO
484 { MP_ROM_QSTR(MP_QSTR_errno), MP_ROM_PTR(&mp_module_uerrno) },
485 #endif
Damien George64f2b212015-10-08 14:58:15 +0100486 #if MICROPY_PY_UCTYPES
Damien Georgecbf76742015-11-27 13:38:15 +0000487 { MP_ROM_QSTR(MP_QSTR_uctypes), MP_ROM_PTR(&mp_module_uctypes) },
Damien George64f2b212015-10-08 14:58:15 +0100488 #endif
489 // Extra constants as defined by a port
490 MICROPY_PORT_CONSTANTS
491};
492STATIC MP_DEFINE_CONST_MAP(mp_constants_map, mp_constants_table);
493#endif
494
Damien Georgeb1533c42016-06-06 17:28:32 +0100495STATIC void push_result_rule(parser_t *parser, size_t src_line, const rule_t *rule, size_t num_args);
496
Damien George64f2b212015-10-08 14:58:15 +0100497#if MICROPY_COMP_CONST_FOLDING
Damien George9b525132016-11-13 15:36:49 +1100498STATIC bool fold_logical_constants(parser_t *parser, const rule_t *rule, size_t *num_args) {
499 if (rule->rule_id == RULE_or_test
500 || rule->rule_id == RULE_and_test) {
501 // folding for binary logical ops: or and
502 size_t copy_to = *num_args;
503 for (size_t i = copy_to; i > 0;) {
504 mp_parse_node_t pn = peek_result(parser, --i);
505 parser->result_stack[parser->result_stack_top - copy_to] = pn;
506 if (i == 0) {
507 // always need to keep the last value
508 break;
509 }
510 if (rule->rule_id == RULE_or_test) {
511 if (mp_parse_node_is_const_true(pn)) {
512 //
513 break;
514 } else if (!mp_parse_node_is_const_false(pn)) {
515 copy_to -= 1;
516 }
517 } else {
518 // RULE_and_test
519 if (mp_parse_node_is_const_false(pn)) {
520 break;
521 } else if (!mp_parse_node_is_const_true(pn)) {
522 copy_to -= 1;
523 }
524 }
525 }
526 copy_to -= 1; // copy_to now contains number of args to pop
527
528 // pop and discard all the short-circuited expressions
529 for (size_t i = 0; i < copy_to; ++i) {
530 pop_result(parser);
531 }
532 *num_args -= copy_to;
533
534 // we did a complete folding if there's only 1 arg left
535 return *num_args == 1;
536
537 } else if (rule->rule_id == RULE_not_test_2) {
538 // folding for unary logical op: not
539 mp_parse_node_t pn = peek_result(parser, 0);
540 if (mp_parse_node_is_const_false(pn)) {
541 pn = mp_parse_node_new_leaf(MP_PARSE_NODE_TOKEN, MP_TOKEN_KW_TRUE);
542 } else if (mp_parse_node_is_const_true(pn)) {
543 pn = mp_parse_node_new_leaf(MP_PARSE_NODE_TOKEN, MP_TOKEN_KW_FALSE);
544 } else {
545 return false;
546 }
547 pop_result(parser);
548 push_result_node(parser, pn);
549 return true;
550 }
551
552 return false;
553}
554
Damien George16a6a472015-12-17 13:06:05 +0000555STATIC bool fold_constants(parser_t *parser, const rule_t *rule, size_t num_args) {
Damien George64f2b212015-10-08 14:58:15 +0100556 // this code does folding of arbitrary integer expressions, eg 1 + 2 * 3 + 4
557 // it does not do partial folding, eg 1 + 2 + x -> 3 + x
558
Damien George22b22652016-01-07 14:40:35 +0000559 mp_obj_t arg0;
Damien George64f2b212015-10-08 14:58:15 +0100560 if (rule->rule_id == RULE_expr
561 || rule->rule_id == RULE_xor_expr
562 || rule->rule_id == RULE_and_expr) {
563 // folding for binary ops: | ^ &
564 mp_parse_node_t pn = peek_result(parser, num_args - 1);
Damien George22b22652016-01-07 14:40:35 +0000565 if (!mp_parse_node_get_int_maybe(pn, &arg0)) {
Damien George64f2b212015-10-08 14:58:15 +0100566 return false;
567 }
Damien George22b22652016-01-07 14:40:35 +0000568 mp_binary_op_t op;
569 if (rule->rule_id == RULE_expr) {
570 op = MP_BINARY_OP_OR;
571 } else if (rule->rule_id == RULE_xor_expr) {
572 op = MP_BINARY_OP_XOR;
573 } else {
574 op = MP_BINARY_OP_AND;
575 }
Damien George16a6a472015-12-17 13:06:05 +0000576 for (ssize_t i = num_args - 2; i >= 0; --i) {
Damien George64f2b212015-10-08 14:58:15 +0100577 pn = peek_result(parser, i);
Damien George22b22652016-01-07 14:40:35 +0000578 mp_obj_t arg1;
579 if (!mp_parse_node_get_int_maybe(pn, &arg1)) {
Damien George64f2b212015-10-08 14:58:15 +0100580 return false;
581 }
Damien George22b22652016-01-07 14:40:35 +0000582 arg0 = mp_binary_op(op, arg0, arg1);
Damien George64f2b212015-10-08 14:58:15 +0100583 }
584 } else if (rule->rule_id == RULE_shift_expr
585 || rule->rule_id == RULE_arith_expr
586 || rule->rule_id == RULE_term) {
587 // folding for binary ops: << >> + - * / % //
588 mp_parse_node_t pn = peek_result(parser, num_args - 1);
Damien George22b22652016-01-07 14:40:35 +0000589 if (!mp_parse_node_get_int_maybe(pn, &arg0)) {
Damien George64f2b212015-10-08 14:58:15 +0100590 return false;
591 }
Damien George16a6a472015-12-17 13:06:05 +0000592 for (ssize_t i = num_args - 2; i >= 1; i -= 2) {
Damien George64f2b212015-10-08 14:58:15 +0100593 pn = peek_result(parser, i - 1);
Damien George22b22652016-01-07 14:40:35 +0000594 mp_obj_t arg1;
595 if (!mp_parse_node_get_int_maybe(pn, &arg1)) {
Damien George64f2b212015-10-08 14:58:15 +0100596 return false;
597 }
Damien George64f2b212015-10-08 14:58:15 +0100598 mp_token_kind_t tok = MP_PARSE_NODE_LEAF_ARG(peek_result(parser, i));
Damien George22b22652016-01-07 14:40:35 +0000599 static const uint8_t token_to_op[] = {
600 MP_BINARY_OP_ADD,
601 MP_BINARY_OP_SUBTRACT,
602 MP_BINARY_OP_MULTIPLY,
603 255,//MP_BINARY_OP_POWER,
604 255,//MP_BINARY_OP_TRUE_DIVIDE,
605 MP_BINARY_OP_FLOOR_DIVIDE,
606 MP_BINARY_OP_MODULO,
607 255,//MP_BINARY_OP_LESS
608 MP_BINARY_OP_LSHIFT,
609 255,//MP_BINARY_OP_MORE
610 MP_BINARY_OP_RSHIFT,
611 };
612 mp_binary_op_t op = token_to_op[tok - MP_TOKEN_OP_PLUS];
Antonin ENFRUNefc971e2016-01-12 22:06:39 +0100613 if (op == (mp_binary_op_t)255) {
Damien George64f2b212015-10-08 14:58:15 +0100614 return false;
615 }
Damien George22b22652016-01-07 14:40:35 +0000616 int rhs_sign = mp_obj_int_sign(arg1);
617 if (op <= MP_BINARY_OP_RSHIFT) {
618 // << and >> can't have negative rhs
619 if (rhs_sign < 0) {
620 return false;
621 }
622 } else if (op >= MP_BINARY_OP_FLOOR_DIVIDE) {
623 // % and // can't have zero rhs
624 if (rhs_sign == 0) {
625 return false;
626 }
627 }
628 arg0 = mp_binary_op(op, arg0, arg1);
Damien George64f2b212015-10-08 14:58:15 +0100629 }
630 } else if (rule->rule_id == RULE_factor_2) {
631 // folding for unary ops: + - ~
632 mp_parse_node_t pn = peek_result(parser, 0);
Damien George22b22652016-01-07 14:40:35 +0000633 if (!mp_parse_node_get_int_maybe(pn, &arg0)) {
Damien George64f2b212015-10-08 14:58:15 +0100634 return false;
635 }
Damien George64f2b212015-10-08 14:58:15 +0100636 mp_token_kind_t tok = MP_PARSE_NODE_LEAF_ARG(peek_result(parser, 1));
Antonin ENFRUNefc971e2016-01-12 22:06:39 +0100637 mp_unary_op_t op;
Damien George64f2b212015-10-08 14:58:15 +0100638 if (tok == MP_TOKEN_OP_PLUS) {
Damien George22b22652016-01-07 14:40:35 +0000639 op = MP_UNARY_OP_POSITIVE;
Damien George64f2b212015-10-08 14:58:15 +0100640 } else if (tok == MP_TOKEN_OP_MINUS) {
Damien George22b22652016-01-07 14:40:35 +0000641 op = MP_UNARY_OP_NEGATIVE;
Damien George64f2b212015-10-08 14:58:15 +0100642 } else {
643 assert(tok == MP_TOKEN_OP_TILDE); // should be
Damien George22b22652016-01-07 14:40:35 +0000644 op = MP_UNARY_OP_INVERT;
Damien George64f2b212015-10-08 14:58:15 +0100645 }
Damien George22b22652016-01-07 14:40:35 +0000646 arg0 = mp_unary_op(op, arg0);
Damien George64f2b212015-10-08 14:58:15 +0100647
648 #if MICROPY_COMP_CONST
649 } else if (rule->rule_id == RULE_expr_stmt) {
650 mp_parse_node_t pn1 = peek_result(parser, 0);
651 if (!MP_PARSE_NODE_IS_NULL(pn1)
652 && !(MP_PARSE_NODE_IS_STRUCT_KIND(pn1, RULE_expr_stmt_augassign)
653 || MP_PARSE_NODE_IS_STRUCT_KIND(pn1, RULE_expr_stmt_assign_list))) {
654 // this node is of the form <x> = <y>
655 mp_parse_node_t pn0 = peek_result(parser, 1);
656 if (MP_PARSE_NODE_IS_ID(pn0)
Damien Georgeeacbd7a2016-04-13 15:21:47 +0100657 && MP_PARSE_NODE_IS_STRUCT_KIND(pn1, RULE_atom_expr_normal)
Damien George64f2b212015-10-08 14:58:15 +0100658 && MP_PARSE_NODE_IS_ID(((mp_parse_node_struct_t*)pn1)->nodes[0])
659 && MP_PARSE_NODE_LEAF_ARG(((mp_parse_node_struct_t*)pn1)->nodes[0]) == MP_QSTR_const
660 && MP_PARSE_NODE_IS_STRUCT_KIND(((mp_parse_node_struct_t*)pn1)->nodes[1], RULE_trailer_paren)
Damien George64f2b212015-10-08 14:58:15 +0100661 ) {
662 // code to assign dynamic constants: id = const(value)
663
664 // get the id
665 qstr id = MP_PARSE_NODE_LEAF_ARG(pn0);
666
667 // get the value
668 mp_parse_node_t pn_value = ((mp_parse_node_struct_t*)((mp_parse_node_struct_t*)pn1)->nodes[1])->nodes[0];
669 if (!MP_PARSE_NODE_IS_SMALL_INT(pn_value)) {
670 parser->parse_error = PARSE_ERROR_CONST;
671 return false;
672 }
673 mp_int_t value = MP_PARSE_NODE_LEAF_SMALL_INT(pn_value);
674
675 // store the value in the table of dynamic constants
676 mp_map_elem_t *elem = mp_map_lookup(&parser->consts, MP_OBJ_NEW_QSTR(id), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND);
677 assert(elem->value == MP_OBJ_NULL);
678 elem->value = MP_OBJ_NEW_SMALL_INT(value);
679
Damien Georgeb1533c42016-06-06 17:28:32 +0100680 // If the constant starts with an underscore then treat it as a private
681 // variable and don't emit any code to store the value to the id.
682 if (qstr_str(id)[0] == '_') {
683 pop_result(parser); // pop const(value)
684 pop_result(parser); // pop id
685 push_result_rule(parser, 0, rules[RULE_pass_stmt], 0); // replace with "pass"
686 return true;
687 }
688
Damien George64f2b212015-10-08 14:58:15 +0100689 // replace const(value) with value
690 pop_result(parser);
691 push_result_node(parser, pn_value);
692
693 // finished folding this assignment, but we still want it to be part of the tree
694 return false;
695 }
696 }
697 return false;
698 #endif
699
700 #if MICROPY_COMP_MODULE_CONST
Damien Georgeeacbd7a2016-04-13 15:21:47 +0100701 } else if (rule->rule_id == RULE_atom_expr_normal) {
702 mp_parse_node_t pn0 = peek_result(parser, 1);
703 mp_parse_node_t pn1 = peek_result(parser, 0);
Damien George64f2b212015-10-08 14:58:15 +0100704 if (!(MP_PARSE_NODE_IS_ID(pn0)
Damien Georgeeacbd7a2016-04-13 15:21:47 +0100705 && MP_PARSE_NODE_IS_STRUCT_KIND(pn1, RULE_trailer_period))) {
Damien George64f2b212015-10-08 14:58:15 +0100706 return false;
707 }
708 // id1.id2
709 // look it up in constant table, see if it can be replaced with an integer
710 mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t*)pn1;
711 assert(MP_PARSE_NODE_IS_ID(pns1->nodes[0]));
712 qstr q_base = MP_PARSE_NODE_LEAF_ARG(pn0);
713 qstr q_attr = MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0]);
714 mp_map_elem_t *elem = mp_map_lookup((mp_map_t*)&mp_constants_map, MP_OBJ_NEW_QSTR(q_base), MP_MAP_LOOKUP);
715 if (elem == NULL) {
716 return false;
717 }
718 mp_obj_t dest[2];
719 mp_load_method_maybe(elem->value, q_attr, dest);
Damien George8d4d6732016-03-19 21:36:32 +0000720 if (!(dest[0] != MP_OBJ_NULL && MP_OBJ_IS_INT(dest[0]) && dest[1] == MP_OBJ_NULL)) {
Damien George64f2b212015-10-08 14:58:15 +0100721 return false;
722 }
Damien George22b22652016-01-07 14:40:35 +0000723 arg0 = dest[0];
Damien George64f2b212015-10-08 14:58:15 +0100724 #endif
725
726 } else {
727 return false;
728 }
729
730 // success folding this rule
731
Damien George16a6a472015-12-17 13:06:05 +0000732 for (size_t i = num_args; i > 0; i--) {
Damien George64f2b212015-10-08 14:58:15 +0100733 pop_result(parser);
734 }
Damien George22b22652016-01-07 14:40:35 +0000735 if (MP_OBJ_IS_SMALL_INT(arg0)) {
Damien Georgeed9c93f2016-11-13 15:35:11 +1100736 push_result_node(parser, mp_parse_node_new_small_int(MP_OBJ_SMALL_INT_VALUE(arg0)));
Damien George22b22652016-01-07 14:40:35 +0000737 } else {
738 // TODO reuse memory for parse node struct?
739 push_result_node(parser, make_node_const_object(parser, 0, arg0));
740 }
Damien George64f2b212015-10-08 14:58:15 +0100741
742 return true;
743}
744#endif
745
Damien George16a6a472015-12-17 13:06:05 +0000746STATIC void push_result_rule(parser_t *parser, size_t src_line, const rule_t *rule, size_t num_args) {
Damien George93b37262016-01-07 13:07:52 +0000747 // optimise away parenthesis around an expression if possible
748 if (rule->rule_id == RULE_atom_paren) {
749 // there should be just 1 arg for this rule
750 mp_parse_node_t pn = peek_result(parser, 0);
751 if (MP_PARSE_NODE_IS_NULL(pn)) {
752 // need to keep parenthesis for ()
753 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, RULE_testlist_comp)) {
754 // need to keep parenthesis for (a, b, ...)
755 } else {
756 // parenthesis around a single expression, so it's just the expression
757 return;
758 }
759 }
760
Damien George64f2b212015-10-08 14:58:15 +0100761 #if MICROPY_COMP_CONST_FOLDING
Damien George9b525132016-11-13 15:36:49 +1100762 if (fold_logical_constants(parser, rule, &num_args)) {
763 // we folded this rule so return straight away
764 return;
765 }
Damien George64f2b212015-10-08 14:58:15 +0100766 if (fold_constants(parser, rule, num_args)) {
767 // we folded this rule so return straight away
768 return;
769 }
770 #endif
771
Damien George58e0f4a2015-09-23 10:50:43 +0100772 mp_parse_node_struct_t *pn = parser_alloc(parser, sizeof(mp_parse_node_struct_t) + sizeof(mp_parse_node_t) * num_args);
Damien George58ba4c32014-04-10 14:27:31 +0000773 if (pn == NULL) {
Damien George64f2b212015-10-08 14:58:15 +0100774 parser->parse_error = PARSE_ERROR_MEMORY;
Damien George58ba4c32014-04-10 14:27:31 +0000775 return;
776 }
777 pn->source_line = src_line;
778 pn->kind_num_nodes = (rule->rule_id & 0xff) | (num_args << 8);
Damien George16a6a472015-12-17 13:06:05 +0000779 for (size_t i = num_args; i > 0; i--) {
Damien429d7192013-10-04 19:53:11 +0100780 pn->nodes[i - 1] = pop_result(parser);
781 }
Damiend99b0522013-12-21 18:17:45 +0000782 push_result_node(parser, (mp_parse_node_t)pn);
Damien429d7192013-10-04 19:53:11 +0100783}
784
Damien George58e0f4a2015-09-23 10:50:43 +0100785mp_parse_tree_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind) {
Damien George69a818d2014-01-12 13:55:24 +0000786
Damien George1b82e9a2014-05-10 17:36:41 +0100787 // initialise parser and allocate memory for its stacks
Damien George69a818d2014-01-12 13:55:24 +0000788
Damien George1b82e9a2014-05-10 17:36:41 +0100789 parser_t parser;
Damien George69a818d2014-01-12 13:55:24 +0000790
Damien George64f2b212015-10-08 14:58:15 +0100791 parser.parse_error = PARSE_ERROR_NONE;
Damien George58ba4c32014-04-10 14:27:31 +0000792
Damien George58ebde42014-05-21 20:32:59 +0100793 parser.rule_stack_alloc = MICROPY_ALLOC_PARSE_RULE_INIT;
Damien George1b82e9a2014-05-10 17:36:41 +0100794 parser.rule_stack_top = 0;
795 parser.rule_stack = m_new_maybe(rule_stack_t, parser.rule_stack_alloc);
Damien429d7192013-10-04 19:53:11 +0100796
Damien George58ebde42014-05-21 20:32:59 +0100797 parser.result_stack_alloc = MICROPY_ALLOC_PARSE_RESULT_INIT;
Damien George1b82e9a2014-05-10 17:36:41 +0100798 parser.result_stack_top = 0;
799 parser.result_stack = m_new_maybe(mp_parse_node_t, parser.result_stack_alloc);
Damien429d7192013-10-04 19:53:11 +0100800
Damien George1b82e9a2014-05-10 17:36:41 +0100801 parser.lexer = lex;
802
Damien George58e0f4a2015-09-23 10:50:43 +0100803 parser.tree.chunk = NULL;
804 parser.cur_chunk = NULL;
805
Damien George64f2b212015-10-08 14:58:15 +0100806 #if MICROPY_COMP_CONST
807 mp_map_init(&parser.consts, 0);
808 #endif
809
Damien George1b82e9a2014-05-10 17:36:41 +0100810 // check if we could allocate the stacks
811 if (parser.rule_stack == NULL || parser.result_stack == NULL) {
812 goto memory_error;
813 }
Damien George08335002014-01-18 23:24:36 +0000814
Damien George69a818d2014-01-12 13:55:24 +0000815 // work out the top-level rule to use, and push it on the stack
Damien George16a6a472015-12-17 13:06:05 +0000816 size_t top_level_rule;
Damien5ac1b2e2013-10-18 19:58:12 +0100817 switch (input_kind) {
Damiend99b0522013-12-21 18:17:45 +0000818 case MP_PARSE_SINGLE_INPUT: top_level_rule = RULE_single_input; break;
Damien Georged02c6d82014-01-15 22:14:03 +0000819 case MP_PARSE_EVAL_INPUT: top_level_rule = RULE_eval_input; break;
Damien5ac1b2e2013-10-18 19:58:12 +0100820 default: top_level_rule = RULE_file_input;
821 }
Damien Georgea4c52c52014-12-05 19:35:18 +0000822 push_rule(&parser, lex->tok_line, rules[top_level_rule], 0);
Damien429d7192013-10-04 19:53:11 +0100823
Damien George69a818d2014-01-12 13:55:24 +0000824 // parse!
825
Damien George16a6a472015-12-17 13:06:05 +0000826 size_t n, i; // state for the current rule
827 size_t rule_src_line; // source line for the first token matched by the current rule
Damien429d7192013-10-04 19:53:11 +0100828 bool backtrack = false;
Damien George08335002014-01-18 23:24:36 +0000829 const rule_t *rule = NULL;
Damien429d7192013-10-04 19:53:11 +0100830
831 for (;;) {
832 next_rule:
Damien George64f2b212015-10-08 14:58:15 +0100833 if (parser.rule_stack_top == 0 || parser.parse_error) {
Damien429d7192013-10-04 19:53:11 +0100834 break;
835 }
836
Damien George1b82e9a2014-05-10 17:36:41 +0100837 pop_rule(&parser, &rule, &i, &rule_src_line);
Damien429d7192013-10-04 19:53:11 +0100838 n = rule->act & RULE_ACT_ARG_MASK;
839
840 /*
841 // debugging
Damien George1b82e9a2014-05-10 17:36:41 +0100842 printf("depth=%d ", parser.rule_stack_top);
843 for (int j = 0; j < parser.rule_stack_top; ++j) {
Damien429d7192013-10-04 19:53:11 +0100844 printf(" ");
845 }
846 printf("%s n=%d i=%d bt=%d\n", rule->rule_name, n, i, backtrack);
847 */
848
849 switch (rule->act & RULE_ACT_KIND_MASK) {
850 case RULE_ACT_OR:
851 if (i > 0 && !backtrack) {
852 goto next_rule;
853 } else {
854 backtrack = false;
855 }
Damien Georgefa7c61d2015-07-24 14:35:57 +0000856 for (; i < n; ++i) {
857 uint16_t kind = rule->arg[i] & RULE_ARG_KIND_MASK;
858 if (kind == RULE_ARG_TOK) {
859 if (lex->tok_kind == (rule->arg[i] & RULE_ARG_ARG_MASK)) {
Damien George6d310a52016-09-23 17:23:16 +1000860 push_result_token(&parser, rule);
Damien Georgefa7c61d2015-07-24 14:35:57 +0000861 mp_lexer_to_next(lex);
Damien429d7192013-10-04 19:53:11 +0100862 goto next_rule;
Damien Georgefa7c61d2015-07-24 14:35:57 +0000863 }
Damien429d7192013-10-04 19:53:11 +0100864 } else {
Damien Georgefa7c61d2015-07-24 14:35:57 +0000865 assert(kind == RULE_ARG_RULE);
866 if (i + 1 < n) {
867 push_rule(&parser, rule_src_line, rule, i + 1); // save this or-rule
868 }
869 push_rule_from_arg(&parser, rule->arg[i]); // push child of or-rule
Damien429d7192013-10-04 19:53:11 +0100870 goto next_rule;
871 }
Damien429d7192013-10-04 19:53:11 +0100872 }
Damien Georgefa7c61d2015-07-24 14:35:57 +0000873 backtrack = true;
Damien429d7192013-10-04 19:53:11 +0100874 break;
875
Damien George2870d852014-12-20 18:06:08 +0000876 case RULE_ACT_AND: {
Damien429d7192013-10-04 19:53:11 +0100877
878 // failed, backtrack if we can, else syntax error
879 if (backtrack) {
880 assert(i > 0);
881 if ((rule->arg[i - 1] & RULE_ARG_KIND_MASK) == RULE_ARG_OPT_RULE) {
882 // an optional rule that failed, so continue with next arg
Damien George1b82e9a2014-05-10 17:36:41 +0100883 push_result_node(&parser, MP_PARSE_NODE_NULL);
Damien429d7192013-10-04 19:53:11 +0100884 backtrack = false;
885 } else {
886 // a mandatory rule that failed, so propagate backtrack
887 if (i > 1) {
888 // already eaten tokens so can't backtrack
889 goto syntax_error;
890 } else {
891 goto next_rule;
892 }
893 }
894 }
895
896 // progress through the rule
897 for (; i < n; ++i) {
Damien George86e94232017-01-17 17:00:55 +1100898 if ((rule->arg[i] & RULE_ARG_KIND_MASK) == RULE_ARG_TOK) {
899 // need to match a token
900 mp_token_kind_t tok_kind = rule->arg[i] & RULE_ARG_ARG_MASK;
901 if (lex->tok_kind == tok_kind) {
902 // matched token
903 if (tok_kind == MP_TOKEN_NAME) {
904 push_result_token(&parser, rule);
Damien429d7192013-10-04 19:53:11 +0100905 }
Damien George86e94232017-01-17 17:00:55 +1100906 mp_lexer_to_next(lex);
907 } else {
908 // failed to match token
909 if (i > 0) {
910 // already eaten tokens so can't backtrack
911 goto syntax_error;
912 } else {
913 // this rule failed, so backtrack
914 backtrack = true;
915 goto next_rule;
916 }
Damien Georged2d64f02015-01-14 21:32:42 +0000917 }
Damien George86e94232017-01-17 17:00:55 +1100918 } else {
919 push_rule(&parser, rule_src_line, rule, i + 1); // save this and-rule
920 push_rule_from_arg(&parser, rule->arg[i]); // push child of and-rule
921 goto next_rule;
Damien429d7192013-10-04 19:53:11 +0100922 }
923 }
924
925 assert(i == n);
926
927 // matched the rule, so now build the corresponding parse_node
928
Damien George65dc9602015-08-14 12:24:11 +0100929 #if !MICROPY_ENABLE_DOC_STRING
Damien George5042bce2014-05-25 22:06:06 +0100930 // this code discards lonely statements, such as doc strings
Damien George1b82e9a2014-05-10 17:36:41 +0100931 if (input_kind != MP_PARSE_SINGLE_INPUT && rule->rule_id == RULE_expr_stmt && peek_result(&parser, 0) == MP_PARSE_NODE_NULL) {
932 mp_parse_node_t p = peek_result(&parser, 1);
Damien George5042bce2014-05-25 22:06:06 +0100933 if ((MP_PARSE_NODE_IS_LEAF(p) && !MP_PARSE_NODE_IS_ID(p)) || MP_PARSE_NODE_IS_STRUCT_KIND(p, RULE_string)) {
Damien George52b5d762014-09-23 15:31:56 +0000934 pop_result(&parser); // MP_PARSE_NODE_NULL
Damien George58e0f4a2015-09-23 10:50:43 +0100935 mp_parse_node_t pn = pop_result(&parser); // possibly RULE_string
936 if (MP_PARSE_NODE_IS_STRUCT(pn)) {
937 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t *)pn;
938 if (MP_PARSE_NODE_STRUCT_KIND(pns) == RULE_string) {
Damien George16a6a472015-12-17 13:06:05 +0000939 m_del(char, (char*)pns->nodes[0], (size_t)pns->nodes[1]);
Damien George58e0f4a2015-09-23 10:50:43 +0100940 }
941 }
Damien George1b82e9a2014-05-10 17:36:41 +0100942 push_result_rule(&parser, rule_src_line, rules[RULE_pass_stmt], 0);
Damien George93afa232014-05-06 21:44:11 +0100943 break;
944 }
945 }
Damien George65dc9602015-08-14 12:24:11 +0100946 #endif
Damien George93afa232014-05-06 21:44:11 +0100947
Damien George0c1de1c2016-04-14 13:23:50 +0100948 // count number of arguments for the parse node
949 i = 0;
Damien George16a6a472015-12-17 13:06:05 +0000950 size_t num_not_nil = 0;
Damien George0c1de1c2016-04-14 13:23:50 +0100951 for (size_t x = n; x > 0;) {
952 --x;
953 if ((rule->arg[x] & RULE_ARG_KIND_MASK) == RULE_ARG_TOK) {
954 mp_token_kind_t tok_kind = rule->arg[x] & RULE_ARG_ARG_MASK;
955 if (tok_kind == MP_TOKEN_NAME) {
956 // only tokens which were names are pushed to stack
957 i += 1;
958 num_not_nil += 1;
959 }
960 } else {
961 // rules are always pushed
962 if (peek_result(&parser, i) != MP_PARSE_NODE_NULL) {
963 num_not_nil += 1;
964 }
965 i += 1;
Damien429d7192013-10-04 19:53:11 +0100966 }
967 }
Damien George0c1de1c2016-04-14 13:23:50 +0100968
969 if (num_not_nil == 1 && (rule->act & RULE_ACT_ALLOW_IDENT)) {
970 // this rule has only 1 argument and should not be emitted
Damiend99b0522013-12-21 18:17:45 +0000971 mp_parse_node_t pn = MP_PARSE_NODE_NULL;
Damien George16a6a472015-12-17 13:06:05 +0000972 for (size_t x = 0; x < i; ++x) {
Damien George1b82e9a2014-05-10 17:36:41 +0100973 mp_parse_node_t pn2 = pop_result(&parser);
Damiend99b0522013-12-21 18:17:45 +0000974 if (pn2 != MP_PARSE_NODE_NULL) {
Damien429d7192013-10-04 19:53:11 +0100975 pn = pn2;
976 }
977 }
Damien George1b82e9a2014-05-10 17:36:41 +0100978 push_result_node(&parser, pn);
Damien George0c1de1c2016-04-14 13:23:50 +0100979 } else {
980 // this rule must be emitted
981
982 if (rule->act & RULE_ACT_ADD_BLANK) {
983 // and add an extra blank node at the end (used by the compiler to store data)
984 push_result_node(&parser, MP_PARSE_NODE_NULL);
985 i += 1;
986 }
987
988 push_result_rule(&parser, rule_src_line, rule, i);
Damien429d7192013-10-04 19:53:11 +0100989 }
990 break;
Damien George2870d852014-12-20 18:06:08 +0000991 }
Damien429d7192013-10-04 19:53:11 +0100992
Damien George86e94232017-01-17 17:00:55 +1100993 default: {
994 assert((rule->act & RULE_ACT_KIND_MASK) == RULE_ACT_LIST);
995
Damien429d7192013-10-04 19:53:11 +0100996 // n=2 is: item item*
997 // n=1 is: item (sep item)*
998 // n=3 is: item (sep item)* [sep]
Damien George2870d852014-12-20 18:06:08 +0000999 bool had_trailing_sep;
Damien429d7192013-10-04 19:53:11 +01001000 if (backtrack) {
1001 list_backtrack:
1002 had_trailing_sep = false;
1003 if (n == 2) {
1004 if (i == 1) {
1005 // fail on item, first time round; propagate backtrack
1006 goto next_rule;
1007 } else {
1008 // fail on item, in later rounds; finish with this rule
1009 backtrack = false;
1010 }
1011 } else {
1012 if (i == 1) {
1013 // fail on item, first time round; propagate backtrack
1014 goto next_rule;
1015 } else if ((i & 1) == 1) {
1016 // fail on item, in later rounds; have eaten tokens so can't backtrack
1017 if (n == 3) {
1018 // list allows trailing separator; finish parsing list
1019 had_trailing_sep = true;
1020 backtrack = false;
1021 } else {
1022 // list doesn't allowing trailing separator; fail
1023 goto syntax_error;
1024 }
1025 } else {
1026 // fail on separator; finish parsing list
1027 backtrack = false;
1028 }
1029 }
1030 } else {
1031 for (;;) {
Damien George16a6a472015-12-17 13:06:05 +00001032 size_t arg = rule->arg[i & 1 & n];
Damien George86e94232017-01-17 17:00:55 +11001033 if ((arg & RULE_ARG_KIND_MASK) == RULE_ARG_TOK) {
1034 if (lex->tok_kind == (arg & RULE_ARG_ARG_MASK)) {
1035 if (i & 1 & n) {
1036 // separators which are tokens are not pushed to result stack
Damien429d7192013-10-04 19:53:11 +01001037 } else {
Damien George86e94232017-01-17 17:00:55 +11001038 push_result_token(&parser, rule);
Damien429d7192013-10-04 19:53:11 +01001039 }
Damien George86e94232017-01-17 17:00:55 +11001040 mp_lexer_to_next(lex);
1041 // got element of list, so continue parsing list
1042 i += 1;
1043 } else {
1044 // couldn't get element of list
1045 i += 1;
1046 backtrack = true;
1047 goto list_backtrack;
1048 }
1049 } else {
1050 assert((arg & RULE_ARG_KIND_MASK) == RULE_ARG_RULE);
1051 push_rule(&parser, rule_src_line, rule, i + 1); // save this list-rule
1052 push_rule_from_arg(&parser, arg); // push child of list-rule
1053 goto next_rule;
Damien429d7192013-10-04 19:53:11 +01001054 }
1055 }
1056 }
1057 assert(i >= 1);
1058
1059 // compute number of elements in list, result in i
1060 i -= 1;
1061 if ((n & 1) && (rule->arg[1] & RULE_ARG_KIND_MASK) == RULE_ARG_TOK) {
1062 // don't count separators when they are tokens
1063 i = (i + 1) / 2;
1064 }
1065
1066 if (i == 1) {
1067 // list matched single item
1068 if (had_trailing_sep) {
1069 // if there was a trailing separator, make a list of a single item
Damien George1b82e9a2014-05-10 17:36:41 +01001070 push_result_rule(&parser, rule_src_line, rule, i);
Damien429d7192013-10-04 19:53:11 +01001071 } else {
1072 // just leave single item on stack (ie don't wrap in a list)
1073 }
1074 } else {
Damien George1b82e9a2014-05-10 17:36:41 +01001075 push_result_rule(&parser, rule_src_line, rule, i);
Damien429d7192013-10-04 19:53:11 +01001076 }
1077 break;
Damien George2870d852014-12-20 18:06:08 +00001078 }
Damien429d7192013-10-04 19:53:11 +01001079 }
1080 }
Damien91d387d2013-10-09 15:09:52 +01001081
Damien George64f2b212015-10-08 14:58:15 +01001082 #if MICROPY_COMP_CONST
1083 mp_map_deinit(&parser.consts);
1084 #endif
1085
Damien George58e0f4a2015-09-23 10:50:43 +01001086 // truncate final chunk and link into chain of chunks
1087 if (parser.cur_chunk != NULL) {
Colin Hogbenf9b6b372016-10-31 14:05:56 +00001088 (void)m_renew_maybe(byte, parser.cur_chunk,
Damien George58e0f4a2015-09-23 10:50:43 +01001089 sizeof(mp_parse_chunk_t) + parser.cur_chunk->alloc,
Colin Hogbenf9b6b372016-10-31 14:05:56 +00001090 sizeof(mp_parse_chunk_t) + parser.cur_chunk->union_.used,
1091 false);
Damien George58e0f4a2015-09-23 10:50:43 +01001092 parser.cur_chunk->alloc = parser.cur_chunk->union_.used;
1093 parser.cur_chunk->union_.next = parser.tree.chunk;
1094 parser.tree.chunk = parser.cur_chunk;
1095 }
1096
Damien Georgef8048332015-02-08 13:40:20 +00001097 mp_obj_t exc;
Damien George58ba4c32014-04-10 14:27:31 +00001098
Damien George64f2b212015-10-08 14:58:15 +01001099 if (parser.parse_error) {
1100 #if MICROPY_COMP_CONST
1101 if (parser.parse_error == PARSE_ERROR_CONST) {
1102 exc = mp_obj_new_exception_msg(&mp_type_SyntaxError,
1103 "constant must be an integer");
1104 } else
1105 #endif
1106 {
1107 assert(parser.parse_error == PARSE_ERROR_MEMORY);
1108 memory_error:
1109 exc = mp_obj_new_exception_msg(&mp_type_MemoryError,
1110 "parser could not allocate enough memory");
1111 }
Damien George58e0f4a2015-09-23 10:50:43 +01001112 parser.tree.root = MP_PARSE_NODE_NULL;
Damien Georgefdfcee72015-10-12 12:59:18 +01001113 } else if (
1114 lex->tok_kind != MP_TOKEN_END // check we are at the end of the token stream
1115 || parser.result_stack_top == 0 // check that we got a node (can fail on empty input)
1116 ) {
1117 syntax_error:
1118 if (lex->tok_kind == MP_TOKEN_INDENT) {
1119 exc = mp_obj_new_exception_msg(&mp_type_IndentationError,
1120 "unexpected indent");
1121 } else if (lex->tok_kind == MP_TOKEN_DEDENT_MISMATCH) {
1122 exc = mp_obj_new_exception_msg(&mp_type_IndentationError,
1123 "unindent does not match any outer indentation level");
1124 } else {
1125 exc = mp_obj_new_exception_msg(&mp_type_SyntaxError,
1126 "invalid syntax");
1127 }
1128 parser.tree.root = MP_PARSE_NODE_NULL;
1129 } else {
1130 // no errors
1131
1132 //result_stack_show(parser);
1133 //printf("rule stack alloc: %d\n", parser.rule_stack_alloc);
1134 //printf("result stack alloc: %d\n", parser.result_stack_alloc);
1135 //printf("number of parse nodes allocated: %d\n", num_parse_nodes_allocated);
1136
1137 // get the root parse node that we created
1138 assert(parser.result_stack_top == 1);
1139 exc = MP_OBJ_NULL;
1140 parser.tree.root = parser.result_stack[0];
Damien George58ba4c32014-04-10 14:27:31 +00001141 }
1142
Damien George69a818d2014-01-12 13:55:24 +00001143 // free the memory that we don't need anymore
Damien George1b82e9a2014-05-10 17:36:41 +01001144 m_del(rule_stack_t, parser.rule_stack, parser.rule_stack_alloc);
1145 m_del(mp_parse_node_t, parser.result_stack, parser.result_stack_alloc);
Damien George0bfc7632015-02-07 18:33:58 +00001146 // we also free the lexer on behalf of the caller (see below)
Damien George69a818d2014-01-12 13:55:24 +00001147
Damien George0bfc7632015-02-07 18:33:58 +00001148 if (exc != MP_OBJ_NULL) {
1149 // had an error so raise the exception
1150 // add traceback to give info about file name and location
1151 // we don't have a 'block' name, so just pass the NULL qstr to indicate this
1152 mp_obj_exception_add_traceback(exc, lex->source_name, lex->tok_line, MP_QSTR_NULL);
1153 mp_lexer_free(lex);
1154 nlr_raise(exc);
1155 } else {
1156 mp_lexer_free(lex);
Damien George58e0f4a2015-09-23 10:50:43 +01001157 return parser.tree;
Damien George0bfc7632015-02-07 18:33:58 +00001158 }
Damien429d7192013-10-04 19:53:11 +01001159}
Damien George58e0f4a2015-09-23 10:50:43 +01001160
1161void mp_parse_tree_clear(mp_parse_tree_t *tree) {
1162 mp_parse_chunk_t *chunk = tree->chunk;
1163 while (chunk != NULL) {
1164 mp_parse_chunk_t *next = chunk->union_.next;
1165 m_del(byte, chunk, sizeof(mp_parse_chunk_t) + chunk->alloc);
1166 chunk = next;
1167 }
1168}
Damien Georgedd5353a2015-12-18 12:35:44 +00001169
1170#endif // MICROPY_ENABLE_COMPILER