Skip to content

Commit c7cb1df

Browse files
committed
py/parse: Fix macro evaluation by avoiding empty __VA_ARGS__.
Empty __VA_ARGS__ are not allowed in the C preprocessor so adjust the rule arg offset calculation to not use them. Also, some compilers (eg MSVC) require an extra layer of macro expansion.
1 parent d3fbfa4 commit c7cb1df

1 file changed

Lines changed: 17 additions & 10 deletions

File tree

py/parse.c

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -131,53 +131,60 @@ STATIC const uint16_t rule_arg_combined_table[] = {
131131
#undef opt_rule
132132
};
133133

134-
// Macro to create a list of N-1 identifiers where N is the number of variable arguments to the macro
134+
// Macro to create a list of N identifiers where N is the number of variable arguments to the macro
135+
#define RULE_EXPAND(x) x
135136
#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__
137+
#define RULE_PADDING2(rule, ...) RULE_EXPAND(RULE_PADDING3(rule, __VA_ARGS__))
138+
#define RULE_PADDING3(rule, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, ...) __VA_ARGS__
138139
#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,
139140

140-
// Use an enum to create constants that specify where in rule_arg_combined_table a given rule starts
141+
// Use an enum to create constants specifying how much room a rule takes in rule_arg_combined_table
141142
enum {
142-
#define DEF_RULE(rule, comp, kind, ...) RULE_ARG_OFFSET_##rule, RULE_PADDING(rule, __VA_ARGS__)
143+
#define DEF_RULE(rule, comp, kind, ...) RULE_PADDING(rule, __VA_ARGS__)
143144
#define DEF_RULE_NC(rule, kind, ...)
144145
#include "py/grammar.h"
145146
#undef DEF_RULE
146147
#undef DEF_RULE_NC
147148
#define DEF_RULE(rule, comp, kind, ...)
148-
#define DEF_RULE_NC(rule, kind, ...) RULE_ARG_OFFSET_##rule, RULE_PADDING(rule, __VA_ARGS__)
149+
#define DEF_RULE_NC(rule, kind, ...) RULE_PADDING(rule, __VA_ARGS__)
149150
#include "py/grammar.h"
150151
#undef DEF_RULE
151152
#undef DEF_RULE_NC
152153
};
153154

155+
// Macro to compute the start of a rule in rule_arg_combined_table
156+
#define RULE_ARG_OFFSET(rule, ...) RULE_ARG_OFFSET2(rule, __VA_ARGS__, RULE_ARG_OFFSET_IDS(rule))
157+
#define RULE_ARG_OFFSET2(rule, ...) RULE_EXPAND(RULE_ARG_OFFSET3(rule, __VA_ARGS__))
158+
#define RULE_ARG_OFFSET3(rule, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, ...) _13
159+
#define RULE_ARG_OFFSET_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, PAD0_##r,
160+
154161
// Use the above enum values to create a table of offsets for each rule's arg
155162
// data, which indexes rule_arg_combined_table. The offsets require 9 bits of
156163
// storage but only the lower 8 bits are stored here. The 9th bit is computed
157164
// in get_rule_arg using the FIRST_RULE_WITH_OFFSET_ABOVE_255 constant.
158165
STATIC const uint8_t rule_arg_offset_table[] = {
159-
#define DEF_RULE(rule, comp, kind, ...) RULE_ARG_OFFSET_##rule & 0xff,
166+
#define DEF_RULE(rule, comp, kind, ...) RULE_ARG_OFFSET(rule, __VA_ARGS__) & 0xff,
160167
#define DEF_RULE_NC(rule, kind, ...)
161168
#include "py/grammar.h"
162169
#undef DEF_RULE
163170
#undef DEF_RULE_NC
164171
0, // RULE_const_object
165172
#define DEF_RULE(rule, comp, kind, ...)
166-
#define DEF_RULE_NC(rule, kind, ...) RULE_ARG_OFFSET_##rule & 0xff,
173+
#define DEF_RULE_NC(rule, kind, ...) RULE_ARG_OFFSET(rule, __VA_ARGS__) & 0xff,
167174
#include "py/grammar.h"
168175
#undef DEF_RULE
169176
#undef DEF_RULE_NC
170177
};
171178

172179
// Define a constant that's used to determine the 9th bit of the values in rule_arg_offset_table
173180
static const size_t FIRST_RULE_WITH_OFFSET_ABOVE_255 =
174-
#define DEF_RULE(rule, comp, kind, ...) RULE_ARG_OFFSET_##rule >= 0x100 ? RULE_##rule :
181+
#define DEF_RULE(rule, comp, kind, ...) RULE_ARG_OFFSET(rule, __VA_ARGS__) >= 0x100 ? RULE_##rule :
175182
#define DEF_RULE_NC(rule, kind, ...)
176183
#include "py/grammar.h"
177184
#undef DEF_RULE
178185
#undef DEF_RULE_NC
179186
#define DEF_RULE(rule, comp, kind, ...)
180-
#define DEF_RULE_NC(rule, kind, ...) RULE_ARG_OFFSET_##rule >= 0x100 ? RULE_##rule :
187+
#define DEF_RULE_NC(rule, kind, ...) RULE_ARG_OFFSET(rule, __VA_ARGS__) >= 0x100 ? RULE_##rule :
181188
#include "py/grammar.h"
182189
#undef DEF_RULE
183190
#undef DEF_RULE_NC

0 commit comments

Comments
 (0)