summaryrefslogtreecommitdiffstatshomepage
path: root/py/parse.c
diff options
context:
space:
mode:
Diffstat (limited to 'py/parse.c')
-rw-r--r--py/parse.c23
1 files changed, 14 insertions, 9 deletions
diff --git a/py/parse.c b/py/parse.c
index 2179f2878c..07ceceeeb7 100644
--- a/py/parse.c
+++ b/py/parse.c
@@ -38,13 +38,14 @@
#include "parse.h"
#include "smallint.h"
-#define RULE_ACT_KIND_MASK (0xf0)
#define RULE_ACT_ARG_MASK (0x0f)
+#define RULE_ACT_KIND_MASK (0x30)
+#define RULE_ACT_ALLOW_IDENT (0x40)
+#define RULE_ACT_ADD_BLANK (0x80)
#define RULE_ACT_OR (0x10)
#define RULE_ACT_AND (0x20)
#define RULE_ACT_LIST (0x30)
-#define RULE_ARG_BLANK (0x0000)
#define RULE_ARG_KIND_MASK (0xf000)
#define RULE_ARG_ARG_MASK (0x0fff)
#define RULE_ARG_TOK (0x1000)
@@ -52,7 +53,7 @@
#define RULE_ARG_OPT_TOK (0x3000)
#define RULE_ARG_OPT_RULE (0x4000)
-#define ADD_BLANK_NODE(rule_id) ((rule_id) == RULE_funcdef || (rule_id) == RULE_classdef || (rule_id) == RULE_comp_for || (rule_id) == RULE_lambdef || (rule_id) == RULE_lambdef_nocond)
+#define ADD_BLANK_NODE(rule) ((rule->act & RULE_ACT_ADD_BLANK) != 0)
// (un)comment to use rule names; for debugging
//#define USE_RULE_NAME (1)
@@ -75,6 +76,8 @@ enum {
RULE_string, // special node for non-interned string
};
+#define ident (RULE_ACT_ALLOW_IDENT)
+#define blank (RULE_ACT_ADD_BLANK)
#define or(n) (RULE_ACT_OR | n)
#define and(n) (RULE_ACT_AND | n)
#define one_or_more (RULE_ACT_LIST | 2)
@@ -181,7 +184,7 @@ void mp_parse_node_free(mp_parse_node_t pn) {
if (rule_id == RULE_string) {
m_del(char, (char*)pns->nodes[0], (mp_uint_t)pns->nodes[1]);
} else {
- bool adjust = ADD_BLANK_NODE(rule_id);
+ bool adjust = ADD_BLANK_NODE(rules[rule_id]);
if (adjust) {
n--;
}
@@ -573,15 +576,17 @@ mp_parse_node_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind, mp_p
emit_rule = true;
}
- // never emit these rules if they have only 1 argument
- // NOTE: can't put atom_paren here because we need it to distinguisg, for example, [a,b] from [(a,b)]
- // TODO possibly put varargslist_name, varargslist_equal here as well
- if (rule->rule_id == RULE_else_stmt || rule->rule_id == RULE_testlist_comp_3b || rule->rule_id == RULE_import_as_names_paren || rule->rule_id == RULE_typedargslist_name || rule->rule_id == RULE_typedargslist_colon || rule->rule_id == RULE_typedargslist_equal || rule->rule_id == RULE_dictorsetmaker_colon || rule->rule_id == RULE_classdef_2 || rule->rule_id == RULE_with_item_as || rule->rule_id == RULE_assert_stmt_extra || rule->rule_id == RULE_as_name || rule->rule_id == RULE_raise_stmt_from || rule->rule_id == RULE_vfpdef || rule->rule_id == RULE_funcdefrettype) {
+ // if a rule has the RULE_ACT_ALLOW_IDENT bit set then this
+ // rule should not be emitted if it has only 1 argument
+ // NOTE: can't set this flag for atom_paren because we need it
+ // to distinguish, for example, [a,b] from [(a,b)]
+ // TODO possibly set for: varargslist_name, varargslist_equal
+ if (rule->act & RULE_ACT_ALLOW_IDENT) {
emit_rule = false;
}
// always emit these rules, and add an extra blank node at the end (to be used by the compiler to store data)
- if (ADD_BLANK_NODE(rule->rule_id)) {
+ if (ADD_BLANK_NODE(rule)) {
emit_rule = true;
push_result_node(&parser, MP_PARSE_NODE_NULL);
i += 1;