Numworks Epsilon  1.4.1
Graphing Calculator Operating System
parse.c
Go to the documentation of this file.
1 /*
2  * This file is part of the MicroPython project, http://micropython.org/
3  *
4  * The MIT License (MIT)
5  *
6  * Copyright (c) 2013-2015 Damien P. George
7  *
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 
27 #include <stdbool.h>
28 #include <stdint.h>
29 #include <stdio.h>
30 #include <unistd.h> // for ssize_t
31 #include <assert.h>
32 #include <string.h>
33 
34 #include "py/lexer.h"
35 #include "py/parse.h"
36 #include "py/parsenum.h"
37 #include "py/runtime.h"
38 #include "py/objint.h"
39 #include "py/objstr.h"
40 #include "py/builtin.h"
41 
42 #if MICROPY_ENABLE_COMPILER
43 
44 #define RULE_ACT_ARG_MASK (0x0f)
45 #define RULE_ACT_KIND_MASK (0x30)
46 #define RULE_ACT_ALLOW_IDENT (0x40)
47 #define RULE_ACT_ADD_BLANK (0x80)
48 #define RULE_ACT_OR (0x10)
49 #define RULE_ACT_AND (0x20)
50 #define RULE_ACT_LIST (0x30)
51 
52 #define RULE_ARG_KIND_MASK (0xf000)
53 #define RULE_ARG_ARG_MASK (0x0fff)
54 #define RULE_ARG_TOK (0x1000)
55 #define RULE_ARG_RULE (0x2000)
56 #define RULE_ARG_OPT_RULE (0x3000)
57 
58 // (un)comment to use rule names; for debugging
59 //#define USE_RULE_NAME (1)
60 
61 typedef struct _rule_t {
62  byte rule_id;
63  byte act;
64 #ifdef USE_RULE_NAME
65  const char *rule_name;
66 #endif
67  uint16_t arg[];
68 } rule_t;
69 
70 enum {
71 // define rules with a compile function
72 #define DEF_RULE(rule, comp, kind, ...) RULE_##rule,
73 #define DEF_RULE_NC(rule, kind, ...)
74 #include "py/grammar.h"
75 #undef DEF_RULE
76 #undef DEF_RULE_NC
77  RULE_const_object, // special node for a constant, generic Python object
78 
79 // define rules without a compile function
80 #define DEF_RULE(rule, comp, kind, ...)
81 #define DEF_RULE_NC(rule, kind, ...) RULE_##rule,
82 #include "py/grammar.h"
83 #undef DEF_RULE
84 #undef DEF_RULE_NC
85 };
86 
87 #define or(n) (RULE_ACT_OR | n)
88 #define and(n) (RULE_ACT_AND | n)
89 #define and_ident(n) (RULE_ACT_AND | n | RULE_ACT_ALLOW_IDENT)
90 #define and_blank(n) (RULE_ACT_AND | n | RULE_ACT_ADD_BLANK)
91 #define one_or_more (RULE_ACT_LIST | 2)
92 #define list (RULE_ACT_LIST | 1)
93 #define list_with_end (RULE_ACT_LIST | 3)
94 #define tok(t) (RULE_ARG_TOK | MP_TOKEN_##t)
95 #define rule(r) (RULE_ARG_RULE | RULE_##r)
96 #define opt_rule(r) (RULE_ARG_OPT_RULE | RULE_##r)
97 #ifdef USE_RULE_NAME
98 #define DEF_RULE(rule, comp, kind, ...) static const rule_t rule_##rule = { RULE_##rule, kind, #rule, { __VA_ARGS__ } };
99 #define DEF_RULE_NC(rule, kind, ...) static const rule_t rule_##rule = { RULE_##rule, kind, #rule, { __VA_ARGS__ } };
100 #else
101 #define DEF_RULE(rule, comp, kind, ...) static const rule_t rule_##rule = { RULE_##rule, kind, { __VA_ARGS__ } };
102 #define DEF_RULE_NC(rule, kind, ...) static const rule_t rule_##rule = { RULE_##rule, kind, { __VA_ARGS__ } };
103 #endif
104 #include "py/grammar.h"
105 #undef or
106 #undef and
107 #undef list
108 #undef list_with_end
109 #undef tok
110 #undef rule
111 #undef opt_rule
112 #undef one_or_more
113 #undef DEF_RULE
114 #undef DEF_RULE_NC
115 
116 STATIC const rule_t *const rules[] = {
117 // define rules with a compile function
118 #define DEF_RULE(rule, comp, kind, ...) &rule_##rule,
119 #define DEF_RULE_NC(rule, kind, ...)
120 #include "py/grammar.h"
121 #undef DEF_RULE
122 #undef DEF_RULE_NC
123  NULL, // RULE_const_object
124 
125 // define rules without a compile function
126 #define DEF_RULE(rule, comp, kind, ...)
127 #define DEF_RULE_NC(rule, kind, ...) &rule_##rule,
128 #include "py/grammar.h"
129 #undef DEF_RULE
130 #undef DEF_RULE_NC
131 };
132 
133 typedef struct _rule_stack_t {
134  size_t src_line : 8 * sizeof(size_t) - 8; // maximum bits storing source line number
135  size_t rule_id : 8; // this must be large enough to fit largest rule number
136  size_t arg_i; // this dictates the maximum nodes in a "list" of things
137 } rule_stack_t;
138 
139 typedef struct _mp_parse_chunk_t {
140  size_t alloc;
141  union {
142  size_t used;
143  struct _mp_parse_chunk_t *next;
144  } union_;
145  byte data[];
146 } mp_parse_chunk_t;
147 
148 typedef struct _parser_t {
149  size_t rule_stack_alloc;
150  size_t rule_stack_top;
151  rule_stack_t *rule_stack;
152 
153  size_t result_stack_alloc;
154  size_t result_stack_top;
155  mp_parse_node_t *result_stack;
156 
157  mp_lexer_t *lexer;
158 
159  mp_parse_tree_t tree;
160  mp_parse_chunk_t *cur_chunk;
161 
162  #if MICROPY_COMP_CONST
163  mp_map_t consts;
164  #endif
165 } parser_t;
166 
167 STATIC void *parser_alloc(parser_t *parser, size_t num_bytes) {
168  // use a custom memory allocator to store parse nodes sequentially in large chunks
169 
170  mp_parse_chunk_t *chunk = parser->cur_chunk;
171 
172  if (chunk != NULL && chunk->union_.used + num_bytes > chunk->alloc) {
173  // not enough room at end of previously allocated chunk so try to grow
174  mp_parse_chunk_t *new_data = (mp_parse_chunk_t*)m_renew_maybe(byte, chunk,
175  sizeof(mp_parse_chunk_t) + chunk->alloc,
176  sizeof(mp_parse_chunk_t) + chunk->alloc + num_bytes, false);
177  if (new_data == NULL) {
178  // could not grow existing memory; shrink it to fit previous
179  (void)m_renew_maybe(byte, chunk, sizeof(mp_parse_chunk_t) + chunk->alloc,
180  sizeof(mp_parse_chunk_t) + chunk->union_.used, false);
181  chunk->alloc = chunk->union_.used;
182  chunk->union_.next = parser->tree.chunk;
183  parser->tree.chunk = chunk;
184  chunk = NULL;
185  } else {
186  // could grow existing memory
187  chunk->alloc += num_bytes;
188  }
189  }
190 
191  if (chunk == NULL) {
192  // no previous chunk, allocate a new chunk
193  size_t alloc = MICROPY_ALLOC_PARSE_CHUNK_INIT;
194  if (alloc < num_bytes) {
195  alloc = num_bytes;
196  }
197  chunk = (mp_parse_chunk_t*)m_new(byte, sizeof(mp_parse_chunk_t) + alloc);
198  chunk->alloc = alloc;
199  chunk->union_.used = 0;
200  parser->cur_chunk = chunk;
201  }
202 
203  byte *ret = chunk->data + chunk->union_.used;
204  chunk->union_.used += num_bytes;
205  return ret;
206 }
207 
208 STATIC void push_rule(parser_t *parser, size_t src_line, const rule_t *rule, size_t arg_i) {
209  if (parser->rule_stack_top >= parser->rule_stack_alloc) {
210  rule_stack_t *rs = m_renew(rule_stack_t, parser->rule_stack, parser->rule_stack_alloc, parser->rule_stack_alloc + MICROPY_ALLOC_PARSE_RULE_INC);
211  parser->rule_stack = rs;
212  parser->rule_stack_alloc += MICROPY_ALLOC_PARSE_RULE_INC;
213  }
214  rule_stack_t *rs = &parser->rule_stack[parser->rule_stack_top++];
215  rs->src_line = src_line;
216  rs->rule_id = rule->rule_id;
217  rs->arg_i = arg_i;
218 }
219 
220 STATIC void push_rule_from_arg(parser_t *parser, size_t arg) {
221  assert((arg & RULE_ARG_KIND_MASK) == RULE_ARG_RULE || (arg & RULE_ARG_KIND_MASK) == RULE_ARG_OPT_RULE);
222  size_t rule_id = arg & RULE_ARG_ARG_MASK;
223  push_rule(parser, parser->lexer->tok_line, rules[rule_id], 0);
224 }
225 
226 STATIC void pop_rule(parser_t *parser, const rule_t **rule, size_t *arg_i, size_t *src_line) {
227  parser->rule_stack_top -= 1;
228  *rule = rules[parser->rule_stack[parser->rule_stack_top].rule_id];
229  *arg_i = parser->rule_stack[parser->rule_stack_top].arg_i;
230  *src_line = parser->rule_stack[parser->rule_stack_top].src_line;
231 }
232 
236 }
237 
241 }
242 
244  if (MP_PARSE_NODE_IS_SMALL_INT(pn)) {
246  return true;
247  } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, RULE_const_object)) {
249  #if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_D
250  // nodes are 32-bit pointers, but need to extract 64-bit object
251  *o = (uint64_t)pns->nodes[0] | ((uint64_t)pns->nodes[1] << 32);
252  #else
253  *o = (mp_obj_t)pns->nodes[0];
254  #endif
255  return MP_OBJ_IS_INT(*o);
256  } else {
257  return false;
258  }
259 }
260 
261 int mp_parse_node_extract_list(mp_parse_node_t *pn, size_t pn_kind, mp_parse_node_t **nodes) {
262  if (MP_PARSE_NODE_IS_NULL(*pn)) {
263  *nodes = NULL;
264  return 0;
265  } else if (MP_PARSE_NODE_IS_LEAF(*pn)) {
266  *nodes = pn;
267  return 1;
268  } else {
270  if (MP_PARSE_NODE_STRUCT_KIND(pns) != pn_kind) {
271  *nodes = pn;
272  return 1;
273  } else {
274  *nodes = pns->nodes;
275  return MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
276  }
277  }
278 }
279 
280 #if MICROPY_DEBUG_PRINTERS
281 void mp_parse_node_print(mp_parse_node_t pn, size_t indent) {
282  if (MP_PARSE_NODE_IS_STRUCT(pn)) {
283  printf("[% 4d] ", (int)((mp_parse_node_struct_t*)pn)->source_line);
284  } else {
285  printf(" ");
286  }
287  for (size_t i = 0; i < indent; i++) {
288  printf(" ");
289  }
290  if (MP_PARSE_NODE_IS_NULL(pn)) {
291  printf("NULL\n");
292  } else if (MP_PARSE_NODE_IS_SMALL_INT(pn)) {
294  printf("int(" INT_FMT ")\n", arg);
295  } else if (MP_PARSE_NODE_IS_LEAF(pn)) {
297  switch (MP_PARSE_NODE_LEAF_KIND(pn)) {
298  case MP_PARSE_NODE_ID: printf("id(%s)\n", qstr_str(arg)); break;
299  case MP_PARSE_NODE_STRING: printf("str(%s)\n", qstr_str(arg)); break;
300  case MP_PARSE_NODE_BYTES: printf("bytes(%s)\n", qstr_str(arg)); break;
301  default:
303  printf("tok(%u)\n", (uint)arg); break;
304  }
305  } else {
306  // node must be a mp_parse_node_struct_t
308  if (MP_PARSE_NODE_STRUCT_KIND(pns) == RULE_const_object) {
309  #if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_D
310  printf("literal const(%016llx)\n", (uint64_t)pns->nodes[0] | ((uint64_t)pns->nodes[1] << 32));
311  #else
312  printf("literal const(%p)\n", (mp_obj_t)pns->nodes[0]);
313  #endif
314  } else {
315  size_t n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
316 #ifdef USE_RULE_NAME
317  printf("%s(%u) (n=%u)\n", rules[MP_PARSE_NODE_STRUCT_KIND(pns)]->rule_name, (uint)MP_PARSE_NODE_STRUCT_KIND(pns), (uint)n);
318 #else
319  printf("rule(%u) (n=%u)\n", (uint)MP_PARSE_NODE_STRUCT_KIND(pns), (uint)n);
320 #endif
321  for (size_t i = 0; i < n; i++) {
322  mp_parse_node_print(pns->nodes[i], indent + 2);
323  }
324  }
325  }
326 }
327 #endif // MICROPY_DEBUG_PRINTERS
328 
329 /*
330 STATIC void result_stack_show(parser_t *parser) {
331  printf("result stack, most recent first\n");
332  for (ssize_t i = parser->result_stack_top - 1; i >= 0; i--) {
333  mp_parse_node_print(parser->result_stack[i], 0);
334  }
335 }
336 */
337 
338 STATIC mp_parse_node_t pop_result(parser_t *parser) {
339  assert(parser->result_stack_top > 0);
340  return parser->result_stack[--parser->result_stack_top];
341 }
342 
343 STATIC mp_parse_node_t peek_result(parser_t *parser, size_t pos) {
344  assert(parser->result_stack_top > pos);
345  return parser->result_stack[parser->result_stack_top - 1 - pos];
346 }
347 
348 STATIC void push_result_node(parser_t *parser, mp_parse_node_t pn) {
349  if (parser->result_stack_top >= parser->result_stack_alloc) {
350  mp_parse_node_t *stack = m_renew(mp_parse_node_t, parser->result_stack, parser->result_stack_alloc, parser->result_stack_alloc + MICROPY_ALLOC_PARSE_RESULT_INC);
351  parser->result_stack = stack;
352  parser->result_stack_alloc += MICROPY_ALLOC_PARSE_RESULT_INC;
353  }
354  parser->result_stack[parser->result_stack_top++] = pn;
355 }
356 
357 STATIC mp_parse_node_t make_node_const_object(parser_t *parser, size_t src_line, mp_obj_t obj) {
358  mp_parse_node_struct_t *pn = parser_alloc(parser, sizeof(mp_parse_node_struct_t) + sizeof(mp_obj_t));
359  pn->source_line = src_line;
360  #if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_D
361  // nodes are 32-bit pointers, but need to store 64-bit object
362  pn->kind_num_nodes = RULE_const_object | (2 << 8);
363  pn->nodes[0] = (uint64_t)obj;
364  pn->nodes[1] = (uint64_t)obj >> 32;
365  #else
366  pn->kind_num_nodes = RULE_const_object | (1 << 8);
367  pn->nodes[0] = (uintptr_t)obj;
368  #endif
369  return (mp_parse_node_t)pn;
370 }
371 
372 STATIC void push_result_token(parser_t *parser, const rule_t *rule) {
373  mp_parse_node_t pn;
374  mp_lexer_t *lex = parser->lexer;
375  if (lex->tok_kind == MP_TOKEN_NAME) {
376  qstr id = qstr_from_strn(lex->vstr.buf, lex->vstr.len);
377  #if MICROPY_COMP_CONST
378  // if name is a standalone identifier, look it up in the table of dynamic constants
379  mp_map_elem_t *elem;
380  if (rule->rule_id == RULE_atom
381  && (elem = mp_map_lookup(&parser->consts, MP_OBJ_NEW_QSTR(id), MP_MAP_LOOKUP)) != NULL) {
382  if (MP_OBJ_IS_SMALL_INT(elem->value)) {
383  pn = mp_parse_node_new_small_int(MP_OBJ_SMALL_INT_VALUE(elem->value));
384  } else {
385  pn = make_node_const_object(parser, lex->tok_line, elem->value);
386  }
387  } else {
388  pn = mp_parse_node_new_leaf(MP_PARSE_NODE_ID, id);
389  }
390  #else
391  (void)rule;
392  pn = mp_parse_node_new_leaf(MP_PARSE_NODE_ID, id);
393  #endif
394  } else if (lex->tok_kind == MP_TOKEN_INTEGER) {
395  mp_obj_t o = mp_parse_num_integer(lex->vstr.buf, lex->vstr.len, 0, lex);
396  if (MP_OBJ_IS_SMALL_INT(o)) {
397  pn = mp_parse_node_new_small_int(MP_OBJ_SMALL_INT_VALUE(o));
398  } else {
399  pn = make_node_const_object(parser, lex->tok_line, o);
400  }
401  } else if (lex->tok_kind == MP_TOKEN_FLOAT_OR_IMAG) {
402  mp_obj_t o = mp_parse_num_decimal(lex->vstr.buf, lex->vstr.len, true, false, lex);
403  pn = make_node_const_object(parser, lex->tok_line, o);
404  } else if (lex->tok_kind == MP_TOKEN_STRING || lex->tok_kind == MP_TOKEN_BYTES) {
405  // Don't automatically intern all strings/bytes. doc strings (which are usually large)
406  // will be discarded by the compiler, and so we shouldn't intern them.
407  qstr qst = MP_QSTR_NULL;
409  // intern short strings
410  qst = qstr_from_strn(lex->vstr.buf, lex->vstr.len);
411  } else {
412  // check if this string is already interned
413  qst = qstr_find_strn(lex->vstr.buf, lex->vstr.len);
414  }
415  if (qst != MP_QSTR_NULL) {
416  // qstr exists, make a leaf node
417  pn = mp_parse_node_new_leaf(lex->tok_kind == MP_TOKEN_STRING ? MP_PARSE_NODE_STRING : MP_PARSE_NODE_BYTES, qst);
418  } else {
419  // not interned, make a node holding a pointer to the string/bytes object
422  (const byte*)lex->vstr.buf, lex->vstr.len);
423  pn = make_node_const_object(parser, lex->tok_line, o);
424  }
425  } else {
426  pn = mp_parse_node_new_leaf(MP_PARSE_NODE_TOKEN, lex->tok_kind);
427  }
428  push_result_node(parser, pn);
429 }
430 
431 #if MICROPY_COMP_MODULE_CONST
432 STATIC const mp_rom_map_elem_t mp_constants_table[] = {
433  #if MICROPY_PY_UERRNO
434  { MP_ROM_QSTR(MP_QSTR_errno), MP_ROM_PTR(&mp_module_uerrno) },
435  #endif
436  #if MICROPY_PY_UCTYPES
437  { MP_ROM_QSTR(MP_QSTR_uctypes), MP_ROM_PTR(&mp_module_uctypes) },
438  #endif
439  // Extra constants as defined by a port
441 };
442 STATIC MP_DEFINE_CONST_MAP(mp_constants_map, mp_constants_table);
443 #endif
444 
445 STATIC void push_result_rule(parser_t *parser, size_t src_line, const rule_t *rule, size_t num_args);
446 
447 #if MICROPY_COMP_CONST_FOLDING
448 STATIC bool fold_logical_constants(parser_t *parser, const rule_t *rule, size_t *num_args) {
449  if (rule->rule_id == RULE_or_test
450  || rule->rule_id == RULE_and_test) {
451  // folding for binary logical ops: or and
452  size_t copy_to = *num_args;
453  for (size_t i = copy_to; i > 0;) {
454  mp_parse_node_t pn = peek_result(parser, --i);
455  parser->result_stack[parser->result_stack_top - copy_to] = pn;
456  if (i == 0) {
457  // always need to keep the last value
458  break;
459  }
460  if (rule->rule_id == RULE_or_test) {
461  if (mp_parse_node_is_const_true(pn)) {
462  //
463  break;
464  } else if (!mp_parse_node_is_const_false(pn)) {
465  copy_to -= 1;
466  }
467  } else {
468  // RULE_and_test
470  break;
471  } else if (!mp_parse_node_is_const_true(pn)) {
472  copy_to -= 1;
473  }
474  }
475  }
476  copy_to -= 1; // copy_to now contains number of args to pop
477 
478  // pop and discard all the short-circuited expressions
479  for (size_t i = 0; i < copy_to; ++i) {
480  pop_result(parser);
481  }
482  *num_args -= copy_to;
483 
484  // we did a complete folding if there's only 1 arg left
485  return *num_args == 1;
486 
487  } else if (rule->rule_id == RULE_not_test_2) {
488  // folding for unary logical op: not
489  mp_parse_node_t pn = peek_result(parser, 0);
491  pn = mp_parse_node_new_leaf(MP_PARSE_NODE_TOKEN, MP_TOKEN_KW_TRUE);
492  } else if (mp_parse_node_is_const_true(pn)) {
493  pn = mp_parse_node_new_leaf(MP_PARSE_NODE_TOKEN, MP_TOKEN_KW_FALSE);
494  } else {
495  return false;
496  }
497  pop_result(parser);
498  push_result_node(parser, pn);
499  return true;
500  }
501 
502  return false;
503 }
504 
505 STATIC bool fold_constants(parser_t *parser, const rule_t *rule, size_t num_args) {
506  // this code does folding of arbitrary integer expressions, eg 1 + 2 * 3 + 4
507  // it does not do partial folding, eg 1 + 2 + x -> 3 + x
508 
509  mp_obj_t arg0;
510  if (rule->rule_id == RULE_expr
511  || rule->rule_id == RULE_xor_expr
512  || rule->rule_id == RULE_and_expr) {
513  // folding for binary ops: | ^ &
514  mp_parse_node_t pn = peek_result(parser, num_args - 1);
515  if (!mp_parse_node_get_int_maybe(pn, &arg0)) {
516  return false;
517  }
518  mp_binary_op_t op;
519  if (rule->rule_id == RULE_expr) {
520  op = MP_BINARY_OP_OR;
521  } else if (rule->rule_id == RULE_xor_expr) {
522  op = MP_BINARY_OP_XOR;
523  } else {
524  op = MP_BINARY_OP_AND;
525  }
526  for (ssize_t i = num_args - 2; i >= 0; --i) {
527  pn = peek_result(parser, i);
528  mp_obj_t arg1;
529  if (!mp_parse_node_get_int_maybe(pn, &arg1)) {
530  return false;
531  }
532  arg0 = mp_binary_op(op, arg0, arg1);
533  }
534  } else if (rule->rule_id == RULE_shift_expr
535  || rule->rule_id == RULE_arith_expr
536  || rule->rule_id == RULE_term) {
537  // folding for binary ops: << >> + - * / % //
538  mp_parse_node_t pn = peek_result(parser, num_args - 1);
539  if (!mp_parse_node_get_int_maybe(pn, &arg0)) {
540  return false;
541  }
542  for (ssize_t i = num_args - 2; i >= 1; i -= 2) {
543  pn = peek_result(parser, i - 1);
544  mp_obj_t arg1;
545  if (!mp_parse_node_get_int_maybe(pn, &arg1)) {
546  return false;
547  }
549  static const uint8_t token_to_op[] = {
553  255,//MP_BINARY_OP_POWER,
554  255,//MP_BINARY_OP_TRUE_DIVIDE,
557  255,//MP_BINARY_OP_LESS
559  255,//MP_BINARY_OP_MORE
561  };
562  mp_binary_op_t op = token_to_op[tok - MP_TOKEN_OP_PLUS];
563  if (op == (mp_binary_op_t)255) {
564  return false;
565  }
566  int rhs_sign = mp_obj_int_sign(arg1);
567  if (op <= MP_BINARY_OP_RSHIFT) {
568  // << and >> can't have negative rhs
569  if (rhs_sign < 0) {
570  return false;
571  }
572  } else if (op >= MP_BINARY_OP_FLOOR_DIVIDE) {
573  // % and // can't have zero rhs
574  if (rhs_sign == 0) {
575  return false;
576  }
577  }
578  arg0 = mp_binary_op(op, arg0, arg1);
579  }
580  } else if (rule->rule_id == RULE_factor_2) {
581  // folding for unary ops: + - ~
582  mp_parse_node_t pn = peek_result(parser, 0);
583  if (!mp_parse_node_get_int_maybe(pn, &arg0)) {
584  return false;
585  }
587  mp_unary_op_t op;
588  if (tok == MP_TOKEN_OP_PLUS) {
590  } else if (tok == MP_TOKEN_OP_MINUS) {
592  } else {
593  assert(tok == MP_TOKEN_OP_TILDE); // should be
594  op = MP_UNARY_OP_INVERT;
595  }
596  arg0 = mp_unary_op(op, arg0);
597 
598  #if MICROPY_COMP_CONST
599  } else if (rule->rule_id == RULE_expr_stmt) {
600  mp_parse_node_t pn1 = peek_result(parser, 0);
601  if (!MP_PARSE_NODE_IS_NULL(pn1)
602  && !(MP_PARSE_NODE_IS_STRUCT_KIND(pn1, RULE_expr_stmt_augassign)
603  || MP_PARSE_NODE_IS_STRUCT_KIND(pn1, RULE_expr_stmt_assign_list))) {
604  // this node is of the form <x> = <y>
605  mp_parse_node_t pn0 = peek_result(parser, 1);
606  if (MP_PARSE_NODE_IS_ID(pn0)
607  && MP_PARSE_NODE_IS_STRUCT_KIND(pn1, RULE_atom_expr_normal)
608  && MP_PARSE_NODE_IS_ID(((mp_parse_node_struct_t*)pn1)->nodes[0])
609  && MP_PARSE_NODE_LEAF_ARG(((mp_parse_node_struct_t*)pn1)->nodes[0]) == MP_QSTR_const
610  && MP_PARSE_NODE_IS_STRUCT_KIND(((mp_parse_node_struct_t*)pn1)->nodes[1], RULE_trailer_paren)
611  ) {
612  // code to assign dynamic constants: id = const(value)
613 
614  // get the id
615  qstr id = MP_PARSE_NODE_LEAF_ARG(pn0);
616 
617  // get the value
618  mp_parse_node_t pn_value = ((mp_parse_node_struct_t*)((mp_parse_node_struct_t*)pn1)->nodes[1])->nodes[0];
619  mp_obj_t value;
620  if (!mp_parse_node_get_int_maybe(pn_value, &value)) {
622  "constant must be an integer");
623  mp_obj_exception_add_traceback(exc, parser->lexer->source_name,
624  ((mp_parse_node_struct_t*)pn1)->source_line, MP_QSTR_NULL);
625  nlr_raise(exc);
626  }
627 
628  // store the value in the table of dynamic constants
630  assert(elem->value == MP_OBJ_NULL);
631  elem->value = value;
632 
633  // If the constant starts with an underscore then treat it as a private
634  // variable and don't emit any code to store the value to the id.
635  if (qstr_str(id)[0] == '_') {
636  pop_result(parser); // pop const(value)
637  pop_result(parser); // pop id
638  push_result_rule(parser, 0, rules[RULE_pass_stmt], 0); // replace with "pass"
639  return true;
640  }
641 
642  // replace const(value) with value
643  pop_result(parser);
644  push_result_node(parser, pn_value);
645 
646  // finished folding this assignment, but we still want it to be part of the tree
647  return false;
648  }
649  }
650  return false;
651  #endif
652 
653  #if MICROPY_COMP_MODULE_CONST
654  } else if (rule->rule_id == RULE_atom_expr_normal) {
655  mp_parse_node_t pn0 = peek_result(parser, 1);
656  mp_parse_node_t pn1 = peek_result(parser, 0);
657  if (!(MP_PARSE_NODE_IS_ID(pn0)
658  && MP_PARSE_NODE_IS_STRUCT_KIND(pn1, RULE_trailer_period))) {
659  return false;
660  }
661  // id1.id2
662  // look it up in constant table, see if it can be replaced with an integer
664  assert(MP_PARSE_NODE_IS_ID(pns1->nodes[0]));
665  qstr q_base = MP_PARSE_NODE_LEAF_ARG(pn0);
666  qstr q_attr = MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0]);
667  mp_map_elem_t *elem = mp_map_lookup((mp_map_t*)&mp_constants_map, MP_OBJ_NEW_QSTR(q_base), MP_MAP_LOOKUP);
668  if (elem == NULL) {
669  return false;
670  }
671  mp_obj_t dest[2];
672  mp_load_method_maybe(elem->value, q_attr, dest);
673  if (!(dest[0] != MP_OBJ_NULL && MP_OBJ_IS_INT(dest[0]) && dest[1] == MP_OBJ_NULL)) {
674  return false;
675  }
676  arg0 = dest[0];
677  #endif
678 
679  } else {
680  return false;
681  }
682 
683  // success folding this rule
684 
685  for (size_t i = num_args; i > 0; i--) {
686  pop_result(parser);
687  }
688  if (MP_OBJ_IS_SMALL_INT(arg0)) {
689  push_result_node(parser, mp_parse_node_new_small_int(MP_OBJ_SMALL_INT_VALUE(arg0)));
690  } else {
691  // TODO reuse memory for parse node struct?
692  push_result_node(parser, make_node_const_object(parser, 0, arg0));
693  }
694 
695  return true;
696 }
697 #endif
698 
699 STATIC void push_result_rule(parser_t *parser, size_t src_line, const rule_t *rule, size_t num_args) {
700  // optimise away parenthesis around an expression if possible
701  if (rule->rule_id == RULE_atom_paren) {
702  // there should be just 1 arg for this rule
703  mp_parse_node_t pn = peek_result(parser, 0);
704  if (MP_PARSE_NODE_IS_NULL(pn)) {
705  // need to keep parenthesis for ()
706  } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, RULE_testlist_comp)) {
707  // need to keep parenthesis for (a, b, ...)
708  } else {
709  // parenthesis around a single expression, so it's just the expression
710  return;
711  }
712  }
713 
714  #if MICROPY_COMP_CONST_FOLDING
715  if (fold_logical_constants(parser, rule, &num_args)) {
716  // we folded this rule so return straight away
717  return;
718  }
719  if (fold_constants(parser, rule, num_args)) {
720  // we folded this rule so return straight away
721  return;
722  }
723  #endif
724 
725  mp_parse_node_struct_t *pn = parser_alloc(parser, sizeof(mp_parse_node_struct_t) + sizeof(mp_parse_node_t) * num_args);
726  pn->source_line = src_line;
727  pn->kind_num_nodes = (rule->rule_id & 0xff) | (num_args << 8);
728  for (size_t i = num_args; i > 0; i--) {
729  pn->nodes[i - 1] = pop_result(parser);
730  }
731  push_result_node(parser, (mp_parse_node_t)pn);
732 }
733 
735 
736  // initialise parser and allocate memory for its stacks
737 
738  parser_t parser;
739 
740  parser.rule_stack_alloc = MICROPY_ALLOC_PARSE_RULE_INIT;
741  parser.rule_stack_top = 0;
742  parser.rule_stack = m_new(rule_stack_t, parser.rule_stack_alloc);
743 
744  parser.result_stack_alloc = MICROPY_ALLOC_PARSE_RESULT_INIT;
745  parser.result_stack_top = 0;
746  parser.result_stack = m_new(mp_parse_node_t, parser.result_stack_alloc);
747 
748  parser.lexer = lex;
749 
750  parser.tree.chunk = NULL;
751  parser.cur_chunk = NULL;
752 
753  #if MICROPY_COMP_CONST
754  mp_map_init(&parser.consts, 0);
755  #endif
756 
757  // work out the top-level rule to use, and push it on the stack
758  size_t top_level_rule;
759  switch (input_kind) {
760  case MP_PARSE_SINGLE_INPUT: top_level_rule = RULE_single_input; break;
761  case MP_PARSE_EVAL_INPUT: top_level_rule = RULE_eval_input; break;
762  default: top_level_rule = RULE_file_input;
763  }
764  push_rule(&parser, lex->tok_line, rules[top_level_rule], 0);
765 
766  // parse!
767 
768  size_t n, i; // state for the current rule
769  size_t rule_src_line; // source line for the first token matched by the current rule
770  bool backtrack = false;
771  const rule_t *rule = NULL;
772 
773  for (;;) {
774  next_rule:
775  if (parser.rule_stack_top == 0) {
776  break;
777  }
778 
779  pop_rule(&parser, &rule, &i, &rule_src_line);
780  n = rule->act & RULE_ACT_ARG_MASK;
781 
782  /*
783  // debugging
784  printf("depth=%d ", parser.rule_stack_top);
785  for (int j = 0; j < parser.rule_stack_top; ++j) {
786  printf(" ");
787  }
788  printf("%s n=%d i=%d bt=%d\n", rule->rule_name, n, i, backtrack);
789  */
790 
791  switch (rule->act & RULE_ACT_KIND_MASK) {
792  case RULE_ACT_OR:
793  if (i > 0 && !backtrack) {
794  goto next_rule;
795  } else {
796  backtrack = false;
797  }
798  for (; i < n; ++i) {
799  uint16_t kind = rule->arg[i] & RULE_ARG_KIND_MASK;
800  if (kind == RULE_ARG_TOK) {
801  if (lex->tok_kind == (rule->arg[i] & RULE_ARG_ARG_MASK)) {
802  push_result_token(&parser, rule);
803  mp_lexer_to_next(lex);
804  goto next_rule;
805  }
806  } else {
807  assert(kind == RULE_ARG_RULE);
808  if (i + 1 < n) {
809  push_rule(&parser, rule_src_line, rule, i + 1); // save this or-rule
810  }
811  push_rule_from_arg(&parser, rule->arg[i]); // push child of or-rule
812  goto next_rule;
813  }
814  }
815  backtrack = true;
816  break;
817 
818  case RULE_ACT_AND: {
819 
820  // failed, backtrack if we can, else syntax error
821  if (backtrack) {
822  assert(i > 0);
823  if ((rule->arg[i - 1] & RULE_ARG_KIND_MASK) == RULE_ARG_OPT_RULE) {
824  // an optional rule that failed, so continue with next arg
825  push_result_node(&parser, MP_PARSE_NODE_NULL);
826  backtrack = false;
827  } else {
828  // a mandatory rule that failed, so propagate backtrack
829  if (i > 1) {
830  // already eaten tokens so can't backtrack
831  goto syntax_error;
832  } else {
833  goto next_rule;
834  }
835  }
836  }
837 
838  // progress through the rule
839  for (; i < n; ++i) {
840  if ((rule->arg[i] & RULE_ARG_KIND_MASK) == RULE_ARG_TOK) {
841  // need to match a token
842  mp_token_kind_t tok_kind = rule->arg[i] & RULE_ARG_ARG_MASK;
843  if (lex->tok_kind == tok_kind) {
844  // matched token
845  if (tok_kind == MP_TOKEN_NAME) {
846  push_result_token(&parser, rule);
847  }
848  mp_lexer_to_next(lex);
849  } else {
850  // failed to match token
851  if (i > 0) {
852  // already eaten tokens so can't backtrack
853  goto syntax_error;
854  } else {
855  // this rule failed, so backtrack
856  backtrack = true;
857  goto next_rule;
858  }
859  }
860  } else {
861  push_rule(&parser, rule_src_line, rule, i + 1); // save this and-rule
862  push_rule_from_arg(&parser, rule->arg[i]); // push child of and-rule
863  goto next_rule;
864  }
865  }
866 
867  assert(i == n);
868 
869  // matched the rule, so now build the corresponding parse_node
870 
871  #if !MICROPY_ENABLE_DOC_STRING
872  // this code discards lonely statements, such as doc strings
873  if (input_kind != MP_PARSE_SINGLE_INPUT && rule->rule_id == RULE_expr_stmt && peek_result(&parser, 0) == MP_PARSE_NODE_NULL) {
874  mp_parse_node_t p = peek_result(&parser, 1);
876  || MP_PARSE_NODE_IS_STRUCT_KIND(p, RULE_const_object)) {
877  pop_result(&parser); // MP_PARSE_NODE_NULL
878  pop_result(&parser); // const expression (leaf or RULE_const_object)
879  // Pushing the "pass" rule here will overwrite any RULE_const_object
880  // entry that was on the result stack, allowing the GC to reclaim
881  // the memory from the const object when needed.
882  push_result_rule(&parser, rule_src_line, rules[RULE_pass_stmt], 0);
883  break;
884  }
885  }
886  #endif
887 
888  // count number of arguments for the parse node
889  i = 0;
890  size_t num_not_nil = 0;
891  for (size_t x = n; x > 0;) {
892  --x;
893  if ((rule->arg[x] & RULE_ARG_KIND_MASK) == RULE_ARG_TOK) {
894  mp_token_kind_t tok_kind = rule->arg[x] & RULE_ARG_ARG_MASK;
895  if (tok_kind == MP_TOKEN_NAME) {
896  // only tokens which were names are pushed to stack
897  i += 1;
898  num_not_nil += 1;
899  }
900  } else {
901  // rules are always pushed
902  if (peek_result(&parser, i) != MP_PARSE_NODE_NULL) {
903  num_not_nil += 1;
904  }
905  i += 1;
906  }
907  }
908 
909  if (num_not_nil == 1 && (rule->act & RULE_ACT_ALLOW_IDENT)) {
910  // this rule has only 1 argument and should not be emitted
912  for (size_t x = 0; x < i; ++x) {
913  mp_parse_node_t pn2 = pop_result(&parser);
914  if (pn2 != MP_PARSE_NODE_NULL) {
915  pn = pn2;
916  }
917  }
918  push_result_node(&parser, pn);
919  } else {
920  // this rule must be emitted
921 
922  if (rule->act & RULE_ACT_ADD_BLANK) {
923  // and add an extra blank node at the end (used by the compiler to store data)
924  push_result_node(&parser, MP_PARSE_NODE_NULL);
925  i += 1;
926  }
927 
928  push_result_rule(&parser, rule_src_line, rule, i);
929  }
930  break;
931  }
932 
933  default: {
934  assert((rule->act & RULE_ACT_KIND_MASK) == RULE_ACT_LIST);
935 
936  // n=2 is: item item*
937  // n=1 is: item (sep item)*
938  // n=3 is: item (sep item)* [sep]
939  bool had_trailing_sep;
940  if (backtrack) {
941  list_backtrack:
942  had_trailing_sep = false;
943  if (n == 2) {
944  if (i == 1) {
945  // fail on item, first time round; propagate backtrack
946  goto next_rule;
947  } else {
948  // fail on item, in later rounds; finish with this rule
949  backtrack = false;
950  }
951  } else {
952  if (i == 1) {
953  // fail on item, first time round; propagate backtrack
954  goto next_rule;
955  } else if ((i & 1) == 1) {
956  // fail on item, in later rounds; have eaten tokens so can't backtrack
957  if (n == 3) {
958  // list allows trailing separator; finish parsing list
959  had_trailing_sep = true;
960  backtrack = false;
961  } else {
962  // list doesn't allowing trailing separator; fail
963  goto syntax_error;
964  }
965  } else {
966  // fail on separator; finish parsing list
967  backtrack = false;
968  }
969  }
970  } else {
971  for (;;) {
972  size_t arg = rule->arg[i & 1 & n];
973  if ((arg & RULE_ARG_KIND_MASK) == RULE_ARG_TOK) {
974  if (lex->tok_kind == (arg & RULE_ARG_ARG_MASK)) {
975  if (i & 1 & n) {
976  // separators which are tokens are not pushed to result stack
977  } else {
978  push_result_token(&parser, rule);
979  }
980  mp_lexer_to_next(lex);
981  // got element of list, so continue parsing list
982  i += 1;
983  } else {
984  // couldn't get element of list
985  i += 1;
986  backtrack = true;
987  goto list_backtrack;
988  }
989  } else {
990  assert((arg & RULE_ARG_KIND_MASK) == RULE_ARG_RULE);
991  push_rule(&parser, rule_src_line, rule, i + 1); // save this list-rule
992  push_rule_from_arg(&parser, arg); // push child of list-rule
993  goto next_rule;
994  }
995  }
996  }
997  assert(i >= 1);
998 
999  // compute number of elements in list, result in i
1000  i -= 1;
1001  if ((n & 1) && (rule->arg[1] & RULE_ARG_KIND_MASK) == RULE_ARG_TOK) {
1002  // don't count separators when they are tokens
1003  i = (i + 1) / 2;
1004  }
1005 
1006  if (i == 1) {
1007  // list matched single item
1008  if (had_trailing_sep) {
1009  // if there was a trailing separator, make a list of a single item
1010  push_result_rule(&parser, rule_src_line, rule, i);
1011  } else {
1012  // just leave single item on stack (ie don't wrap in a list)
1013  }
1014  } else {
1015  push_result_rule(&parser, rule_src_line, rule, i);
1016  }
1017  break;
1018  }
1019  }
1020  }
1021 
1022  #if MICROPY_COMP_CONST
1023  mp_map_deinit(&parser.consts);
1024  #endif
1025 
1026  // truncate final chunk and link into chain of chunks
1027  if (parser.cur_chunk != NULL) {
1028  (void)m_renew_maybe(byte, parser.cur_chunk,
1029  sizeof(mp_parse_chunk_t) + parser.cur_chunk->alloc,
1030  sizeof(mp_parse_chunk_t) + parser.cur_chunk->union_.used,
1031  false);
1032  parser.cur_chunk->alloc = parser.cur_chunk->union_.used;
1033  parser.cur_chunk->union_.next = parser.tree.chunk;
1034  parser.tree.chunk = parser.cur_chunk;
1035  }
1036 
1037  if (
1038  lex->tok_kind != MP_TOKEN_END // check we are at the end of the token stream
1039  || parser.result_stack_top == 0 // check that we got a node (can fail on empty input)
1040  ) {
1041  syntax_error:;
1042  mp_obj_t exc;
1043  if (lex->tok_kind == MP_TOKEN_INDENT) {
1045  "unexpected indent");
1046  } else if (lex->tok_kind == MP_TOKEN_DEDENT_MISMATCH) {
1048  "unindent does not match any outer indentation level");
1049  } else {
1051  "invalid syntax");
1052  }
1053  // add traceback to give info about file name and location
1054  // we don't have a 'block' name, so just pass the NULL qstr to indicate this
1055  mp_obj_exception_add_traceback(exc, lex->source_name, lex->tok_line, MP_QSTR_NULL);
1056  nlr_raise(exc);
1057  }
1058 
1059  // get the root parse node that we created
1060  assert(parser.result_stack_top == 1);
1061  parser.tree.root = parser.result_stack[0];
1062 
1063  // free the memory that we don't need anymore
1064  m_del(rule_stack_t, parser.rule_stack, parser.rule_stack_alloc);
1065  m_del(mp_parse_node_t, parser.result_stack, parser.result_stack_alloc);
1066 
1067  // we also free the lexer on behalf of the caller
1068  mp_lexer_free(lex);
1069 
1070  return parser.tree;
1071 }
1072 
1074  mp_parse_chunk_t *chunk = tree->chunk;
1075  while (chunk != NULL) {
1076  mp_parse_chunk_t *next = chunk->union_.next;
1077  m_del(byte, chunk, sizeof(mp_parse_chunk_t) + chunk->alloc);
1078  chunk = next;
1079  }
1080 }
1081 
1082 #endif // MICROPY_ENABLE_COMPILER
#define MICROPY_ALLOC_PARSE_RULE_INIT
Definition: mpconfig.h:145
#define m_renew_maybe(type, ptr, old_num, new_num, allow_move)
Definition: misc.h:76
bool mp_parse_node_is_const_true(mp_parse_node_t pn)
mp_obj_t mp_unary_op(mp_unary_op_t op, mp_obj_t arg)
Definition: runtime.c:216
intptr_t mp_int_t
Definition: mpconfigport.h:73
qstr qstr_from_strn(const char *str, size_t len)
Definition: qstr.c:187
bool mp_parse_node_is_const_false(mp_parse_node_t pn)
#define MICROPY_ALLOC_PARSE_RULE_INC
Definition: mpconfig.h:150
void mp_lexer_to_next(mp_lexer_t *lex)
#define INT_FMT
Definition: mpconfigport.h:72
void mp_lexer_free(mp_lexer_t *lex)
const char * qstr_str(qstr q)
Definition: qstr.c:278
void mp_load_method_maybe(mp_obj_t obj, qstr attr, mp_obj_t *dest)
Definition: runtime.c:1040
rule(file_input_3)) DEF_RULE_NC(file_input_3
#define assert(e)
Definition: assert.h:9
mp_parse_node_t nodes[]
Definition: parse.h:57
#define MICROPY_PORT_CONSTANTS
Definition: mpconfig.h:1148
def data
Definition: i18n.py:176
#define MICROPY_ALLOC_PARSE_INTERN_STRING_LEN
Definition: mpconfig.h:165
#define MP_PARSE_NODE_STRUCT_KIND(pns)
Definition: parse.h:76
#define m_del(type, ptr, num)
Definition: misc.h:77
#define MP_PARSE_NODE_LEAF_KIND(pn)
Definition: parse.h:73
char * buf
Definition: misc.h:145
vstr_t vstr
Definition: lexer.h:167
void mp_map_init(mp_map_t *map, size_t n)
Definition: map.c:72
unsigned int size_t
Definition: stddef.h:7
#define MP_PARSE_NODE_LEAF_SMALL_INT(pn)
Definition: parse.h:75
#define MP_PARSE_NODE_IS_SMALL_INT(pn)
Definition: parse.h:68
#define MP_ROM_QSTR(q)
Definition: obj.h:241
unsigned int uintptr_t
Definition: stdint.h:14
#define MP_OBJ_NEW_QSTR(qst)
Definition: obj.h:92
unsigned short uint16_t
Definition: stdint.h:5
#define MP_ROM_PTR(p)
Definition: obj.h:242
const mp_obj_type_t mp_type_bytes
Definition: objstr.c:1964
size_t len
Definition: misc.h:144
unsigned char uint8_t
Definition: stdint.h:4
mp_unary_op_t
Definition: runtime0.h:45
mp_token_kind_t tok_kind
Definition: lexer.h:166
#define MICROPY_ALLOC_PARSE_RESULT_INC
Definition: mpconfig.h:160
uintptr_t mp_parse_node_t
Definition: parse.h:52
uint32_t source_line
Definition: parse.h:55
#define MP_PARSE_NODE_STRUCT_NUM_NODES(pns)
Definition: parse.h:77
#define STATIC
Definition: mpconfig.h:1178
qstr qstr_find_strn(const char *str, size_t str_len)
Definition: qstr.c:166
#define MP_OBJ_SMALL_INT_VALUE(o)
Definition: obj.h:86
int ssize_t
Definition: stddef.h:6
enum _mp_token_kind_t mp_token_kind_t
const mp_obj_type_t mp_type_SyntaxError
MP_DEFINE_CONST_MAP(mp_builtin_module_map, mp_builtin_module_table)
bool mp_parse_node_get_int_maybe(mp_parse_node_t pn, mp_obj_t *o)
mp_map_elem_t * mp_map_lookup(mp_map_t *map, mp_obj_t index, mp_map_lookup_kind_t lookup_kind)
Definition: map.c:138
mp_parse_input_kind_t
Definition: parse.h:91
mp_obj_t mp_obj_new_exception_msg(const mp_obj_type_t *exc_type, const char *msg)
Definition: objexcept.c:343
void mp_map_deinit(mp_map_t *map)
Definition: map.c:96
void mp_parse_node_print(mp_parse_node_t pn, size_t indent)
size_t tok_line
Definition: lexer.h:164
#define MP_OBJ_NEW_SMALL_INT(small_int)
Definition: obj.h:87
#define MP_PARSE_NODE_IS_ID(pn)
Definition: parse.h:69
#define MP_PARSE_NODE_BYTES
Definition: parse.h:49
#define MP_PARSE_NODE_IS_TOKEN_KIND(pn, k)
Definition: parse.h:71
#define MP_PARSE_NODE_IS_STRUCT_KIND(pn, k)
Definition: parse.h:66
int mp_parse_node_extract_list(mp_parse_node_t *pn, size_t pn_kind, mp_parse_node_t **nodes)
#define NULL
Definition: stddef.h:4
#define MP_OBJ_NULL
Definition: obj.h:73
struct _mp_parse_chunk_t * chunk
Definition: parse.h:99
#define MP_PARSE_NODE_STRING
Definition: parse.h:48
#define MICROPY_ALLOC_PARSE_RESULT_INIT
Definition: mpconfig.h:155
#define MP_PARSE_NODE_TOKEN
Definition: parse.h:50
unsigned long long uint64_t
Definition: stdint.h:7
size_t qstr
Definition: qstr.h:48
const mp_obj_type_t mp_type_str
Definition: objstr.c:1950
mp_binary_op_t
Definition: runtime0.h:67
mp_obj_t mp_binary_op(mp_binary_op_t op, mp_obj_t lhs, mp_obj_t rhs)
Definition: runtime.c:277
mp_obj_t value
Definition: obj.h:343
int mp_obj_int_sign(mp_obj_t self_in)
Definition: objint.c:304
#define MP_PARSE_NODE_ID
Definition: parse.h:47
#define MP_OBJ_IS_INT(o)
Definition: obj.h:255
void mp_obj_exception_add_traceback(mp_obj_t self_in, qstr file, size_t line, qstr block)
Definition: objexcept.c:485
tok(NEWLINE)
Definition: obj.h:356
unsigned char byte
Definition: misc.h:37
uint32_t kind_num_nodes
Definition: parse.h:56
mp_obj_t mp_parse_num_decimal(const char *str, size_t len, bool allow_imag, bool force_complex, mp_lexer_t *lex)
Definition: parsenum.c:171
#define m_renew(type, ptr, old_num, new_num)
Definition: misc.h:75
mp_parse_tree_t mp_parse(struct _mp_lexer_t *lex, mp_parse_input_kind_t input_kind)
const mp_obj_type_t mp_type_IndentationError
#define MP_PARSE_NODE_LEAF_ARG(pn)
Definition: parse.h:74
const mp_obj_module_t mp_module_uerrno
#define MP_PARSE_NODE_IS_STRUCT(pn)
Definition: parse.h:65
#define nlr_raise(val)
Definition: nlr.h:89
mp_obj_t mp_obj_new_str_of_type(const mp_obj_type_t *type, const byte *data, size_t len)
Definition: objstr.c:1981
mp_obj_t mp_parse_num_integer(const char *restrict str_, size_t len, int base, mp_lexer_t *lex)
Definition: parsenum.c:49
uint64_t mp_obj_t
Definition: obj.h:39
#define MP_PARSE_NODE_IS_LEAF(pn)
Definition: parse.h:64
#define MP_PARSE_NODE_IS_NULL(pn)
Definition: parse.h:63
const mp_obj_module_t mp_module_uctypes
void mp_parse_tree_clear(mp_parse_tree_t *tree)
qstr source_name
Definition: lexer.h:149
#define MICROPY_ALLOC_PARSE_CHUNK_INIT
Definition: mpconfigport.h:14
#define MP_PARSE_NODE_NULL
Definition: parse.h:45
#define m_new(type, num)
Definition: misc.h:57
parser
Definition: i18n.py:169
unsigned int uint
Definition: misc.h:38