On Fri, Feb 26, 2021 at 11:37:18AM -0800, H. S. Teoh via Digitalmars-d-learn 
wrote:
> On Wed, Feb 24, 2021 at 08:10:30PM +0000, Mike Brown via Digitalmars-d-learn 
> wrote:
> [...]
> > Thank you for the reply. Im struggling extending this to get the
> > nesting working.
[...]

Alright, here's an actual working example. Instead of using classes, I
decided to use templates instead, but the underlying concept is the
same:

-------------------------------------snip--------------------------------------
template branch(string _ident, _values...) {
        enum ident = _ident;
        alias values = _values;
}

// I used strings for easier concatenation to code, otherwise we have to use
// std.conv to convert it which is slow in CTFE.
static immutable string[] primes = [
        "2", "3", "5", "7", "11", "13", "17", "19", "23", "29", "31", "37",
        "41", // fill in more if you need to
];

string genPrimeId(size_t[] indices)
        in (indices.length > 0)
{
        string result = primes[indices[0]];
        foreach (i; indices[1 .. $]) {
                result ~= "*" ~ primes[i];
        }
        return result;
}

template primeIdsImpl(size_t[] indices, Args...)
        if (indices.length > 0 && Args.length > 0)
{
        static if (Args.length == 1) {
                static if (is(typeof(Args[0]) == string)) {
                        enum primeIdsImpl = Args[0] ~ "=" ~ genPrimeId(indices) 
~ ",\n";
                } else {
                        enum primeIdsImpl = Args[0].ident ~ "=" ~ 
genPrimeId(indices) ~ ",\n" ~
                                primeIdsImpl!(indices ~ [ indices[$-1] + 1 ],
                                        Args[0].values);
                }
        } else {
                enum primeIdsImpl = primeIdsImpl!(indices, Args[0]) ~
                        primeIdsImpl!(indices[0 .. $-1] ~ [ indices[$-1] + 1 ],
                                        Args[1 .. $]);
        }
}

template primeIds(string enumName, Args...) if (Args.length > 0) {
        enum primeIds = "enum " ~ enumName ~ " {\n" ~
                primeIdsImpl!([0], Args) ~
                "}";
}

mixin(primeIds!("token_type",
        "endOfFile",
        "unknown",
        "newline",
        branch!("identifier",
                "userDefined",
                "var",
                "uses",
                "constructor",
                "do_",
                "end_",
        ),
        branch!("operator",
                "copyAssignment",
        ),
));

void main() {
        import std;
        writefln("%s", token_type.identifier);
        writefln("%d", token_type.identifier);
}
-------------------------------------snip--------------------------------------


You can change the mixin line to `pragma(msg, ...)` instead to see the
generated code string.

I noticed that the definitions of the first nested identifiers are
different from your original post; I don't know if this is a
misunderstanding on my side or an oversight on your part?  After
identifier=7, the next prime should be 11, not 13, so userDefined should
start with 11*identifier rather than 13*identifier.


T

-- 
Shin: (n.) A device for finding furniture in the dark.

Reply via email to