使用antlr4解析java代码时导航到不属于上下文的标记

时间:2014-07-10 13:30:18

标签: java antlr4

我使用ANTLR 4.2来解析Java源文件。

我的目标是在类中定位具有特定注释的方法。

我面临的问题是Java.g4语法不包含annotation规则作为methodDeclaration规则的一部分(这是有意义的),这意味着它不能直接用于当我覆盖enterMethodDeclaration的{​​{1}}时,我来自上下文对象:

JavaBaseListener

到目前为止,我唯一的想法是获取令牌流并尝试从方法声明上下文的位置向后遍历它。问题在于它非常麻烦(方法的注释可能在修饰符之前,在修饰符之后,即如果修饰符实际存在)并且我觉得它缺少了侦听器/访问者方法的点。 / p>

是否有一种干净的方法来获取方法的注释?

1 个答案:

答案 0 :(得分:2)

不要试图遍历 up 解析树,而是考虑下去。您可以从classBodyDeclaration制作开始,检查是否可以进入memberDeclaration并从那里进入methodDeclaration。如果是这样,你知道你现在正在使用某种方法。然后,只需遍历modifier中的classBodyDeclaration列表即可找到注释。

快速演示:

public class Main {

    public static void main(String[] args) throws Exception {

        String input = "@Annotation(\"class\")\n" +
                "class Mu {\n" +
                "\n" +
                "    @Annotation(\"field\")\n" +
                "    int x;\n" +
                "    \n" +
                "    @Annotation(\"method\")\n" +
                "    void withAnnotation(){}\n" +
                "    \n" +
                "    void withoutAnnotation(){}\n" +
                "}";

        JavaLexer lexer = new JavaLexer(new ANTLRInputStream(input));
        JavaParser parser = new JavaParser(new CommonTokenStream(lexer));

        //   classBodyDeclaration
        //       :   ...
        //       |   modifier* memberDeclaration
        //       ;
        //
        //   memberDeclaration
        //       :   methodDeclaration
        //       |   ...
        //       ;
        //
        //   methodDeclaration
        //       :   (type|'void') Identifier formalParameters ...
        //       ;
        //
        //   modifier
        //       :   classOrInterfaceModifier
        //       |   ...
        //       ;
        //
        //   classOrInterfaceModifier
        //       :   annotation
        //       |   ...
        //       ;
        ParseTreeWalker.DEFAULT.walk(new JavaBaseListener(){
            @Override
            public void enterClassBodyDeclaration(@NotNull JavaParser.ClassBodyDeclarationContext ctx) {

                if (!(ctx.memberDeclaration() != null && ctx.memberDeclaration().methodDeclaration() != null)) {
                    // No method declaration.
                    return;
                }

                String methodName = ctx.memberDeclaration().methodDeclaration().Identifier().getText();

                for (JavaParser.ModifierContext mctx : ctx.modifier()) {
                    if (mctx.classOrInterfaceModifier() != null && mctx.classOrInterfaceModifier().annotation() != null) {
                        System.out.println(methodName + " -> " + mctx.classOrInterfaceModifier().annotation().getText());
                    }
                }
            }
        }, parser.compilationUnit());
    }
}

打印:

withAnnotation -> @Annotation("method")