Compiler

A compile-time compiler (meta-compiler).

To use: (see the unittest for a running example)

Create your pegged grammar. enum _g = q{ GRAMMAR: ... }; mixin (grammar(_g));

Create a template for your compiler, and mixin the default signature. struct myCompiler(ParseTree T) { mixin Compiler!(T,myCompiler); // .... }

The "Compiler" mixin binds the "compileNode" function to a nested scope. We can override the compileNode function for specific matches in the parse tree. To do this, we use string mixins, that bind to the local scope. The template "nodeOverride" takes a condition and a function, and creates a local override that binds the function to "compileNode" if the static condition matches against a tree node. The "compilerOverride" template binds to a node name. This goes inside the parser template definition, and in this case we're overriding the behaviour for a nodes matching a rule named "GRAMMAR.Text". The override template accepts a second string argument representing the code to be mixed in when the name matches. The code should return a string that will be output from the compiler, to be mixed in to the users program. In this example, we concantenate the "matches" property. "T" refers to the current node. // ... mixin (compilerOverride!("GRAMMAR.Text","T.matches.join(\"\")")); // ...

Then, we invoke the compiler. enum _d = q{ ... the input to your parser ... }; mixin Compiler!(myParser,GRAMMAR(_d));

Or we can just pull out the text and not mix it in to our program right away enum code = myParser!(GRAMMAR(_d)).compileNode();

template Compiler (
ParseTree T
alias Parser
) {}

Meta