【问题标题】:ANTLR: Automatic Error Recovery doesn't seem to workANTLR:自动错误恢复似乎不起作用
【发布时间】:2011-12-01 17:18:15
【问题描述】:

我对 ANTLR v3 的自动错误恢复有疑问,这在我的语法中似乎不起作用。 考虑以下语法:

grammar test;

parse   :   define*;

define  :   LPAREN 'define' VARIABLE RPAREN;

// Tokens
LPAREN : '(';
RPAREN : ')';

LETTER  :   ('a'..'z'|'A'..'Z');

VARIABLE : LETTER*;

SPACE : (' ' | '\n' | '\t' | '\r') {$channel = HIDDEN;}; 

当我使用以下输入调用解析规则时:

(define alpha)
(define beta)

他成功地解析了两个定义规则。 但是,当我输入一个不适合的令牌时:

(define alpha)
)
(define beta)

他在第一次看到放错位置的 RPAREN 令牌时取消解析。我认为 antlr 可以处理放错位置的令牌并尝试返回规则,但它似乎对我不起作用。我做错了什么?

提前致谢。

【问题讨论】:

    标签: antlr recovery


    【解决方案1】:

    那是因为当你调用parse规则时:

    parse : define*;
    

    解析器尝试为输入匹配尽可能多的define 规则:

    (define alpha)
    )
    (define beta)
    

    成功匹配(define alpha)后,它会看到),因此它不能再匹配define规则并停止解析。因为) 在您的词法分析器语法中的有效标记,所以您看不到任何警告或错误。

    您需要通过在末尾放置 EOF(文件结尾)标记来“锚定”您的主要解析器规则,从而告诉您的解析器通过 整个 标记流:

    parse : define* EOF;
    

    如果您现在再次解析输入,您将在控制台上看到以下错误:

    line 2:0 missing EOF at ')'
    

    编辑

    define* 没有恢复可能是因为没有固定数量的令牌,使得恢复过程太难了。下面的演示似乎证实了我的怀疑:

    grammar test;
    
    @parser::members {
      public static void main(String[] args) throws Exception {
        String source =  
            "(define alpha) \n" +
            ")              \n" +
            "(define beta)    ";
        testLexer lexer = new testLexer(new ANTLRStringStream(source));
        testParser parser = new testParser(new CommonTokenStream(lexer));
        parser.parse();
      }
    }
    
    parse    : define define EOF {System.out.println("parsed >>>" + $text + "<<<");};
    define   : LPAREN 'define' VARIABLE RPAREN;
    LPAREN   : '(';
    RPAREN   : ')';
    LETTER   : ('a'..'z'|'A'..'Z');
    VARIABLE : LETTER+;
    SPACE    : (' ' | '\n' | '\t' | '\r') {$channel = HIDDEN;};
    

    如果您运行testParser 类,控制台会打印以下内容:

    line 2:0 extraneous input ')' expecting LPAREN
    parsed >>>(define alpha) 
    )              
    (define beta)    <<<
    

    即警告打印到System.err,但是当将parse规则限制为两个define而不是define*时,解析也会继续。

    【讨论】:

    • @Bart:我明白这一点,但他又没有解析第二个表达式。我如何让 antlr 尝试像 TP 的 Antlr 书中描述的“通过单个符号删除恢复”?
    • 这对我来说真的很不幸。这与书中的示例或其他错误恢复有效的情况有何不同?
    • 不,它有同样的错误。但是我尝试了书中的语法,它似乎只有在它需要固定标记(如;)时才能恢复,而不是规则或子规则,就像你说的那样。还是非常感谢。我会将其发布在 ANTLR 邮件列表上,看看是否有人知道解决方案,但我认为您是对的。
    • @Sebastian,正确,错误仍然出现(因为它仍然是错误的),但解析确实继续。请参阅我的编辑
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-15
    • 1970-01-01
    相关资源
    最近更新 更多