2016-01-31 101 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

相關問題