После вашего mainRule вы должны добавить токен EOF
, в противном случае ANTLR прекратит синтаксический анализ, когда нет действительного токена для сопоставления.
Кроме того, правило atom
должно действительно быть правилом лексера, а не парсера (правила лексера начинаются с заглавной буквы).
Попробуйте вместо этого:
grammar Test;
@parser::members {
public static void main(String[] args) throws Exception {
String text = "0,1 , 1 , 0,1";
ANTLRStringStream in = new ANTLRStringStream(text);
TestLexer lexer = new TestLexer(in);
CommonTokenStream tokens = new CommonTokenStream(lexer);
System.out.println(new TestParser(tokens).mainRule());
}
}
mainRule returns [List<String> words]
@init{$words = new ArrayList<String>();}
: w=Atom {$words.add($w.text);} (',' w=Atom {$words.add($w.text);} )* EOF
;
Atom
: '0' | '1'
;
WS
: ( '\t' | ' ' | '\r' | '\n'| '\u000C' )+ { $channel = HIDDEN; }
;
EDIT
Для уточнения: как вы уже выяснили, EOF
не является обязательным. Это только заставит парсер пройти весь ввод. NoViableAltException
генерируется только тогда, когда лексер натыкается на токен / символ, который не обрабатывается вашей лексерской грамматикой. Поскольку в вашей грамматике определены три токена (0
, 1
и ,
) и , ваш ввод "00"
не содержит символов, не обработанных вашим грамматика, NoViableAltException
не выбрасывается. Если вы измените свой ввод на что-то вроде "0?0"
, то появится NoViableAltException
.
Поскольку ваш синтаксический анализатор находит первый 0
, а затем не находит ,
, он просто прекращает синтаксический анализ, так как вы не «сказали» ему анализировать весь путь до конца файла.
Надеюсь, это прояснит ситуацию. Если нет, дайте мне знать.