我正在尝试使用 ANTLR 来分析使用完整 Java 语法的大量代码。由于 ANTLR 需要打开所有源文件并扫描它们,我想知道它是否也可以返回代码行。
我检查了 Lexer 和 Parser 的 API,似乎它们没有返回 LoC。使用语法规则来获得 LoC 是否容易?完整的 Java 规则很复杂,我真的不想弄乱它的大部分。
我正在尝试使用 ANTLR 来分析使用完整 Java 语法的大量代码。由于 ANTLR 需要打开所有源文件并扫描它们,我想知道它是否也可以返回代码行。
我检查了 Lexer 和 Parser 的 API,似乎它们没有返回 LoC。使用语法规则来获得 LoC 是否容易?完整的 Java 规则很复杂,我真的不想弄乱它的大部分。
如果你有一个现有的 ANTLR 语法,并且想在解析过程中计算某些东西,你可以这样做:
grammar ExistingGrammar;
// ...
@parser::members {
public int loc = 0;
}
// ...
someParserRule
: SomeLexerRule someOtherParserRule {loc++;}
;
// ...
因此,每当您的 oparser 遇到 a 时someParserRule
,您可以loc
通过放置{loc++;}
在规则之后(或之前)来增加 1。
因此,无论您对代码行的定义是什么,只需将{loc++;}
其放入规则中即可增加计数器。注意不要增加两次:
statement
: someParserRule {loc++;}
| // ...
;
someParserRule
: SomeLexerRule someOtherParserRule {loc++;}
;
我刚刚注意到,在您的问题标题中,您询问这是否可以在词法分析期间完成。那是不可能的。假设 LoC 总是以';'
. 在词法分析期间,您将无法区分';'
之后的赋值(即单个 LoC)和语句中的 2 ';'
(for(int i = 0; i < n; i++) { ... }
不会是 2 LoC)。
在 C 目标中,数据结构 ANTLR3_INPUT_STREAM 有一个 getLine() 函数,它从输入流中返回当前行。这似乎是 CharStream.getLine() 的 Java 版本。您应该可以随时调用它并获取输入流中的当前行。
使用访问者访问 CompilationUnit 上下文,然后 context.stop.getLine() 将为您提供编译单元上下文的最后行号。
@Override public Integer visitCompilationUnit(@NotNull JAVAParser.CompilationUnitContext ctx) {
return ctx.stop.getLine();
}