没有办法访问 GrammarRootAST

there's no way to visit a GrammarRootAST

多年来我一直在尝试创建一个实现 GrammarASTVisitor.

的访问者

我正在 Grammar object:

上加载语法规则
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)方法。然而,我刚刚意识到我不太清楚到底如何访问 children。我不太明白 如何让 children AST 节点保持其类型

我试过 node.getChildren(),但是 returns 是 List<? extends Object>,所以 GrammarASTVisitor 上没有 visit(Object) 方法实现 visit(Object).

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

有什么想法吗?

遗憾的是Java不支持双重调度。您必须手动覆盖 visit(GrammarAST node) ,它由节点的 class 切换并分派到适当的方法。实际上,他们应该给出一些抽象的 class 来执行此操作,但它不存在。

所以基本上类似于下面的代码(用 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
}

...