summaryrefslogtreecommitdiffstatshomepage
path: root/py/parse.c
diff options
context:
space:
mode:
Diffstat (limited to 'py/parse.c')
-rw-r--r--py/parse.c75
1 files changed, 30 insertions, 45 deletions
diff --git a/py/parse.c b/py/parse.c
index 569cf257a7..54e199e593 100644
--- a/py/parse.c
+++ b/py/parse.c
@@ -72,6 +72,7 @@ enum {
RULE_maximum_number_of,
RULE_string, // special node for non-interned string
RULE_bytes, // special node for non-interned bytes
+ RULE_const_object, // special node for a constant, generic Python object
};
#define ident (RULE_ACT_ALLOW_IDENT)
@@ -170,7 +171,7 @@ mp_parse_node_t mp_parse_node_new_leaf(mp_int_t kind, mp_int_t arg) {
if (kind == MP_PARSE_NODE_SMALL_INT) {
return (mp_parse_node_t)(kind | (arg << 1));
}
- return (mp_parse_node_t)(kind | (arg << 5));
+ return (mp_parse_node_t)(kind | (arg << 4));
}
void mp_parse_node_free(mp_parse_node_t pn) {
@@ -180,6 +181,8 @@ void mp_parse_node_free(mp_parse_node_t pn) {
mp_uint_t rule_id = MP_PARSE_NODE_STRUCT_KIND(pns);
if (rule_id == RULE_string || rule_id == RULE_bytes) {
m_del(char, (char*)pns->nodes[0], (mp_uint_t)pns->nodes[1]);
+ } else if (rule_id == RULE_const_object) {
+ // don't free the const object since it's probably used by the compiled code
} else {
bool adjust = ADD_BLANK_NODE(rules[rule_id]);
if (adjust) {
@@ -215,8 +218,6 @@ void mp_parse_node_print(mp_parse_node_t pn, mp_uint_t indent) {
mp_uint_t arg = MP_PARSE_NODE_LEAF_ARG(pn);
switch (MP_PARSE_NODE_LEAF_KIND(pn)) {
case MP_PARSE_NODE_ID: printf("id(%s)\n", qstr_str(arg)); break;
- case MP_PARSE_NODE_INTEGER: printf("int(%s)\n", qstr_str(arg)); break;
- case MP_PARSE_NODE_DECIMAL: printf("dec(%s)\n", qstr_str(arg)); break;
case MP_PARSE_NODE_STRING: printf("str(%s)\n", qstr_str(arg)); break;
case MP_PARSE_NODE_BYTES: printf("bytes(%s)\n", qstr_str(arg)); break;
case MP_PARSE_NODE_TOKEN: printf("tok(" INT_FMT ")\n", arg); break;
@@ -229,6 +230,8 @@ void mp_parse_node_print(mp_parse_node_t pn, mp_uint_t indent) {
printf("literal str(%.*s)\n", (int)pns->nodes[1], (char*)pns->nodes[0]);
} else if (MP_PARSE_NODE_STRUCT_KIND(pns) == RULE_bytes) {
printf("literal bytes(%.*s)\n", (int)pns->nodes[1], (char*)pns->nodes[0]);
+ } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == RULE_const_object) {
+ printf("literal const(%p)\n", (mp_obj_t)pns->nodes[0]);
} else {
mp_uint_t n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
#ifdef USE_RULE_NAME
@@ -285,11 +288,11 @@ STATIC void push_result_node(parser_t *parser, mp_parse_node_t pn) {
parser->result_stack[parser->result_stack_top++] = pn;
}
-STATIC void push_result_string_bytes(parser_t *parser, mp_uint_t src_line, mp_uint_t rule_kind, const char *str, mp_uint_t len) {
+STATIC mp_parse_node_t make_node_string_bytes(parser_t *parser, mp_uint_t src_line, mp_uint_t rule_kind, const char *str, mp_uint_t len) {
mp_parse_node_struct_t *pn = m_new_obj_var_maybe(mp_parse_node_struct_t, mp_parse_node_t, 2);
if (pn == NULL) {
memory_error(parser);
- return;
+ return MP_PARSE_NODE_NULL;
}
pn->source_line = src_line;
pn->kind_num_nodes = rule_kind | (2 << 8);
@@ -297,7 +300,19 @@ STATIC void push_result_string_bytes(parser_t *parser, mp_uint_t src_line, mp_ui
memcpy(p, str, len);
pn->nodes[0] = (mp_int_t)p;
pn->nodes[1] = len;
- push_result_node(parser, (mp_parse_node_t)pn);
+ return (mp_parse_node_t)pn;
+}
+
+STATIC mp_parse_node_t make_node_const_object(parser_t *parser, mp_uint_t src_line, mp_obj_t obj) {
+ mp_parse_node_struct_t *pn = m_new_obj_var_maybe(mp_parse_node_struct_t, mp_parse_node_t, 1);
+ if (pn == NULL) {
+ memory_error(parser);
+ return MP_PARSE_NODE_NULL;
+ }
+ pn->source_line = src_line;
+ pn->kind_num_nodes = RULE_const_object | (1 << 8);
+ pn->nodes[0] = (mp_uint_t)obj;
+ return (mp_parse_node_t)pn;
}
STATIC void push_result_token(parser_t *parser) {
@@ -305,45 +320,16 @@ STATIC void push_result_token(parser_t *parser) {
mp_lexer_t *lex = parser->lexer;
if (lex->tok_kind == MP_TOKEN_NAME) {
pn = mp_parse_node_new_leaf(MP_PARSE_NODE_ID, qstr_from_strn(lex->vstr.buf, lex->vstr.len));
- } else if (lex->tok_kind == MP_TOKEN_NUMBER) {
- bool dec = false;
- bool small_int = true;
- mp_int_t int_val = 0;
- mp_uint_t len = lex->vstr.len;
- const char *str = lex->vstr.buf;
- mp_uint_t base = 0;
- mp_uint_t i = mp_parse_num_base(str, len, &base);
- bool overflow = false;
- for (; i < len; i++) {
- mp_uint_t dig;
- int clower = str[i] | 0x20;
- if (unichar_isdigit(str[i]) && (mp_uint_t)(str[i] - '0') < base) {
- dig = str[i] - '0';
- } else if (base == 16 && 'a' <= clower && clower <= 'f') {
- dig = clower - 'a' + 10;
- } else if (str[i] == '.' || clower == 'e' || clower == 'j') {
- dec = true;
- break;
- } else {
- small_int = false;
- break;
- }
- // add next digi and check for overflow
- if (mp_small_int_mul_overflow(int_val, base)) {
- overflow = true;
- }
- int_val = int_val * base + dig;
- if (!MP_SMALL_INT_FITS(int_val)) {
- overflow = true;
- }
- }
- if (dec) {
- pn = mp_parse_node_new_leaf(MP_PARSE_NODE_DECIMAL, qstr_from_strn(str, len));
- } else if (small_int && !overflow && MP_SMALL_INT_FITS(int_val)) {
- pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, int_val);
+ } else if (lex->tok_kind == MP_TOKEN_INTEGER) {
+ mp_obj_t o = mp_parse_num_integer(lex->vstr.buf, lex->vstr.len, 0, lex);
+ if (MP_OBJ_IS_SMALL_INT(o)) {
+ pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, MP_OBJ_SMALL_INT_VALUE(o));
} else {
- pn = mp_parse_node_new_leaf(MP_PARSE_NODE_INTEGER, qstr_from_strn(str, len));
+ pn = make_node_const_object(parser, lex->tok_line, o);
}
+ } else if (lex->tok_kind == MP_TOKEN_FLOAT_OR_IMAG) {
+ mp_obj_t o = mp_parse_num_decimal(lex->vstr.buf, lex->vstr.len, true, false, lex);
+ pn = make_node_const_object(parser, lex->tok_line, o);
} else if (lex->tok_kind == MP_TOKEN_STRING || lex->tok_kind == MP_TOKEN_BYTES) {
// Don't automatically intern all strings/bytes. doc strings (which are usually large)
// will be discarded by the compiler, and so we shouldn't intern them.
@@ -360,8 +346,7 @@ STATIC void push_result_token(parser_t *parser) {
pn = mp_parse_node_new_leaf(lex->tok_kind == MP_TOKEN_STRING ? MP_PARSE_NODE_STRING : MP_PARSE_NODE_BYTES, qst);
} else {
// not interned, make a node holding a pointer to the string/bytes data
- push_result_string_bytes(parser, lex->tok_line, lex->tok_kind == MP_TOKEN_STRING ? RULE_string : RULE_bytes, lex->vstr.buf, lex->vstr.len);
- return;
+ 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);
}
} else {
pn = mp_parse_node_new_leaf(MP_PARSE_NODE_TOKEN, lex->tok_kind);