Suggestion: "break template;"
Pragma
ericanderton at yahoo.removeme.com
Wed Feb 28 13:52:46 PST 2007
Russell Lewis wrote:
> I have been writing a compile-time parser using Tuples and CTFE. I
> admit, I am writing it basically by thinking iteratively, and writing
> templates that execute the code that would have otherwise happened at
> runtime.
>
> There is one big annoyance I keep running into, though, and it is the
> inability to "return" from this sort of template in the middle. Imagine
> that I'm thinking something like this (writing it as runtime code, first):
> parse_tree parse(char[] str) {
> if(str.length == 0)
> return new parse_tree; // empty tree
>
> // do lots of other complex stuff
> }
>
> Now, when I translate this into templates, I get something like:
> template Parse(char[] str) {
> static if(str.length == 0)
> alias struct {} Parse;
> else {
> // do lots of other complex stuff
> }
> }
>
> Sometimes, I end up pretty deeply nested in the else clauses of my
> static if's. It's technically correct, but ugly. What I would like to
> see is the template equivalent of "return" - something which would break
> you out of the current evaluation. My idea is to use the syntax "break
> template;"
>
> Then the template code becomes something which I think is clearer, and
> closer to how I'm actually thinking about things:
> template Parse(char[] str) {
> static if(str.length == 0) {
> alias struct {} Parse;
> break template;
> }
>
> // do lots of other complex stuff
> }
>
> Russ
I ran into this too when attempting some compile-time parsing. While I haven't attempted anything since compile-time
function evaluation (CTFE) was introduced, I did devise the following technique for templates:
template ParseTerm(){
const char[] Reason = null; // is non-null for any term that fails, and contains the reason
const bool Passed = true; // is false for any term that fails
alias Foobar Result; // where foobar is any value that you wish to "return" from this term.
}
As long as all your templates in your parser adhere to this "interface", you can do things like this:
template ParseSomething(char[] str){
alias ParseSomethingElse!(str) Term1;
static if(Term1.Passed){
alias Term1.Result Result; // return the result (could be anything really)
const char[] Reason = null;
const bool Passed = true;
}
else{
alias Tuple!() Result; // return an 'empty' result
const char[] Reason = "Parse failure: " ~ Term1.Reason;
const bool Passed = false;
}
}
... then use 'ParseSomething' in the same manner as 'ParseSomethingElse' elsewhere in your parser.
--
- EricAnderton at yahoo
More information about the Digitalmars-d
mailing list