ANTLR:自动错误恢复似乎不起作用

时间:2011-12-01 17:18:16

标签: antlr recovery

我对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可以处理错位的令牌并试图恢复规则,但它似乎对我没用。我做错了什么?

提前感谢。

1 个答案:

答案 0 :(得分:2)

这是因为当您调用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而不是{{}}时,解析也会继续{1}}。