[antlr-interest] Article against TreeWalkers

Jeff Barnes Jeff.Barnes at codesic.com
Wed Mar 8 12:59:02 PST 2006


Jeff sez:
 
>Would it be fair to say that one big switch statement is not as good as an interface?
> 
>
Andy sez:
I don't think so. I'm not sure how an interface could even replace a big
switch statement in the case I show there, where we're
saying "I'm processing a particular AST node, and here's a huge switch
statement on the node type". I suppose we could
have a bunch interfaces (e.g. "ImABinaryOperatorNode"), and have the AST
node implement one of them, but that
doesn't seem to make things any cleaner to me.

Jeff sez:

If using an interface doesn't seem cleaner, then you probably are better off with a big switch statement. Me? I groan whenever I have to look at a big switch statement. But my primary reason for using an interface is by extension; I want to give the metatype as much responsibility as I can. I can see similarity between the tree metalanguage and metamodel. I just wish there were a mechanism for explicit constraints in the tree grammar without going to code.

My lexers get "primitive" values. For example:

COMMA:
    ","
;
    
protected
DIGIT:
    '0'..'9'
;

protected
DOUBLE:
    INT '.' INT
;
    
protected
ID:
    (LETTER | '_') (DIGIT | LETTER | '_')*
    ;
    

...


My parsers make sure the words form structurally valid sentences:

model 
{
}
:
    object object
;

object
{
}
:
    LPAREN! OBJECT^
    typeid:ID 
    (
        param
    )*
    (
        attribute
    )* 
    RPAREN!
;

attribute
{
}
:
    ID^
    value 
;

...

And my trees make sure the parser doesn't return nonsense as well as check other "paragraph" structure:

pkg
{
        String component = null;
}
:!
    #(
        OBJECT
        pkgid:ID {pkgid.getText().equals("Class_Category")}? {## = #pkgid;}
        name:STRING {#pkgid.addChild(#name);}
            (
                {_t.getText().equals("logical_models")}? 
                    #(ID 
                        #(LIST ID {component = _t.getFirstChild().getText(); }
                            (   {(_t.getFirstChild() != null) && {(_t.getFirstChild().getText().equals("Class_Category"))}? p:pkg {#name.addChild(#p);}
                            |   {(_t.getFirstChild() != null) && {(_t.getFirstChild().getText().equals("Class"))}? c:clazz {#name.addChild(#c);}

...
                            )*
                        )
                    )
            |   {_t.getText().equals("statemachine")}? #(smid:ID sm:state_machine {#name.addChild(#smid); #smid.addChild(#sm);})
            |!  attr:attribute
            )+
        
    )
;

clazz
{
    int irCt = 0;
}
:!
    #(
        OBJECT
        clid:ID {## = #(#clid,#[ID,"Name"]);}
        name:STRING {#clid.getFirstChild().addChild(#name);}
        (   {_t.getText().equals("class_attributes")}?  
                #(atts:ID {#clid.addChild(#atts);}
                    #(LIST ID 
                        (
                            ca:class_attribute {#atts.addChild(#ca);}
                        )*
                    )
                )
        |   {_t.getText().equals("nestedClasses")}? 
                #(nc:ID {#clid.addChild(#nc);}
                    #(LIST ID 
                        (
                            c:clazz {#nc.addChild(#c);}
                        )*
                    )
                )
        |   {_t.getText().equals("superclasses")}? 
                #(sups:ID {#clid.addChild(#sups);}
                    #(LIST ID 
                        (
                            ir:inheritance_relationship {#sups.addChild(#ir);}
                        )*
                    )
                )
        |   {_t.getText().equals("statemachine")}? #(smid:ID sm:state_machine {#clid.addChild(#smid); #smid.addChild(#sm);})
        |!  attr:attribute! 
        )*
    )
;

class_attribute
{}
:!
    #(
        OBJECT
        attid:ID {attid.getText().equals("ClassAttribute")}? {## = #(#attid,#[ID,"Name"]);}
        name:STRING {#attid.getFirstChild().addChild(#name);}
        (
            {_t.getText().equals("type")}?
                #(id1:ID sv:STRING) {#attid.addChild(#id1); #id1.addChild(#sv);}
        |
            {_t.getText().equals("static")}?
                #(id2:ID bv1:BOOLEAN) {#attid.addChild(#id2); #id2.addChild(#bv1);}
        |
            {_t.getText().equals("derived")}?
                #(id3:ID bv2:BOOLEAN) {#attid.addChild(#id3); #id3.addChild(#bv2);}
        |! attribute
        )+
    )
;

 

Now I just gotta figure out a way to get the state of the tree without going to code (_t, etc.).

Jeff



More information about the antlr-interest mailing list