Hi all,
I'm currently working on a project to revamp an existing code generation system
my team uses and add some new features. The generator takes a set of
pseudo-class/struct definitions like
class foo
{
Int X;
SomeClass Y;
map<int,int> Z;
};
And generates an output C++ class with a bunch of decoration.
class foo
{
public:
int getX() const { return mX; }
void setX(int val) { mX = val; }
SomeClass &getY() { return mY; }
Map<int,int> &getZ() { return mZ; }
Private:
Int X;
SomeClass Y;
map<int,int> Z;
};
(There's a lot more to the specification, but this is good enough to
demonstrate my issues).
One of our goals is to support a lot more than C++, and to allow people to
override the generation as necessary to fit into their projects. ANTLR +
StringTemplates seems to suit our needs perfectly. Our old model used
flex/bison, a custom tree of classes (since classes can have inner classes, and
we support namespaces), and a gnarly set of hand-written C++ output code. Yuck.
So I've spent the past few weeks getting into ANTRL, reading the manual,
reading the reference, trying out the samples, building samples, toy languages
etc. I'm now in the process of prototyping out our new tool, but I've run into
a dilemma on the overall structure.
What I'd like to do is parse everything into an AST, then build a tree walker
that outputs templates (and maybe another walker to do some error
verification). But what I can't figure out is how you separate the MVC model
parts using a tree walker and templates. I want to have a main template
interface such that the "big items" (class, member, etc) are put out through
there, and a subtemplate interface for overriding something like C++. In that
way, if I want to change the type of "map" to be "custommap" I just need to
change the template that prints out a map type. What I don't get though is
that with a tree walker you get one stab at outputting text. So if I have a
template like:
class $className$
{
public:
$members$
};
I can see how the top section gets printed out:
class : ^(CLASS n=SYMBOL m=members*) - > classTemplate(name={$n.text},
members={$m}) ;
member : ^(int n=SYMBOL) -> intMemberTemplate(name={$n.text}) ;
| ^(t=SYMBOL n=SYMBOL) -> classMemberTemplate(name={$n.text}, type={$t}) ;
;
Where intMemberTemplate and classMemberTemplate print out the getter/setter
funcs from above.
What I don't see how to do is have two sections where the class walks through
the members. It goes through them once, emits their templates once, and moves
on. To generate the C++ class above, I need two passes - one to generate the
getters/setters, one to do the variable declarations. I could do it in one
pass with lots of public/private keywords, but the generated code is less
readable. I could duplicate the tree, but then I'm forcing view structure into
the model, which seems to go against the whole ST philosophy. I could also
create a "member" object and use its attributes in the template, but I guess
that seems a little less clean because then I'm really walking through some
other data structure instead of using the tree walker.
One other reason I want to use the tree walker to print out the various
getters/setters and declarations is that it has built in context as to what
each member is. If I just have something like
private:
$members:declVar()$
};
Then the template "declVar" either needs to have a bunch of if..else statements
to split up the member type and print out the right thing, or I need to do
something like have a Member.toString() function to do the dirty work of
formatting the declaration. That of course means potentially putting in view
code in the model, which I'd really like to avoid.
So bottom line: am I leaning to far in the "do everything in the tree walker"
direction? Has anyone had a problem where one input can generate several
templates, and each template might have several different variations depending
on the input? I feel like I should have seen this done somewhere, but I
looked through a lot of examples and didn't see exactly what I wanted.
Any advice here is appreciated.
Thanks
Ryan
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"il-antlr-interest" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/il-antlr-interest?hl=en
-~----------~----~----~----~------~----~------~--~---
List: http://www.antlr.org/mailman/listinfo/antlr-interest
Unsubscribe:
http://www.antlr.org/mailman/options/antlr-interest/your-email-address