[stringtemplate-interest] [ST4] How to apply multiple "format"s to an expression?

Udo Borkowski ub at abego-software.de
Sun Feb 20 23:41:13 PST 2011


Hi Collin,

> Lets contrast this with what one might do with one or more ModelAdapters.

thanks for showing the relation to ModelAdapters. I never thought of it this way but you are right, it looks like using a ModelAdapter solves many of my issues. Great. Syntactically I like the ModelAdapter approach even better.

The MultiFormatStringRenderer also has its virtue as one may reuse existing (third party) string renderers without writing extra code (if applicable). And with a string renderer the template may pass in "parameters", like "%15s". 

So I would go the pragmatic way and use both.

Udo


On 21.02.2011, at 03:17, Collin Fagan wrote:

> Okay so I did some hacking and have this:
> 
> STGroup group = new STGroupFile("templates/MultiFormatStringRenderer.stg");
> 
> AttributeRenderer stringRenderer = ... your string renderer here ...
> group.registerRenderer(String.class, new MultiFormatStringRenderer(stringRenderer, " "));
>         
> ST st = group.getInstanceOf("main");
> st.add("string", "     Renderers are fun!     ");
> 
> System.out.println(st.render());
> 
> -----
> 
> main(string) ::= <<
> String - Raw Value = "<string>"
> 
> String - format="strip" = "<string; format="strip">"
> String - format="strip uncapitalize" = "<string; format="strip uncapitalize">"
> String - format="strip uncapitalize swapCase" = "<string; format="strip uncapitalize swapCase">"
> 
> >>
> 
> And it outputs:
> 
> String - Raw Value = "     Renderers are fun!     "
> 
> String - format="strip" = "Renderers are fun!"
> String - format="strip uncapitalize" = "renderers are fun!"
> String - format="strip uncapitalize swapCase" = "RENDERERS ARE FUN!
> 
> It supports splitting on any regex delimiter, because it just uses String.split() underneath. I got this far and began to wonder if this is really worth it. First it will never work for the general case, just for String. That might surprise someone who might attempt a "cross-type" rendering scenario. 
> 
> Example:
> 
> <trueBooleanValue; format="YN uncapitalize">
> 
> Lets pretend there is a Boolean renderer for which YN transforms a Boolean value into "Yes" and "No" strings. One  might assume that the above statement would produce "yes" but this in fact is not the case, it's a error because the entire string is passed to BooleanRenderer and not my special StringRenderer. A renderer is just not going to get this done on it's own, you would need a language change. 
> 
> 
> Lets contrast this with what one might do with one or more ModelAdapters.
> 
> <trueBooleanValue.YN.uncapitalize>
> 
> This would produce the expected "yes" output and is more concise then the format statement. 
> 
> For your specific example:
> 
> <n;format="|upper|%15s">
> 
> If you used a model adapter it would look like this:
> 
> <n.upper.("%15s")>
> 
> So it occurs to me ... why would anyone use a renderer with a parameter when they can just write a model adapter? I know, I know what you are thinking.. "booo! hissss! renderers are great! Model adapters are not for rendering!" Which is true but syntactically they are very convenient and are "chain friendly". 
> 
> What do others think?
> 
> Collin
> 
> 
> On Sat, Feb 19, 2011 at 8:58 AM, Udo Borkowski <ub at abego-software.de> wrote:
> Hi Colin,
> 
>> Humm ... but it would be interesting to build a Renderer that took a delimited set of format parameters.  
>> 
>> <n;format="%15s,upper">
>> 
>> Of course comma works great here but not for the general case .. maybe make the delimiter a parameter to the renderer? I might slap something together to try it out. 
> 
> 
> this sounds like a great idea.
> 
> May I throw in some suggestions?
> 
> Rather than using the commonly used separator "," I would use the pipe '|' character to separate the multiple format parts (by default). Actually the new renderer to be written has some "pipe" functionality: the output of one renderer is the input for another and so on. So ‘|‘ also makes semantically.
> 
> Of cause there should be the option to change the separator. However I would not (only) make this a parameter to the renderer but also make this an option in the format string itself. E.g. in one application you may want to use the same renderer (instance) with different separators.
> 
> Here two possible formats:
> 
> <n;format="|upper|%15s">
> 
> Here the initial ‘|‘ indicates the pipe formatting and the pipe renderer splits the rest of the format text and processes each format one after another. 
> 
> To define a different separator one could start with ‘|x|‘, i.e. the new separator is framed by two pipe chars. E.g. to use the ";" one would write:
> 
> <n;format="|;|upper;%15s">
> 
> 
> An alternative syntax may start with a keyword to indicate we want to do piping. The character following the keyword is then used as the separator. E.g. if we use the keyword "pipe" the tag would look like this:
> 
> <n;format="pipe|upper|%15s">
> 
> or for the semicolon case:
> 
> <n;format="pipe;upper;%15s">
> 
> I would prefer the second syntax. In that case there would not even be the need to decide for a good "default separator" ;-)
> 
> 
> Udo
> 
> 
>  
> On 18.02.2011, at 23:53, Collin Fagan wrote:
> 
>> This could actually be done by extending the ObjectModelAdaptor model adapter to have it check for such a method.
>> 
>> Such an adapter is available as part of STRUM.
>> PublicMethodModelAdapter - access any public method from ST
>> Humm ... but it would be interesting to build a Renderer that took a delimited set of format parameters.  
>> 
>> <n;format="%15s,upper">
>> 
>> Of course comma works great here but not for the general case .. maybe make the delimiter a parameter to the renderer? I might slap something together to try it out. 
>> 
>> Collin
>> 
>> On Fri, Feb 18, 2011 at 4:29 PM, Sam Harwell <sharwell at pixelminegames.com> wrote:
>> Does this work:
>> 
>>  
>> <(upper(n)); format="%-15s">
>> 
>>  
>> With this definition of upper(x)?
>> 
>>  
>> upper(x) ::= <<
>> 
>> <x; format="upper">
>> 
>> >> 
>> 
>>  
>> Also, here’s an interesting case where if <x.y> checked for a method y() (zero parameters and non-void return value), you could use <n.toUpperCase; format="%-15s">. This could actually be done by extending the ObjectModelAdaptor model adapter to have it check for such a method.
>> 
>>  
>> Sam
>> 
>>  
>> From: stringtemplate-interest-bounces at antlr.org [mailto:stringtemplate-interest-bounces at antlr.org] On Behalf Of Udo Borkowski
>> Sent: Friday, February 18, 2011 4:02 PM
>> To: stringtemplate-interest List
>> Subject: [stringtemplate-interest] [ST4] How to apply multiple "format"s to an expression?
>> 
>>  
>> Hi,
>> 
>>  
>> I would like to generate a constant definition like this:
>> 
>>  
>>             public static final int ABC             = 123;
>> 
>>             public static final int GHIJKLMN        = 456;
>> 
>>  
>> To make sure the "="s are aligned I can use the Java String format padding feature, e.g. use a template like this:
>> 
>>  
>> t1(n,v) ::= <<
>> 
>> public static final int «n;format="%-15s"» = «v»;
>> 
>> >> 
>> 
>>  
>> However the name is given in mixed case and I need to "upper" it, e.g. with something like this:
>> 
>>  
>> t2(n,v) ::= <<
>> 
>> public static final int «n;format="upper"» = «v»;
>> 
>> >> 
>> 
>>  
>> Is there a way to combine both formats, so I get an uppercased, right padded name?
>> 
>>  
>>  
>> Udo
>> 
>>  
>> 
>> _______________________________________________
>> stringtemplate-interest mailing list
>> stringtemplate-interest at antlr.org
>> http://www.antlr.org/mailman/listinfo/stringtemplate-interest
>> 
>> 
> 
> 

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.antlr.org/pipermail/stringtemplate-interest/attachments/20110221/9e867ee4/attachment-0001.html 


More information about the stringtemplate-interest mailing list