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