summaryrefslogtreecommitdiffstatshomepage
path: root/py/parse.c
diff options
context:
space:
mode:
Diffstat (limited to 'py/parse.c')
-rw-r--r--py/parse.c74
1 files changed, 41 insertions, 33 deletions
diff --git a/py/parse.c b/py/parse.c
index 49b42e5d77..fc74a5fa50 100644
--- a/py/parse.c
+++ b/py/parse.c
@@ -80,7 +80,8 @@ static const rule_t *rules[] = {
};
typedef struct _rule_stack_t {
- byte rule_id;
+ unsigned int src_line : 24;
+ unsigned int rule_id : 8;
int32_t arg_i; // what should be the size and signedness?
} rule_stack_t;
@@ -92,45 +93,54 @@ typedef struct _parser_t {
uint result_stack_alloc;
uint result_stack_top;
mp_parse_node_t *result_stack;
+
+ mp_lexer_t *lexer;
} parser_t;
-static void push_rule(parser_t *parser, const rule_t *rule, int arg_i) {
+static void push_rule(parser_t *parser, int src_line, const rule_t *rule, int arg_i) {
if (parser->rule_stack_top >= parser->rule_stack_alloc) {
parser->rule_stack = m_renew(rule_stack_t, parser->rule_stack, parser->rule_stack_alloc, parser->rule_stack_alloc * 2);
parser->rule_stack_alloc *= 2;
}
- parser->rule_stack[parser->rule_stack_top].rule_id = rule->rule_id;
- parser->rule_stack[parser->rule_stack_top].arg_i = arg_i;
- parser->rule_stack_top += 1;
+ rule_stack_t *rs = &parser->rule_stack[parser->rule_stack_top++];
+ rs->src_line = src_line;
+ rs->rule_id = rule->rule_id;
+ rs->arg_i = arg_i;
}
static void push_rule_from_arg(parser_t *parser, uint arg) {
assert((arg & RULE_ARG_KIND_MASK) == RULE_ARG_RULE || (arg & RULE_ARG_KIND_MASK) == RULE_ARG_OPT_RULE);
uint rule_id = arg & RULE_ARG_ARG_MASK;
assert(rule_id < RULE_maximum_number_of);
- push_rule(parser, rules[rule_id], 0);
+ push_rule(parser, mp_lexer_cur(parser->lexer)->src_line, rules[rule_id], 0);
}
-static void pop_rule(parser_t *parser, const rule_t **rule, uint *arg_i) {
+static void pop_rule(parser_t *parser, const rule_t **rule, uint *arg_i, uint *src_line) {
parser->rule_stack_top -= 1;
*rule = rules[parser->rule_stack[parser->rule_stack_top].rule_id];
*arg_i = parser->rule_stack[parser->rule_stack_top].arg_i;
+ *src_line = parser->rule_stack[parser->rule_stack_top].src_line;
}
mp_parse_node_t mp_parse_node_new_leaf(machine_int_t kind, machine_int_t arg) {
return (mp_parse_node_t)(kind | (arg << 4));
}
-int num_parse_nodes_allocated = 0;
-mp_parse_node_struct_t *parse_node_new_struct(int rule_id, int num_args) {
+//int num_parse_nodes_allocated = 0;
+mp_parse_node_struct_t *parse_node_new_struct(int src_line, int rule_id, int num_args) {
mp_parse_node_struct_t *pn = m_new_obj_var(mp_parse_node_struct_t, mp_parse_node_t, num_args);
- pn->source = 0; // TODO
+ pn->source_line = src_line;
pn->kind_num_nodes = (rule_id & 0xff) | (num_args << 8);
- num_parse_nodes_allocated += 1;
+ //num_parse_nodes_allocated += 1;
return pn;
}
void mp_parse_node_show(mp_parse_node_t pn, int indent) {
+ if (MP_PARSE_NODE_IS_STRUCT(pn)) {
+ printf("[% 4d] ", (int)((mp_parse_node_struct_t*)pn)->source_line);
+ } else {
+ printf(" ");
+ }
for (int i = 0; i < indent; i++) {
printf(" ");
}
@@ -258,8 +268,8 @@ static void push_result_token(parser_t *parser, const mp_lexer_t *lex) {
push_result_node(parser, pn);
}
-static void push_result_rule(parser_t *parser, const rule_t *rule, int num_args) {
- mp_parse_node_struct_t *pn = parse_node_new_struct(rule->rule_id, num_args);
+static void push_result_rule(parser_t *parser, int src_line, const rule_t *rule, int num_args) {
+ mp_parse_node_struct_t *pn = parse_node_new_struct(src_line, rule->rule_id, num_args);
for (int i = num_args; i > 0; i--) {
pn->nodes[i - 1] = pop_result(parser);
}
@@ -280,6 +290,8 @@ mp_parse_node_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind, qstr
parser->result_stack_top = 0;
parser->result_stack = m_new(mp_parse_node_t, parser->result_stack_alloc);
+ parser->lexer = lex;
+
// work out the top-level rule to use, and push it on the stack
int top_level_rule;
switch (input_kind) {
@@ -287,13 +299,14 @@ mp_parse_node_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind, qstr
case MP_PARSE_EVAL_INPUT: top_level_rule = RULE_eval_input; break;
default: top_level_rule = RULE_file_input;
}
- push_rule(parser, rules[top_level_rule], 0);
+ push_rule(parser, mp_lexer_cur(lex)->src_line, rules[top_level_rule], 0);
// parse!
- uint n, i;
+ uint n, i; // state for the current rule
+ uint rule_src_line; // source line for the first token matched by the current rule
bool backtrack = false;
- const rule_t *rule;
+ const rule_t *rule = NULL;
mp_token_kind_t tok_kind;
bool emit_rule;
bool had_trailing_sep;
@@ -304,7 +317,7 @@ mp_parse_node_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind, qstr
break;
}
- pop_rule(parser, &rule, &i);
+ pop_rule(parser, &rule, &i, &rule_src_line);
n = rule->act & RULE_ACT_ARG_MASK;
/*
@@ -333,8 +346,8 @@ mp_parse_node_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind, qstr
}
break;
case RULE_ARG_RULE:
- push_rule(parser, rule, i + 1);
- push_rule_from_arg(parser, rule->arg[i]);
+ push_rule(parser, rule_src_line, rule, i + 1); // save this or-rule
+ push_rule_from_arg(parser, rule->arg[i]); // push child of or-rule
goto next_rule;
default:
assert(0);
@@ -398,14 +411,9 @@ mp_parse_node_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind, qstr
}
break;
case RULE_ARG_RULE:
- //if (i + 1 < n) {
- push_rule(parser, rule, i + 1);
- //}
- push_rule_from_arg(parser, rule->arg[i]);
- goto next_rule;
case RULE_ARG_OPT_RULE:
- push_rule(parser, rule, i + 1);
- push_rule_from_arg(parser, rule->arg[i]);
+ push_rule(parser, rule_src_line, rule, i + 1); // save this and-rule
+ push_rule_from_arg(parser, rule->arg[i]); // push child of and-rule
goto next_rule;
default:
assert(0);
@@ -462,9 +470,9 @@ mp_parse_node_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind, qstr
}
//printf("done and %s n=%d i=%d notnil=%d\n", rule->rule_name, n, i, num_not_nil);
if (emit_rule) {
- push_result_rule(parser, rule, i);
+ push_result_rule(parser, rule_src_line, rule, i);
} else if (num_not_nil == 0) {
- push_result_rule(parser, rule, i); // needed for, eg, atom_paren, testlist_comp_3b
+ push_result_rule(parser, rule_src_line, rule, i); // needed for, eg, atom_paren, testlist_comp_3b
//result_stack_show(parser);
//assert(0);
} else if (num_not_nil == 1) {
@@ -478,7 +486,7 @@ mp_parse_node_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind, qstr
}
push_result_node(parser, pn);
} else {
- push_result_rule(parser, rule, i);
+ push_result_rule(parser, rule_src_line, rule, i);
}
break;
@@ -538,8 +546,8 @@ mp_parse_node_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind, qstr
}
break;
case RULE_ARG_RULE:
- push_rule(parser, rule, i + 1);
- push_rule_from_arg(parser, arg);
+ push_rule(parser, rule_src_line, rule, i + 1); // save this list-rule
+ push_rule_from_arg(parser, arg); // push child of list-rule
goto next_rule;
default:
assert(0);
@@ -559,13 +567,13 @@ mp_parse_node_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind, qstr
// list matched single item
if (had_trailing_sep) {
// if there was a trailing separator, make a list of a single item
- push_result_rule(parser, rule, i);
+ push_result_rule(parser, rule_src_line, rule, i);
} else {
// just leave single item on stack (ie don't wrap in a list)
}
} else {
//printf("done list %s %d %d\n", rule->rule_name, n, i);
- push_result_rule(parser, rule, i);
+ push_result_rule(parser, rule_src_line, rule, i);
}
break;