[antlr-interest] Using own ASTLabelType and quantification

John B. Brodie jbb at acm.org
Tue Jan 12 10:09:41 PST 2010


Greetings!

On Tue, 2010-01-12 at 17:06 +0100, Olaf Keijsers wrote:
> Greetings,
> 
> I am trying to make a treewalker for my grammar in order to check if it 
> contains nondeterminism. I would like to be able to set some properties for 
> every node I encounter, so I figured it would be a good idea to use my own 
> ASTLabelType.
> 
> I have set "ASTLabelType=GrooveTree" in my options, and my grammar uses this 
> labeltype now, but I get the following exception when trying to use the 
> checker:
> java.lang.ClassCastException: org.antlr.runtime.tree.CommonTree cannot be 
> cast to groove.control.parse.GrooveTree
>  at 
> groove.control.parse.GCLDeterminismChecker.program(GCLDeterminismChecker.java:139)
> 
> This line contains:
> root_0 = (GrooveTree)adaptor.nil();
> 
> and is part of the program() method. Somehow I think this is a beginner's 
> error, but I cannot find the solution. I have tried to work around it by 
> using the default ASTLabelType and keeping a Map<CommonTree,Boolean> to keep 
> track of the property I would like, but this seems cumbersome. Could anyone 
> point me in a good direction?

You need to setup a tree adaptor so that the runtime knows how to
construct your nodes.

These are the things I had to do in order to get my own ASTLabelType,
note that my AST is called ExprAST -- so replace all occurrances of that
string below with yours. also note that I did this over a year ago using
an earlier version of ANTLR v3, so altho this still works, just re-ran
my tests, today's version of ANTLR may make some of my steps simpler
and/or entirely un-necessary... YMMV

1) in the grammar add the ASTLabelType= option (as you have already
done)

2) create your new tree node class, ensuring that it extends CommonTree.
Here is my ExprAST (note that Type is also one of my classes):

//----begin ExprAST here....
import org.antlr.runtime.Token;
import org.antlr.runtime.tree.*;

public class ExprAST extends CommonTree {

   public Type type;

   public ExprAST() {
      super();
      type = null;
   }

   public ExprAST(Token tok) {
      super(tok);
      type = null;
   }

   public ExprAST(ExprAST tree) {
      super(tree);
      this.type = tree.type;
   }

   public ExprAST(Token tok, Type type) {
      super(tok);
      this.type = type;
   }

   @Override public Tree dupNode() {
      return new ExprAST(this);
   }

   @Override public String toString() {
      final String result;
      if (type==null) {
         result = super.toString();
      } else {
         result = String.format("%s[%s]",
                     super.toString(),type.nickName());
      }
      return result;
   }
}
//----end ExprAST

3) copy org.antlr.runtime.tree.CommonErrorNode from the ANTLR run-time
sources. I called mine ExprASTErrorNode. Edit your copy so that is
extends your new tree node class rather than CommonTree.

4) create an instance of the adaptor class, i do this in my main:

//---begin adaptor code here...
   // Custom adaptor to create ExprAST node type
   private static final TreeAdaptor adaptor = new CommonTreeAdaptor() {
         @Override public Object create(Token payload) {
            return new ExprAST(payload);
         }
         @Override public Object dupNode(Object old) {
            return (old==null)? null : ((ExprAST)old).dupNode();
         }
         @Override public Object errorNode(TokenStream input,
                                           Token start, Token stop,
                                           RecognitionException e) {
            return new ExprASTErrorNode(input, start, stop, e);
         }
      };
//----end adaptor code.

5) call the parser's setAdaptor method with the above adaptor. I invoke
my parser with something similar to this:

//----begin parser invocation code here...
   ExprLexer lexer = new ExprLexer(...whatever....);
   CommonTokenStream tokens = new CommonTokenStream(lexer);
   ExprParser parser = new ExprParser(tokens);
   parser.setTreeAdaptor(adaptor);
   ExprParser.program_return p_result = parser.program();

   ast = p_result.tree;
//----end parser invocation code.

> 
> Thanks!

Hope this helps...
   -jbb




More information about the antlr-interest mailing list