[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