parsing - 如何使用 ANTLRv4 仅解析一些评论

标签 parsing comments antlr antlr4

我使用 ANTLRv4 开发了分析 Java 源代码的应用程序。我声称将所有单行注释与第一个标记 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);
        }
    }
}

结果 = map ,如下所示:

"develop cycle" -> for(...){...}
"atomic" -> int a
"revision required" -> {...}

已关注 official book (1)和 stackoverflow 上的类似主题( (2)(3)(4)(5)(6) )我尝试了几种方法。

起初我希望有特殊的评论 channel ,如 (1) 中所述。和 (2)但错误rule 'LINE_COMMENT' contains a lexer command with an unrecognized constant value; lexer interpreters may produce incorrect output发生了。

我想以忽略所有单行注释的方式解析源代码会更好,但以 TODO 开头的注释除外。 。我希望可以将待办事项注释直接添加到 AST 中,以便使用监听器/步行器。我只需要为 TODO 注释注册监听器/步行器并提取以下语句,将两者添加到所需的 map 中。

我一直在修改官方Java8 gammar两天但没有任何成功。要么编译器提示,要么 AST 被破坏。

这是我所做的更新:

// ...
COMMENT
    :   '/*' .*? '*/' -> skip
    ;

TODO_COMMENT
    :   '// TODO' ~[\r\n]*
    ;

LINE_COMMENT
    :   '//' ~[\r\n]* -> skip
    ;

有人可以帮我吗?语法不是我的菜。提前致谢

编辑1:

上面发布的语法修改符合要求,没有错误,但生成了以下树(请注意红色标记的节点包括 int )

error AST

编辑2:

假设上面的代码示例,在调用 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, '@'}

很明显语法是不正确的,因为它很难处理简单的例子

最佳答案

原因是您不希望在任何解析器规则中添加特殊注释,即没有解析器会匹配它。

您(至少)可以执行以下操作:

  1. 添加可选的TODO_COMMENT?在每个解析器规则的前面。
  2. TODO_COMMENT token 添加到单独的 channel ,例如ToDoCommentChannel(不要忘记定义此 channel 的常量!)并选择树遍历中注释后面的每个构造。

我会做什么的粗略概述:

  • TODO_COMMENT 使用单独的 channel 。
  • 照常进行 lex 和解析
  • 从 token 流中获取所有 token ,并找到所需 channel 的 token ,并在默认 channel 上获取以下 token 并将它们存储在列表中。
  • 遍历解析并检查每个输入的规则,如果起始标记在列表中。如果是,则将规则文本复制到结果列表中,否则递归(如果 TODO_COMMENT 可以嵌套,甚至在起始标记位于列表中时递归)。

更新:

关于规则“LINE_COMMENT”包含具有无法识别的常量值的词法分析器命令;词法分析器解释器可能会产生不正确的输出错误:

这可以忽略,因为它只影响 Antlrworks2 或插件使用的解释器。您也可以这样做:

//Instead of
TODO_COMMENT
    :   '// TODO' ~[\r\n]*  -> channel(ToDoCommentChannel)
    ;    

// do this (assuming the channel value is indeed 42):
TODO_COMMENT
    :   '// TODO' ~[\r\n]*  -> channel(42 /*ToDoCommentChannel*/)
    ;    

这适用于 Antlrworks2 和代码(您仍然可以在 Java 运行时代码中使用 channel 的常量值)。

关于parsing - 如何使用 ANTLRv4 仅解析一些评论,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24280850/

相关文章:

linux - 使用 bash 获取字符串的一部分

python - 将自顶向下语法规则转换为 BNF

java - 注释是否会使运行程序变慢?

jsp - Sublime Text 2、jsp隐藏评论快捷方式

java - Antlworks语法解析器

Javascript/XML - 获取节点名称

parsing - 是否有关于 Erlang 解析转换的完整教程?

python - 如何在 Python 中创建多行注释?

java - 如何在不使用太多 if 子句的情况下获取类型?

java - 在 ANTLR 中,如何根据特定的低级规则解析流?