Допустим, вы пытаетесь проанализировать ввод "abc"
(без кавычек).Теперь ваше правило field
содержит type identifier
, и type
также может соответствовать identifier
.Таким образом, вы могли бы сказать, что парсер должен соответствовать identifier identifier
.Но как вход должен быть «разделен»?Синтаксический анализатор может сопоставить "a"
с первым identifier
и "bc"
со вторым identifier
.Но он также может соответствовать "ab"
первому и "c"
второму.
Тот факт, что синтаксический анализатор может создать более одного разбора из одного входа, является неоднозначностьюв вашей грамматике (сообщение об ошибке вы столкнулись).И причина этого в том, что вы пытаетесь создать идентификаторы во время анализа, в то время как вы должны создавать их во время лексера.Итак, если вы создаете токены лексера identifier
вместо токенов парсера, все должно быть в порядке.
И ваш лексер не должен создавать токены ALPHA
, DIGIT
и LETTER
.Эти правила должны использоваться только другим лексером (поэтому они должны быть помечены как «фрагментированные» правила).
Наконец, точно так же, как правило идентификатора, вы должны сделать правило number
правилом лексера вместоправило синтаксического анализатора (правила лексера начинаются с заглавной буквы, правила синтаксического анализатора с строчной буквы):
grammar twp3;
type : primitiveType | Identifier | 'any' 'defined' 'by' Identifier;
primitiveType : 'int' | 'string' | 'binary' | 'any';
field : 'optional'? type Identifier ';';
Identifier : LETTER (LETTER | DIGIT)*;
Number : DIGIT+;
fragment ALPHA : ('a'..'z'|'A'..'Z');
fragment DIGIT : ('0' .. '9');
fragment LETTER : ALPHA | '_';