|
3 | 3 | *
|
4 | 4 | * The MIT License (MIT)
|
5 | 5 | *
|
6 |
| - * Copyright (c) 2013-2015 Damien P. George |
| 6 | + * Copyright (c) 2013-2017 Damien P. George |
7 | 7 | *
|
8 | 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy
|
9 | 9 | * of this software and associated documentation files (the "Software"), to deal
|
@@ -108,36 +108,81 @@ STATIC const uint8_t rule_act_table[] = {
|
108 | 108 | #undef list_with_end
|
109 | 109 | };
|
110 | 110 |
|
111 |
| -// Define the argument data for each rule |
| 111 | +// Define the argument data for each rule, as a combined array |
| 112 | +STATIC const uint16_t rule_arg_combined_table[] = { |
112 | 113 | #define tok(t) (RULE_ARG_TOK | MP_TOKEN_##t)
|
113 | 114 | #define rule(r) (RULE_ARG_RULE | RULE_##r)
|
114 | 115 | #define opt_rule(r) (RULE_ARG_OPT_RULE | RULE_##r)
|
115 | 116 |
|
116 |
| -#define DEF_RULE(rule, comp, kind, ...) static const uint16_t const rule_arg_##rule[] = { __VA_ARGS__ }; |
117 |
10000
| -#define DEF_RULE_NC(rule, kind, ...) static const uint16_t const rule_arg_##rule[] = { __VA_ARGS__ }; |
| 117 | +#define DEF_RULE(rule, comp, kind, ...) __VA_ARGS__, |
| 118 | +#define DEF_RULE_NC(rule, kind, ...) |
| 119 | +#include "py/grammar.h" |
| 120 | +#undef DEF_RULE |
| 121 | +#undef DEF_RULE_NC |
| 122 | + |
| 123 | +#define DEF_RULE(rule, comp, kind, ...) |
| 124 | +#define DEF_RULE_NC(rule, kind, ...) __VA_ARGS__, |
118 | 125 | #include "py/grammar.h"
|
119 | 126 | #undef DEF_RULE
|
120 | 127 | #undef DEF_RULE_NC
|
121 | 128 |
|
122 | 129 | #undef tok
|
123 | 130 | #undef rule
|
124 | 131 | #undef opt_rule
|
| 132 | +}; |
| 133 | + |
| 134 | +// Macro to create a list of N-1 identifiers where N is the number of variable arguments to the macro |
| 135 | +#define RULE_PADDING(rule, ...) RULE_PADDING2(rule, __VA_ARGS__, RULE_PADDING_IDS(rule)) |
| 136 | +#define RULE_PADDING2(rule, ...) RULE_PADDING3(rule, __VA_ARGS__) |
| 137 | +#define RULE_PADDING3(rule, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, ...) __VA_ARGS__ |
| 138 | +#define RULE_PADDING_IDS(r) PAD12_##r, PAD11_##r, PAD10_##r, PAD9_##r, PAD8_##r, PAD7_##r, PAD6_##r, PAD5_##r, PAD4_##r, PAD3_##r, PAD2_##r, PAD1_##r, |
| 139 | + |
| 140 | +// Use an enum to create constants that specify where in rule_arg_combined_table a given rule starts |
| 141 | +enum { |
| 142 | +#define DEF_RULE(rule, comp, kind, ...) RULE_ARG_OFFSET_##rule, RULE_PADDING(rule, __VA_ARGS__) |
| 143 | +#define DEF_RULE_NC(rule, kind, ...) |
| 144 | +#include "py/grammar.h" |
| 145 | +#undef DEF_RULE |
| 146 | +#undef DEF_RULE_NC |
| 147 | +#define DEF_RULE(rule, comp, kind, ...) |
| 148 | +#define DEF_RULE_NC(rule, kind, ...) RULE_ARG_OFFSET_##rule, RULE_PADDING(rule, __VA_ARGS__) |
| 149 | +#include "py/grammar.h" |
| 150 | +#undef DEF_RULE |
| 151 | +#undef DEF_RULE_NC |
| 152 | +}; |
125 | 153 |
|
126 |
| -// Define an array of pointers to corresponding rule data |
127 |
| -STATIC const uint16_t *const rule_arg_table[] = { |
128 |
| -#define DEF_RULE(rule, comp, kind, ...) &rule_arg_##rule[0], |
| 154 | +// Use the above enum values to create a table of offsets for each rule's arg |
| 155 | +// data, which indexes rule_arg_combined_table. The offsets require 9 bits of |
| 156 | +// storage but only the lower 8 bits are stored here. The 9th bit is computed |
| 157 | +// in get_rule_arg using the FIRST_RULE_WITH_OFFSET_ABOVE_255 constant. |
| 158 | +STATIC const uint8_t rule_arg_offset_table[] = { |
| 159 | +#define DEF_RULE(rule, comp, kind, ...) RULE_ARG_OFFSET_##rule & 0xff, |
129 | 160 | #define DEF_RULE_NC(rule, kind, ...)
|
130 | 161 | #include "py/grammar.h"
|
131 | 162 | #undef DEF_RULE
|
132 | 163 | #undef DEF_RULE_NC
|
133 |
| - NULL, // RULE_const_object |
| 164 | + 0, // RULE_const_object |
134 | 165 | #define DEF_RULE(rule, comp, kind, ...)
|
135 |
| -#define DEF_RULE_NC(rule, kind, ...) &rule_arg_##rule[0], |
| 166 | +#define DEF_RULE_NC(rule, kind, ...) RULE_ARG_OFFSET_##rule & 0xff, |
136 | 167 | #include "py/grammar.h"
|
137 | 168 | #undef DEF_RULE
|
138 | 169 | #undef DEF_RULE_NC
|
139 | 170 | };
|
140 | 171 |
|
| 172 | +// Define a constant that's used to determine the 9th bit of the values in rule_arg_offset_table |
| 173 | +static const size_t FIRST_RULE_WITH_OFFSET_ABOVE_255 = |
| 174 | +#define DEF_RULE(rule, comp, kind, ...) RULE_ARG_OFFSET_##rule >= 0x100 ? RULE_##rule : |
| 175 | +#define DEF_RULE_NC(rule, kind, ...) |
| 176 | +#include "py/grammar.h" |
| 177 | +#undef DEF_RULE |
| 178 | +#undef DEF_RULE_NC |
| 179 | +#define DEF_RULE(rule, comp, kind, ...) |
| 180 | +#define DEF_RULE_NC(rule, kind, ...) RULE_ARG_OFFSET_##rule >= 0x100 ? RULE_##rule : |
| 181 | +#include "py/grammar.h" |
| 182 | +#undef DEF_RULE |
| 183 | +#undef DEF_RULE_NC |
| 184 | +0; |
| 185 | + |
141 | 186 | #if USE_RULE_NAME
|
142 | 187 | // Define an array of rule names corresponding to each rule
|
143 | 188 | STATIC const char *const rule_name_table[] = {
|
@@ -189,6 +234,14 @@ typedef struct _parser_t {
|
189 | 234 | #endif
|
190 | 235 | } parser_t;
|
191 | 236 |
|
| 237 | +STATIC const uint16_t *get_rule_arg(uint8_t r_id) { |
| 238 | + size_t off = rule_arg_offset_table[r_id]; |
| 239 | + if (r_id >= FIRST_RULE_WITH_OFFSET_ABOVE_255) { |
| 240 | + off |= 0x100; |
| 241 | + } |
| 242 | + return &rule_arg_combined_table[off]; |
| 243 | +} |
| 244 | + |
192 | 245 | STATIC void *parser_alloc(parser_t *parser, size_t num_bytes) {
|
193 | 246 | // use a custom memory allocator to store parse nodes sequentially in large chunks
|
194 | 247 |
|
@@ -816,7 +869,7 @@ mp_parse_tree_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind) {
|
816 | 869 | size_t rule_src_line; // source line for the first token matched by the current rule
|
817 | 870 | uint8_t rule_id = pop_rule(&parser, &i, &rule_src_line);
|
818 | 871 | uint8_t rule_act = rule_act_table[rule_id];
|
819 |
| - const uint16_t *rule_arg = rule_arg_table[rule_id]; |
| 872 | + const uint16_t *rule_arg = get_rule_arg(rule_id); |
820 | 873 | size_t n = rule_act & RULE_ACT_ARG_MASK;
|
821 | 874 |
|
822 | 875 | /*
|
|
0 commit comments