ANTLRSстартер писал:
Иногда предупреждение (ANTLRWorks 1.4.2): решение может соответствовать вводу, например «{Int, Word}», используя несколько альтернатив: 1, 2 (ссылаясь на id2)
Но только иногда!
Нет, введенная вами грамматика всегда выдаст это предупреждение. Возможно, вы не всегда замечаете это (ваш IDE-плагин или ANTLRWorks могут показывать это на вкладке, которую вы не открывали), но предупреждение есть. Убедитесь сами, создав лексер / парсер из командной строки:
java -cp antlr-3.4-complete.jar org.antlr.Tool NestedBrackets1a1.g
даст:
warning(200): NestedBrackets1a1.g:49:19:
Decision can match input such as "{Int, Word}" using multiple alternatives: 1, 2
As a result, alternative(s) 2 were disabled for that input
Это потому, что у вас есть *
после ( id2 )
внутри вашего comment
правила, а id2
также является повторением токенов: ( Word | Int )+
. Допустим, ваш ввод "# foo bar"
(#
, за которым следуют два Word
токена). ANTLR теперь может анализировать входные данные более чем одним способом: 2 токена "foo"
и "bar"
могут совпадать с ( id2 )*
, где id2
соответствует одному токену Word
за раз, но "foo"
и "bar"
также может совпадать с правилом id2
.
Посмотрите на объединенные правила:
comment
: '#' ( ( Word | Int )+ )*
;
Видите, как вы повторяете повторение: ( ( ... )+ )*
? Обычно это проблема, как и в вашем случае.
Решите эту проблему, заменив *
на ?
:
comment
: '#' ( id2 )?
;
id2
: ( Word | Int )+
;
или удалив +
:
comment
: '#' ( id2 )*
;
id2
: ( Word | Int )
;
ANTLRSстартер писал:
Следующим расширением должно быть то, что комментарий (id2) может содержать символы '(' и ')'.
Это вызывает проблемы, поскольку за комментарием следует TCListEnd
, то есть )
. Я не рекомендую оставлять комментарии подходящими )
.
EDIT
Обратите внимание, что комментарии обычно удаляются из исходного файла при маркировке входного источника. Таким образом, вам не нужно учитывать их в правилах парсера. Вы можете сделать это, "пропустив" эти токены в правиле лексера:
Comment
: '#' ~('\r' | '\n')* {skip();}
;