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

如何使Antlr4在规则完成时停止解析,antlr4,Antlr4,我必须解析文件中有表达式的部分,如: garbage garbage garbage BEGIN <something> END garbage garbage... 它正确地解析了我的表达式,如果它是我文件中唯一的东西的话。遗憾的是,当我在文件中遇到BEGIN时尝试踢解析器时,解析器将正确地解析表达式,但随后将尝试在结束后获取其他标记 我已经阅读了ANTLR4书中的abiut Fyzy语法部分,但这不是我想要的,因为解析的结果基本上会影响文件的其余部分,解析的结果将产生一组替换,

我必须解析文件中有表达式的部分,如:

garbage garbage garbage
BEGIN <something> END
garbage garbage...
它正确地解析了我的表达式,如果它是我文件中唯一的东西的话。遗憾的是,当我在文件中遇到BEGIN时尝试踢解析器时,解析器将正确地解析表达式,但随后将尝试在结束后获取其他标记

我已经阅读了ANTLR4书中的abiut Fyzy语法部分,但这不是我想要的,因为解析的结果基本上会影响文件的其余部分,解析的结果将产生一组替换,应用于下面的文本中

我要寻找的是一种告诉解析器在END关键字之后停止的方法。我已尝试覆盖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;
}

但在本例中,流已关闭,我无法再将其用于剩余文件…

您可以在lexer中创建一种特殊模式,将垃圾作为单个垃圾令牌使用。在下面的示例代码中,我将GarbageMode作为独立模式,这要求您在创建lexer的新实例后显式调用lexer.setModeGarbageMode。另一种方法是将垃圾和垃圾模块开始规则置于默认模式,并将其余规则从默认模式移至新模式,例如MainMode


使上述lexer工作的关键是在创建垃圾令牌之前重写lexer.emit方法以重置输入流位置。这方面的一个示例在中提供,并带有相应的单元测试。在您的情况下,如果垃圾令牌的文本以BEGIN结尾,您只需从垃圾令牌中删除最后5个字符。

应该可以,谢谢您的技巧,假设我可以标记inputStream,但在这里,我必须完成我的家庭作业。仅供参考,我使用了一个“模糊解析器”,它会吞下语法中没有的所有内容,但这意味着我必须读取文件两次。你的建议将为我节省一个阶段。如果有一个在条目规则完成后停止获取令牌的特性,那将是非常棒的。类似于解析结束时的伪令牌EOP之类的东西可能会有所帮助。wdyt?@EmmanuelLécharny如果你尝试的话,你最终会遇到的。事实上,我遇到了118:-我本应该得到一个异常,但实际上,lexer只是读取文件末尾的所有内容。。。这就是为什么我发布了这个问题。
public Token LT(int k) 
{
    Token token = super.LT( k );

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

    return token;
}
BEGIN
  : 'BEGIN'
  ;

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

mode GarbageMode;

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

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