Home > Mobile >  What is the best alternative to C's nested array designators in C for initializing a 2D array
What is the best alternative to C's nested array designators in C for initializing a 2D array

Time:10-07

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:

  1. 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, ...},
        ...
    }
  1. 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();
  • Related