antlr4 访问者不访问解析树中的节点

anltr4 visitor doesn't visit nodes in parse tree

我有一个使用 ANTLR4 处理 Java 文件的简单应用程序。

InputStream stream = String.class.getResourceAsStream("/sample-function.java");

Java8Lexer lexer = new Java8Lexer(CharStreams.fromStream(stream));
CommonTokenStream tokens = new CommonTokenStream(lexer);
Java8Parser parser = new Java8Parser(tokens);
ParseTree tree = parser.compilationUnit();

HighLevelClassVisitor visitor = new HighLevelClassVisitor();
System.out.println(visitor.visit(tree).toString());

我创建了一个简单的访问器,它应该 return string 完成对所有解析树节点的访问。

public class HighLevelClassVisitor extends Java8BaseVisitor<StringBuilder> {

    private StringBuilder sb = new StringBuilder();

    @Override
    public StringBuilder visitPackageDeclaration(PackageDeclarationContext ctx) {
        sb.append("Package declaration: ").append(ctx.packageName().getText());
        return sb;
    }

    @Override
    public StringBuilder visitNormalClassDeclaration(NormalClassDeclarationContext ctx) {
        sb.append("Class normal declaration: class ").append(ctx.Identifier().getText());
        return sb;
    }

    @Override
    public StringBuilder visitClassModifier(ClassModifierContext ctx) {
        sb.append("Class modifier: ").append(ctx.getText());
        return sb;
    }
}

但是当我执行应用程序时,它 returns null 作为 visit 方法的结果。当我在访问方法中放置一些 system.out 调用时,它什么也不显示。它似乎根本不访问节点。另一方面,listener 工作得很好。

有什么问题?

问题是您没有覆盖 visitor.visit(tree) 方法,在其抽象实现中,returns null。

访问者模式(与侦听器不同)的要点在于,您决定访问哪些节点。您可以访问所有这些,只访问您需要的那些,或者根本不访问任何东西。

因此,您的问题的解决方案可能是:

  • 覆盖 HighLevelClassVisitor class 中的 visit(ParseTree) 方法并提供正确的实现(我猜你还需要实现 visitCompilationUnit())。
  • 或者,只访问树中您真正感兴趣的那些部分,即:
    PackageDeclarationContext ctx = parser.packageDeclaration();
    HighLevelClassVisitor visitor = new HighLevelClassVisitor();
    System.out.println(visitor.visitPackageDeclaration(ctx).toString());