那是因为当你调用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*时,解析也会继续。