[prev in list] [next in list] [prev in thread] [next in thread] 

List:       stringtemplate-interest
Subject:    [stringtemplate-interest] Understanding template recursion
From:       strohman () cs ! umass ! edu (Trevor Strohman)
Date:       2007-05-26 16:56:11
Message-ID: 7E1CDAC0-9492-4B73-99DA-55D763F79E3A () cs ! umass ! edu
[Download RAW message or body]


On May 26, 2007, at 10:53 AM, John Snyders wrote:

>
>> What I'm really trying to do is output nested loops.  If my list  
>> is a,b,c,d, I want, for example:
>>     for( int ai=0; ai<a; ai++ ) {
>>         for( int bi=0; bi<b; bi++ ) {
>>             for( int ci=0; ci<c; ci++ ) {
>>                 for( int di; di<d; di++ ) {
>>                     ...
>>                 }
>>             }
>>         }
>>     }
>>
>> I can work around it by making each loop a different method in the  
>> exported code, like:
>>     for( int ai=0; ai<a; ai++ ) {
>>         bLoop(ai);
>>     }
>> and I can change my model so that I have a.next = b, b.next = c,  
>> c.next = d.  I prefer the nested loop, though.

> I'm not sure exactly what you are trying to describe here. Are a,  
> b, c, d lists or sizes of some list? And by method in exported code  
> do you mean template?

'a', 'b', 'c' and 'd' are just letters as far as StringTemplate is  
concerned.  The template is writing a Java source code file.  As an  
even simpler example, suppose I have a list called items = [ 'a',  
'b', 'c', 'd' ], and I want to use StringTemplate to make this Java  
method:

public void myMethod() {
	if( a ) {
		if( b ) {
			if( c ) {
				if( d ) {
					doSomething();
				}
			}
		}
	}
}

This is what I mean by "method in the exported code".  I am using  
StringTemplate to generate this method.

> You don't need a separate template to do nested loops here is an  
> example
> With data that looks like this in JSON format (a list of lists)
> {"nested": [
>  [ "a", "b", "c", "d" ],
>  [ 1, 2, 3, 4 ],
>  [ "i", "ii", "iii", "iv" ]
>  ]
> }
> And a group file like this
> group group1;
>
> main() ::= <<
> $nested: { l1 |
>   level 1 $l1: { l2 | level 2 $l2$ }$
> }$
> >>
> calling main produces this output (blank lines removed)
>    level 1 level 2 a level 2 b level 2 c level 2 d
>    level 1 level 2 1 level 2 2 level 2 3 level 2 4
>    level 1 level 2 i level 2 ii level 2 iii level 2 iv

This is different than what I'm trying to do, because your template  
has only two "levels".  I need one level for each item in the list.

Try this with STST (very nice tool, by the way):

(begin Recurse.stg)
group Recurse;

test() ::= "$rec(items)$"

rec(x) ::= <<
$if(x)$
if ( $first(x)$ ) {
         $if(rest(x))$
         $rec(rest(x))$
         $else$
         doSomething();
         $endif$
}
$endif$
 >>
(end Recurse.stg)

(begin recurse.js)
{ "items" : [ "a", "b", "c", "d", "e", "f", "g", "h" ] }
(end recurse.js)

% ./stst-run Recurse.test recurse.js
if ( a ) {
         if ( b ) {
                 if ( e ) {
                         if ( h ) {
                                 doSomething();
                         }
                 }
         }
}

You can see that it skips some letters.

By the way, I have worked around this problem by using nested  
methods.  It's not the perfect solution, but my code does work (and  
the result is much, much cleaner than using String.format to generate  
code)

Trevor





[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic