【发布时间】:2014-08-08 11:19:03
【问题描述】:
我使用 ANTLRv4 开发分析 Java 源代码的应用程序。我声称将所有单行 cmets 与第一个令牌 TODO(例如 // TODO <some-comment>)以及直接以下语句匹配。
示例代码:
class Simple {
public static void main(String[] args) {
// TODO develop cycle
for (int i = 0; i < 5; i++) {
// unmatched comment
System.out.println("hello");
}
// TODO atomic
int a;
// TODO revision required
{
int b = a+4;
System.out.println(b);
}
}
}
结果 = 地图像这样:
"develop cycle" -> for(...){...}
"atomic" -> int a
"revision required" -> {...}
关注 official book (1) 和 stackoverflow 上的类似主题((2)、(3)、(4)、(5)、(6))我尝试了几种方法。
起初我希望有 (1) 和 (2) 中描述的特殊 COMMENTS 频道,但出现错误 rule 'LINE_COMMENT' contains a lexer command with an unrecognized constant value; lexer interpreters may produce incorrect output。
我想以忽略所有单行 cmets 但以 TODO 开头的方式解析源代码会更好。我希望可以将 todo-cmets 直接添加到 AST 中以使用侦听器/步行器。比我只需要为 TODO 注释注册监听器/walker 并提取以下语句,将两者都添加到所需的 map。
我已经修改官方Java8 gammar 两天了,但没有任何成功。编译器抱怨或 AST 被错误混合。
这是我所做的更新:
// ...
COMMENT
: '/*' .*? '*/' -> skip
;
TODO_COMMENT
: '// TODO' ~[\r\n]*
;
LINE_COMMENT
: '//' ~[\r\n]* -> skip
;
谁能帮帮我?语法不是我的一杯茶。提前致谢
EDIT1:
上面贴的语法修改没有错误,但是生成了下面的树(请注意红色标记的节点包括int)
EDIT2:
假设上面的代码示例,在调用parser.compilationUnit();时会产生以下错误
line 3:2 extraneous input '// TODO develop cycle;' expecting {'abstract', 'assert', 'boolean', 'break', 'byte', 'char', 'class', 'continue', 'do', 'double', 'enum', 'final', 'float', 'for', 'if', 'int', 'interface', 'long', 'new', 'private', 'protected', 'public', 'return', 'short', 'static', 'strictfp', 'super', 'switch', 'synchronized', 'this', 'throw', 'try', 'void', 'while', IntegerLiteral, FloatingPointLiteral, BooleanLiteral, CharacterLiteral, StringLiteral, 'null', '(', '{', '}', ';', '<', '!', '~', '++', '--', '+', '-', Identifier, '@'}
line 8:2 extraneous input '// TODO atomic;' expecting {'abstract', 'assert', 'boolean', 'break', 'byte', 'char', 'class', 'continue', 'do', 'double', 'enum', 'final', 'float', 'for', 'if', 'int', 'interface', 'long', 'new', 'private', 'protected', 'public', 'return', 'short', 'static', 'strictfp', 'super', 'switch', 'synchronized', 'this', 'throw', 'try', 'void', 'while', IntegerLiteral, FloatingPointLiteral, BooleanLiteral, CharacterLiteral, StringLiteral, 'null', '(', '{', '}', ';', '<', '!', '~', '++', '--', '+', '-', Identifier, '@'}
line 11:2 extraneous input '// TODO revision required;' expecting {'abstract', 'assert', 'boolean', 'break', 'byte', 'char', 'class', 'continue', 'do', 'double', 'enum', 'final', 'float', 'for', 'if', 'int', 'interface', 'long', 'new', 'private', 'protected', 'public', 'return', 'short', 'static', 'strictfp', 'super', 'switch', 'synchronized', 'this', 'throw', 'try', 'void', 'while', IntegerLiteral, FloatingPointLiteral, BooleanLiteral, CharacterLiteral, StringLiteral, 'null', '(', '{', '}', ';', '<', '!', '~', '++', '--', '+', '-', Identifier, '@'}
显然语法是不正确的,因为它与简单的例子很矛盾
【问题讨论】:
-
上述语法摘录的确切错误是什么?会发生什么样的不匹配?
-
@UweAllner 所做的编辑,请参阅提供的方案 - 为什么
int也被标记? -
@ptrbel 对我来说这看起来很正确。 int 不是
// TODO xxx的一部分,而是直接在下一个块语句子树中跟随它。据我了解您的问题,这似乎确实是理想的结果。你期待什么? -
@UweAllner 例如ANTLR 没有生成
Java8BaseVisitor::visitTODO_COMMENT- 如何在没有访问者的情况下直接匹配以下语句? -
恕我直言,int 仅被标记,因为它直接跟随“额外”
TODO_COMMENT。我会忽略此错误,尤其是因为错误消息不会报告int的错误。
标签: parsing comments antlr antlr4