I am currently trying to convert my small regular expression engine from C to C . To discard syntactically incorrect regexes in a compact way, I use a 2D array to define what kinds of tokens are allowed after one another:
#define NUMBER_OF_TOKEN_KINDS 15
typedef enum {
Literal,
Alternator,
...
} TokenKind;
bool grammar_allowed[NUMBER_OF_TOKEN_KINDS][NUMBER_OF_TOKEN_KINDS] = {
...
[Literal][Alternator] = true,
[Alternator][Literal] = true,
...
}
With this kind of structure you can easily catch a big percentage of syntax errors by checking if grammar_allowed[previous_token][current_token]
is set.
This way of initializing grammar_allowed
doesn't work in C , because nested array designators are not part of the language. I can think of two working alternatives to the code above, but both have drawbacks:
- Just don't use designators to initialize entries in the array. This makes it significantly less readable, because I can't see at a glance which entry corresponds to which tokens. It would also be annoying to add/remove tokens or fix a wrong initialization.
private:
static constexpr bool m_grammar_allowed[NUMBER_OF_TOKEN_KINDS][NUMBER_OF_TOKEN_KINDS] = {
{false, true, true, false, false, true, ...},
...
}
- Initialize the entries line by line in a constructor. This doesn't lose readability but is slower, because the data has to be loaded in at runtime instead of being stored in the executable itself.
Lexer() {
...
m_grammar_allowed[Literal][Alternator] = true;
m_grammar_allowed[Alternator][Literal] = true;
...
}
Is there any other way to initialize a 2D array like this in C , but without sacrificing readability or performance?
Thank you!
CodePudding user response:
You might create a constexpr function to initialize your std::array
(instead of C-array):
constexpr
std::array<std::array<bool, NUMBER_OF_TOKEN_KINDS>, NUMBER_OF_TOKEN_KINDS>
make_grammar_allowed()
{
std::array<std::array<bool, NUMBER_OF_TOKEN_KINDS>, NUMBER_OF_TOKEN_KINDS> res {};
res[Literal][Alternator] = true;
res[Alternator][Literal] = true;
// ...
return res;
}
and
static constexpr
std::array<std::array<bool, NUMBER_OF_TOKEN_KINDS>, NUMBER_OF_TOKEN_KINDS>
m_grammar_allowed = make_grammar_allowed();