I am defining a lexer for a programming language. Part of this involves having a table of keywords and tokens:
#define FOREACH_KEYWORD(V) \
V(And, and) \
V(Else, else) \
V(False, false) \
V(If, if) \
V(Or, or) \
V(True, true)
#define FOREACH_TOKEN(V) \
V(Plus) \
V(Minus) \
V(Times) \
V(Div) \
FOREACH_KEYWORD(V)
These macros are intended to be used like so:
const char *kTokenTypeNames[] = {
#define STR(NAME) #NAME,
FOREACH_TOKEN(STR)
#undef STR
};
// which would ideally expand to
const char *kTokenTypeNames[] = {
"Plus", "Minus", "Times", "Div", "And", "Else", "False", "If", "Or", "True",
};
And the keywords should be included in the token list. The above pseudocode does not work because the two different V
macro parameters have different arities. I would like any macro that has to deal with tokens to only need to take 1 parameter, and any macro that deals with keywords to need to take 2. I'd rather not make everything variadic. I feel like it should be possible to add some interstitial macros to make this combination possible, but I have as of yet not been clever enough to make this happen.
I suppose, in general: I would like to be able to take an X-macro of arity N and reduce it to some M where M is smaller than N.
How can I achieve this?
Given your specs I think this is what you're looking for.
#define AB_TO_A(A,B) (A)
#define EVAL(...) __VA_ARGS__
#define FOREACH_KEYWORD(V) \
V(And, and) \
V(Else, else) \
V(False, false) \
V(If, if) \
V(Or, or) \
V(True, true)
#define FOREACH_TOKEN(V) \
V(Plus) \
V(Minus) \
V(Times) \
V(Div) \
EVAL(FOREACH_KEYWORD(V AB_TO_A))
const char *kTokenTypeNames[] = {
#define STR(NAME) #NAME,
FOREACH_TOKEN(STR)
#undef STR
};
Coliru demo here.