[antlr-interest] LIP pg. 285 11.4 Rewriter. How do you do it with ANLTR 3?

Stephen Tuttlebee themightystephen at googlemail.com
Thu Mar 17 05:56:17 PDT 2011


Hi Eric

I don't know if I understand your question completely (I haven't read 
the previous questions you mentioned), but are you simply asking how you 
rewrite a tree using ANTLR? Or were you actually asking how ANTLR 
actually IMPLEMENTS this rewriting under the hood (i.e. what code does 
it generate to do the rewriting)? Or something else?

If you were asking the first question, then I can provide a fairly 
simple example from a couple of grammars I have been working on recently 
(I don't know if the example is too simple since it only alters the tree 
in a very minor way, and maybe you're thinking along the lines of larger 
and more substantial changes to the tree).

I have the 'phase 1 grammar' (JavaBPhase1Parser.g) that does the parsing 
and has tree rewrite rules to build an AST. This grammar has the 
following options:
options {
     language = Java;
     output = AST;
     tokenVocab = JavaBLexer;
}

This grammar just builds a tree in the normal way.

My 'phase 2 grammar' (JavaBPhase2WalkerSem1.g) is a tree grammar that 
reads that AST, performs some semantic analysis of the input and spits 
out an almost identical AST. It has similar options as before but the 
really important one here is the rewrite=true option:
options {
     language = Java;
     output = AST; // since we are performing a tree rewrite, as well as 
reading in an AST, I will also be outputting an AST
     rewrite = true; // <---- this is the key option here
     tokenVocab = JavaBPhase1Parser;
     ASTLabelType = CommonTree; // this option here because we're 
reading in a tree and ANTLR would like to know the type of the nodes
}

The rewrite=true causes the tree to be spat out just the same as the 
input tree except where you specify otherwise. For example, in one rule 
I perform some semantic analysis that informs me on how to rewrite the tree:

compositionExpression
     @init {
     boolean compositionComponent = false; // this is only here rather 
than further below where I would want to use it because in the code 
generated by ANTLR the variable is out of scope if I declare it down there
     }
     : ... // other tree rule
     | ... // other tree rule
     | ^(PLAIN_OR_COMPOSITION_COMPONENT ^(IDENT IDENTIFIER))
       { .... some actions that perform semantic analysis (look up in 
the symbol table) to decide if compositionComponent is true or false }
       -> {compositionComponent}? ^(COMPOSITION_COMPONENT ^(IDENT 
IDENTIFIER))
       ->                                                
^(PLAIN_COMPONENT ^(IDENT IDENTIFIER))


In this example I am performing a very simple tree rewrite by simply 
changing the imaginary token of a subtree's root node, but you could 
change the entire subtree by changing the rewrite rule(s) to produce a 
completely different subtree.

For larger, more 'structural' changes to the tree, I would imagine you 
need to do a fair amount of passing subtrees around as parameters / 
return values between rules so that you have access to the subtrees in 
the rules that need them. p170 of the ANTLR reference book has an 
example of this kind of thing (example is used in doing tree 
construction in a *parser* grammar but you can do exactly the same in a 
tree grammar).

You can also have semantic predicates (I think that's the proper name) 
before multiple rewrite rules to rewrite the tree in different ways 
depending on what the boolean expression in the semantic predicates 
evaluates to. See page 181 of ANTLR reference for an example in the 
variableDefinition rule:
variableDefinition
     : modifiers type ID ('=' expression)? ';'
        -> {inMethod}? ^(VARIABLE ID modifier* type expression?) // 
semantic predicate used here
        ->                        ^(FIELD ID modifier* type expression?)
     ;
Again, that example is used in doing tree construction in a parser 
grammar but you can do exactly the same in a tree grammar.

Bear in mind though (at least I think this is the case...), that with 
these semantic predicates you have to ensure that there is a default 
case which specifies the tree to be built if all the other previous 
semantic predicates evaluate to false.

Hope this helps.

Stephen


More information about the antlr-interest mailing list