Это потому, что когда вы вызываете правило parse
:
parse : define*;
парсер пытается найти как можно больше define
правил для ввода:
(define alpha)
)
(define beta)
После успешного совпадения с (define alpha)
он видит )
, поэтому он больше не может соответствовать правилу define
и прекращает его синтаксический анализ. И поскольку )
является действительным токеном в вашей грамматике лексера, вы не видите ни предупреждения, ни ошибки.
Вы должны указать парсеру пройти весь поток токенов , "привязав" правило основного синтаксического анализатора, поместив маркер EOF
(конец файла) в конце:
parse : define* EOF;
Если вы снова проанализируете ввод, вы увидите следующую ошибку на вашей консоли:
line 2:0 missing EOF at ')'
EDIT
Тот факт, что 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*
.