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