> Almost the complete language is available in CTFE, therefore classes could be used to implement the parse tree representation. However, a limitation that does exist is that classes that were created in CTFE cannot yet be stored in static variables or enums. How will the interface to your library look like?
I recently wrote a parsing expression grammar module in D, also to create grammars and parsers at compile-time and parse inputs at CT.
(PEG: http://en.wikipedia.org/wiki/Parsing_expression_grammar)
Usage is like this:
mixin Grammar(
"JSON <- '{' ( Pair ( ',' Pair )* )? '}'"
, "Pair <- String ':' Value"
, "Value <- String / Number / JSON / Array / True / False / Null"
, `True <- "true"`
(..., rest of JSON grammar)
);
enum result = JSON.parse(
`{ "Hello":42,
"World!":
{
"a":[0,1,2,3]
}
}`);
I deliberatly used classes to construct the parsers, for I wanted an extended class template example in a big tutorial on templates I'm writing. For now, the resulting grammars are space-insensitive, because I grew tired of always inserting Spaces parsers everywhere.
The parse tree is done with a tree struct. Since it holds strings (captures), it can be manipulated at CT to recreate new code. Any tree-walking function can collect the captures to build a D code string which can then be mixed in.
For exampe, last week, I created a template constraints parser, to then test the resulting tree with template parameters. It tests the entire constraint with passed parameters and, if it fails, it recursively tests the sub-constraints to find ones that return false.
So, given "if (isIntegral!T && !(isFloatingPoint!(U) || is(U : W)))", it will test "isIntegral!T" and so on.
All in all, it's quite fun and works OK, it just slows down compilation a bit. What was just an example in a tutorial is slowly becoming its own project. I think I'll put it on Github in a week or two.
Philippe