2016-01-31 143 views
0

我一直试图长年建立一个实现GrammarASTVisitor的访问者。有没有办法访问一个语法根据

我加载一个Grammar对象的语法规则:

final Grammar g = Grammar.load("....dslGrammar.g4"); 

在那之后,我想用我的执行GrammarASTVisitor接口的访问语法的AST

public class DSLGrammarVisitor implements GrammarASTVisitor { 

    @Override 
    public Object visit(GrammarAST node) 
    { 

    } 

    @Override 
    public Object visit(GrammarRootAST node) 
    { 
     return null; 
    } 

    @Override 
    public Object visit(RuleAST node) 
    { 
     return null; 
    } 

    @Override 
    public Object visit(BlockAST node) 
    { 
     return null; 
    } 

    @Override 
    public Object visit(OptionalBlockAST node) 
    { 
     return null; 
    } 

    @Override 
    public Object visit(PlusBlockAST node) 
    { 
     return null; 
    } 

    @Override 
    public Object visit(StarBlockAST node) 
    { 
     return null; 
    } 

    @Override 
    public Object visit(AltAST node) 
    { 
     return null; 
    } 

    @Override 
    public Object visit(NotAST node) 
    { 
     return null; 
    } 

    @Override 
    public Object visit(PredAST node) 
    { 
     return null; 
    } 

    @Override 
    public Object visit(RangeAST node) 
    { 
     return null; 
    } 

    @Override 
    public Object visit(SetAST node) 
    { 
     return null; 
    } 

    @Override 
    public Object visit(RuleRefAST node) 
    { 
     return null; 
    } 

    @Override 
    public Object visit(TerminalAST node) 
    { 
     return null; 
    } 
} 

所以,从文件中加载语法后,我这样做:

GrammarASTVisitor v = new GrammarASTVisitorImpl(); 
g.ast.visit(v) 

之后,执行visit(grammarRootAST)方法。但是,我刚刚意识到我还没有弄清楚地球上的孩子们究竟该如何参观。我不太清楚如何让孩子的AST节点保持其类型

我试着node.getChildren(),但它返回一个List<? extends Object>,因此对GrammarASTVisitor没有visit(Object)法实施visit(Object)

我试着node.getChildrenAsArray()也,但是,每一个项目是一个GrammarAST节点,而不是RuleASTSetASTTerminalAST等等...

任何想法?

回答

1

不幸的是,Java不支持双重调度。您必须手动覆盖访问(GrammarAST节点),该节点通过节点的类进行切换并分派给适当的方法。其实他们应该给一些抽象类来做到这一点,但它不存在。

所以基本上类似下面(写在XTEND,但你可以将其转换成Java)应该做的伎俩代码:

GrammarASTVisitor() { 
override visit(GrammarAST node) { 
    node.children?.forEach[ 
     switch(it) { 
      case RuleAST: visit(it as RuleAST) 
      case BlockAST: visit(it as BlockAST) 
      case OptionalBlockAST: visit(it as OptionalBlockAST) 
      case PlusBlockAST: visit(it as PlusBlockAST) 
      case StarBlockAST: visit(it as StarBlockAST) 
      case AltAST: visit(it as AltAST) 
      case NotAST: visit(it as NotAST) 
      case PredAST: visit(it as PredAST) 
      case RangeAST: visit(it as RangeAST) 
      case SetAST: visit(it as SetAST) 
      case RuleRefAST: visit(it as RuleRefAST) 
      case TerminalAST: visit(it as TerminalAST) 
      default: visit(it as GrammarAST) 
     } 
    ] 
    node 
} 

override visit(GrammarRootAST node) { 
    node.children?.forEach[this.visit(it as GrammarAST)] 
    node 
} 

... 
+1

非常感谢!我一直在等待很久! – Jordi

相关问题