我必须解析文件的某些部分,其中包含以下表达式:
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;
}
但在这种情况下,流已关闭,我无法再将其用于剩余文件...
答案 0 :(得分:0)
您可以在词法分析器中创建一个特殊模式,将垃圾作为单个GARBAGE
令牌使用。在以下示例代码中,我将GarbageMode
作为单独模式,这要求您在创建词法分析器的新实例后显式调用lexer.setMode(GarbageMode)
。另一种方法是将Garbage
和GarbageMode_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个字符。