如何在规则完成时使Antlr4停止解析

时间:2014-06-10 08:43:38

标签: antlr4

我必须解析文件的某些部分,其中包含以下表达式:

garbage garbage garbage
BEGIN <something> END
garbage garbage...

在这里,我想解析BEGIN和END之间的所有内容,将垃圾放在一边。

我尝试编写一个解析器,其规则如下:

rule : BEGIN expr END;
expr : ... ;

正确解析我的表达式,如果它是我文件中唯一的东西。可悲的是,当我遇到一个&#34; BEGIN&#34;在我的文件中,解析器将正确解析表达式,但在&#34; END&#34;之后将尝试获取其他一些令牌。

我在ANTLR4书中已经阅读了部分abiut fyzzy语法,但这不是我想要的,因为解析的结果会影响文件的剩余部分(基本上,解析的结果会产生一组替换适用于以下文本)。

我正在寻找的是一种告诉解析器在&#34; END&#34;之后停止的方法。关键词。我试图覆盖TokenStream以在满足END时生成Token.EOF,并使用此修改后的规则集:

rule : BEGIN expr EOF;
expr : ... ;

代码如下:

public Token LT(int k) 
{
    Token token = super.LT( k );

    if ( token.getType() == MyParser.END )
    {
        token = new CommonToken(Token.EOF,"");
    }

    return token;
}

但在这种情况下,流已关闭,我无法再将其用于剩余文件...

1 个答案:

答案 0 :(得分:0)

您可以在词法分析器中创建一个特殊模式,将垃圾作为单个GARBAGE令牌使用。在以下示例代码中,我将GarbageMode作为单独模式,这要求您在创建词法分析器的新实例后显式调用lexer.setMode(GarbageMode)。另一种方法是将GarbageGarbageMode_BEGIN规则置于默认模式,并将其余规则从默认模式移至新模式,例如MainMode

BEGIN
  : 'BEGIN'
  ;

END
  : 'END' -> mode(GarbageMode)
  ;

mode GarbageMode;

  GARBAGE
    : .+? (BEGIN | EOF) -> mode(DEFAULT_MODE)
    ;

  GarbageMode_BEGIN
    : BEGIN -> type(BEGIN), mode(DEFAULT_MODE)
    ;

使上述词法分析器工作的关键是覆盖Lexer.emit方法以在创建GARBAGE令牌之前重置输入流位置。 PositionAdjustingLexer.g4中提供了一个示例,其中包含相应的单元测试testPositionAdjustingLexer()。在您的情况下,如果令牌的文字以GARBAGE结尾,您只需从BEGIN令牌中删除最后5个字符。