没有办法访问GrammarRootAST

时间:2016-01-31 17:11:52

标签: antlr4

我多年来一直试图创建一个实现GrammarASTVisitor的访问者。

我在Grammar对象上加载语法规则:

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

之后,我正在尝试使用AST接口的实现来访问语法GrammarASTVisitor

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>,因此visit(Object)上没有GrammarASTVisitor方法来实现visit(Object)

我也尝试使用node.getChildrenAsArray()但是,每个项目都是GrammarAST个节点,而不是RuleASTSetASTTerminalAST等等...

有什么想法吗?

1 个答案:

答案 0 :(得分: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
}

...