java - Antlr 中的词法分析器模式

标签 java antlr antlr4

全部: 我正在尝试编写一个 antlr 解析器来解析一些文本,其格式如下:

RP   NUCLEOTIDE SEQUENCE [GENOMIC DNA],
RP   PROTEIN SEQUENCE OF 1-22; 2-17;
RP   240-256; 318-339 AND 381-390, AND CHARACTERIZATION.

基本上所有行都有一个前导'RP'来指示文本行的内容,最后一行应该以“.”结尾来指示结束这种类型的线路。文本也可以是任何东西。我最终需要的是文本。

我为此写了一个 Antlr 语法:

grammar RefLine;

rp_line: RP_HEADER RP_TEXT;

RP_HEADER : 'RP   '            -> pushMode(RP_FREE_TEXT_MODE);

mode RP_FREE_TEXT_MODE;
RP_HEADER_SKIP: '\nRP   '      -> skip;
RP_TEXT: .+;
DOT_NEWLINE: '.\n'             -> popMode;

这里的想法是,当看到第一个 RP_HEADER 时,它会更改为 RP_FREE_TEXT_MODE,从而跳过两行之间的任何 RP_HEADER。当看到 DOT_NEWLINE 时,返回主模式。

然而,这个语法不能用 Antlr 4.1 编译,产生错误:

[ERROR] Message{errorType=MODE_NOT_IN_LEXER, args=[RP_FREE_TEXT_MODE, org.antlr.v4.tool.Grammar@5c0662], e=null, fileName='RefLine.g4', line=7, charPosition=5}
[WARNING] Message{errorType=IMPLICIT_TOKEN_DEFINITION, args=[RP_TEXT], e=null, fileName='RefLine.g4', line=3, charPosition=19}

不太明白为什么会报错。谁能解释在 Antlr 中使用词法分析器模式的正确方法?还有,mode中定义的TOKEN是不是解析器规则不可用?

编辑:

正如@auselen 所建议的,我将词法分析器语法放在一个单独的文件 RefLineLex.g4 中:

lexer grammar RefLineLex;

RP_HEADER : 'RP   '            -> pushMode(RP_FREE_TEXT_MODE);

mode RP_FREE_TEXT_MODE;
RP_HEADER_SKIP: '\nRP   '      -> skip;
RP_TEXT: .+;
DOT_NEWLINE: '.\n'             -> popMode;

在另一个组合语法 RefLine.g4 中,我有:

grammar RefLine;
import RefLineLex;

rp_line: RP_HEADER RP_TEXT ;

现在 Antlr 编译文件,但在 RefLineLexer.java 中生成:

private void RP_HEADER_action(RuleContext _localctx, int actionIndex) {
        switch (actionIndex) {
        case 0: pushMode(RP_FREE_TEXT_MODE);  break;
        }
    }

常量:RP_FREE_TEXT_MODE 未在 RefLineLexer.java 中的任何位置定义。 我还缺少什么吗?

最佳答案

Lexer 模式仅在 Lexer 文法中可用,在复合文法(Lexer + Parser)中不可用。参见 Lexer Rules对于一些糟糕的文档并检查 XML Parser示例在 github 上实现。

您应该已经能够在错误打印中非常有用的 errorType=MODE_NOT_IN_LEXER 消息中理解这一点 :)

关于java - Antlr 中的词法分析器模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18243283/

相关文章:

Java 开源文本挖掘框架

antlr - 在 ANTLR 中编写语言转换器

java - 让 Antlr 词法分析器将语法错误作为标记处理

c# - 停止访问的推荐方法是什么?

ANTLR4 访问者子树检查

java - Apache Camel Message Exchange - 您能否迭代交换以从交换中的单个消息生成多个输出文件

java - 处理 Jackson 序列化的常见方法是什么

java - 无法验证签名(cmssigneddata)bouncycaSTLe

antlr - 如何在 ANTLR3 中制作 TreeParser?

java - 我如何在 ANTLR 中实现流量控制(*执行*if-else,for...while....)?