如何正确匹配java方法调用与Antlr4



我正在编写一个简单的程序,用于分析方法体(用Java 7编写)并列出它所具有的所有方法调用。

对于初学者,我希望能够检测对静态方法的调用,对局部变量和类成员变量的调用:

class TestSubject {
    String m;
    void alpha() {
        String l;
        l.charAt(0); // local
        m.contains(""); // member
        String.valueOf(0);  // static
        bravo().valueOf(0); // local on method
    }
    String bravo() {
        return "";
    }
}

方法调用通常看起来像foo.bar()。我目前正在努力匹配这种模式。这是语法的(相关)部分,应该用来描述以下内容:

expression
    :   primary
    |   expression '.' Identifier
    |   expression '(' expressionList? ')'
    这个语法如何生成看起来像'foo.bar()'的东西?毕竟,唯一被允许的事情之后的'。'是标识符。语法的哪一部分描述了'.'后面的'bar()' ?关键是:匹配方法调用的最佳方式是什么?

目前我有一些东西:

@Override
public void enterExpression(@NotNull JavaParser.ExpressionContext ctx) {
    if(ctx.expression() != null && ctx.expression().size() == 1 && right(ctx) != null){
        // This is something that may be a method invocation
    }
}

捕获静态调用,但这显然是弱的…

我已经有了一个符号表(类成员变量、方法局部变量和方法参数的哈希)。我的问题是匹配方法调用。我很难理解Java是如何。g4语法生成方法+获得形式为x.y()的表达式的最佳方式是什么(稍后我将进行必要的解释)

是的,表达式规则应该是正确的规则,但很难看出它如何匹配。

最好的建议是将print语句/断点添加到enterEveryRule &exitEveryRule方法,并解析和遍历一个最小的源代码示例。这将显示匹配的确切路径。

查看github.com/antlr/antlr4/tree/master/tool/test/org/antlr/v4/test获取如何快速测试运行的示例——BaseTest.java使测试代码片段变得容易。

不幸的是,您不能仅仅根据语法/解析树来区分静态方法调用和实例方法调用。例如,给定以下声明:

    public class MyClass {
        public static void method(){};
    }

则以下两个调用都是静态方法调用:

    MyClass.method();  // static method call
    MyClass m = new MyClass();
    m.method();        // static method call!!

要可靠地区分静态和实例方法调用,需要:

  1. 分析正在调用其方法的类,找出哪些方法是静态的,哪些不是。

  2. 分析调用以确定在.之前是否有表达式类型名称

  3. 如果您有类型名称,那么方法必须是static

  4. 如果你有一个表达式你需要确定表达式的类型

  5. 给定表达式类型,并且给定该类型是类,您需要执行方法签名匹配以确定最佳匹配

  6. 最后,查看匹配的方法是否为static

这里有Antlr4语法的参考实现:https://github.com/antlr/grammars-v4/tree/master/java

  1. 这个语法如何生成看起来像'foo.bar()'的东西?毕竟,唯一被允许的事情之后的'。'是标识符。语法的哪一部分描述了'.'后面的'bar()' ?

    如果你看这行:

    expression
       :   primary
       |   expression '.' Identifier
       // ...
       |   expression '(' expressionList? ')' #FunctionInvocation // <-- this is the line that catches all function invocations
    

    你会看到foo.bar是一个expressionfoo.bar ( )也是一个表达式

  2. 切中要害:匹配方法调用的最佳方式是什么?

相关内容

  • 没有找到相关文章

最新更新