[antlr-interest] Code generation design philosophy?

Butterfoss, Ryan RButterfoss at ea.com
Wed Aug 12 17:48:34 PDT 2009


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




-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.antlr.org/pipermail/antlr-interest/attachments/20090812/8f8d02cd/attachment.html 


More information about the antlr-interest mailing list