[antlr-interest] improving template support in antlr v3
Terence Parr
parrt at cs.usfca.edu
Fri Dec 23 12:24:57 PST 2005
On Dec 23, 2005, at 3:12 AM, hwk.cortex-brainware at t-online.de wrote:
> I think there are some common scenarios:
>
> 1) Call different templates (even when I only return one template,
> I might
> use some templates during calculation). We could use a common
> syntax here
> like $ST["name"] to extract a template form the group. This would be a
> reserved word.
Yes, i have been working with this cool start-up company recently and
I have been trying to use the template stuff. I have not needed
multiple templates from a single rule, but let me add my own
frustrations here and we can probably come up with a nice bit of
extension. John Mitchell suggested this exact strategy...get
something working (avoiding the complicated thing I was designing)
and then try to build something with it! ;)
So, I do this a few times in a Java grammar:
StringTemplate fcallST = templateLib.getInstanceOf("fcall");
fcallST.setAttribute("ids", $type.st); // type is a rule reference
above
$anEnclosingTemplateVisibleHere.setAttribute("fcalls",fcallST);
Wouldn't it be nice to do as you say (a rewrite like constructor but
in an action):
StringTemplate fcallST = $fcall(ids=$type.st);
and then we could have a syntax like pyStringTemplate to use array
syntax instead of setAttribute:
$anEnclosingTemplateVisibleHere["fcalls"] = fcallST;
The problem of course is clear: The dollar syntax $x.y is way to
simple to handle the above and it's ambiguous anyway. We'd need a
keyword as you say I think, but that makes it messy.
<sidetracked>
Actually, given that I must be consistent across output options, how
will we build trees inline?
{AST t = ^($ID.text, $INT.text);}
I suppose we could make ^ significant like we did with #(...)
before. Hmm...What would a node constructor be?
^ID["blort]
I suppose that would be ok.
</sidetracked>
So, do we need a special symbol for inline stringtemplate stuff?
Ick. @ is action, $ is attribute. Hm...keyword is probably better.
Ack...can't just randomly look for a keyword...need a symbol.
Hmm...well, what about, symbol plus braces:
StringTemplate fcallST = ${fcall(ids=$type.st)};
${anEnclosingTemplateVisibleHere["fcalls"] = fcallST};
I don't like overloading $ though but I hate to create another
special symbol just for templates like:
StringTemplate fcallST = %{fcall(ids=$type.st)}
%{anEnclosingTemplateVisibleHere["fcalls"] = fcallST};
Is there some generic thing I could do with %{...}? Ick. Would they
have to nest?
%{anEnclosingTemplateVisibleHere["fcalls"] = %{fcall(ids=$type.st)}};
Probably. To me that is not very readable to the casual observer
where the explicit is very readable.
Perhaps your $templates::fcall(ids=$type.st) would work with
"templates" being the keyword / built-in scope of templates.
Actually that would work. :)
StringTemplate fcallST = $templates::fcall(ids=$type.st);
$anEnclosingTemplateVisibleHere.setAttribute("fcalls",fcallST);
It saves a bit of typing and is more clear. :)
> Better yet: How about defining a string template group in the
> grammar:
>
> group MyTemplates; // This only a defines a property in the parser
> to set a
> string template group. Later, we could allow to define the
> templates inline.
I think you want this to be dynamic so, as you request below, you can
reset the template group for each pass using setTemplateLib().
> Then one could call templates of the group using a syntax like
> MyTemplates::Name. There would be a default group, which is used if
> the
> group name is omitted.
We can just use the $templates::name(...) generic mechanism so we can
dynamically change the actual group. Your way might be useful with
the ST interface I plan on implementing. In this way, I could verify
that your template names actually make sense. Heh, i like it!
> -> xxx calls default group "xxx" and returns this as result
> -> MyTemplates::xxx calls "xxx" in the the MyTemplates group and
> returns
> this as result.
Interesting. You want to be able to define multiple template
libraries? Ok, so
$templates::fcall(...)
$MyTemplates::blort(...)
I dislike overriding the $scope::x syntax so much, but it seems like
it would work. How would we specify the new template groups?
templates Java;
templates Debug;
then you could say $Java::fcall(...) and $Debug::dump(...). But, the
lib names should be interfaces so you're not locked into a specific
template group, right? This would generate methods like:
setJavaTemplateLib(...)
in the parser so you could set the actual lib.
How often would this multiple template lib thing be used do you think?
> Within actions $MyTemplates::xxx would call the template.
>
> Now, we could nest them:
>
> -> ResultTemplate(MyTemplates::xxx($Name), MyTemplates::yyy($Id)), or
> whatever...
Yup.
Oh, right we'd need to allow
-> Java::fcall(...)
syntax too.
> 2) Build a collection of templates. These are useful to pass them
> to other
> templates...
>
> Currently, only the result of a rule can be added to a list. This
> could be
> expanded to support multiple lists, one per template.
>
> Just allow the same syntax to be used in front of each template call:
> myList+=MyTemplates::xxx adds the template to a list called myList.
Is that in an action? You can pass in multiple templates to fill
with templates you create in that rule. You can pass multiple return
values back and just add to a list manually. How often do you need
to return multiple templates though? When I need this I just access
the outer template where they will go and then setAttribute for each
new template. I've yet to need multiple return templates.
> Maybe we should add the possibility to define lists in a scope:
> scope global {
> Templatecollection myList; // or something like that
> }
>
> Use it like this: global::myList+=MyTemplates::xxx(...).
We're getting closer and closer to the simple neutral action language
I was thinking of adding later ;) Hm...this is getting a big much. I
think:
global::myList.add($MyTemplates::xxx());
would be just as good ;)
> Overall, I think, template manipulation within ANTLR should be
> expanded. Of
I plan on it...just trying to let actual need guide us. :)
> course, I can code that now within actions but it would be far more
> user
> friendly if normal cases could be expressed in a standard and
> uniform way.
Yes, let's come up with a nice extension.
> I have several 2.7.5 grammars in C# and Java, which only differs in
> the
> action code because of different method and class names. Using
> ANTLR 3 with
> templates I was hoping to move all differences to a set of
> templates. This
> only works if templates can be manipulated within ANTLR itself.
Can't you just a different template group with setTemplateLib?
> Kind regards
>
>
> BTW: I was thinking about using multiple passes using the same
> action code,
> but using different template groups for each pass...
Are you using setTemplateLib?
Let me add my own frustrations now.
This is a drag:
packageDefinition
: 'package' identifier SEMI -> {$identifier.st}
;
Could we do this?
packageDefinition
: 'package' identifier SEMI -> identifier
;
What if we always returned the template for a single element?
type
: identifier
| builtInType
;
the template for identifier / builtInType would be autocopied to
$type.st return value. I don't like this actually... it's not
consistent with having multiple elements in a production. Perhaps
type
: identifier -> identifier
| builtInType
;
is "better". Weird looking though.
Here is a case where I might have just plain foo instead of a.b.c.
In either case I need to set the return type. I hate doing ( x ->
template(...) ) syntax in the middle of a rule. I want that -> on
the end! Here is what I do now:
identifier
: (i=IDENT -> qid(id={$i.text}))
( DOT i=IDENT {$identifier.st.setAttribute("id",$i.text);} )*
;
Oh, actually we can do this properly even now. Duh, just queue up
the IDs.
identifier
: ids+=IDENT ( DOT ids+=IDENT )*
-> qid(id={toStrings($ids)})
;
I've posted this to the blog too.
http://www.antlr.org/blog/antlr3/rewrite.tml
Ter
More information about the antlr-interest
mailing list