Какой лучший способ обработки необязательных токенов в antlr4
Предположим, у меня есть следующие данные:
Great University
Graduated in 2010
Some University
09/2009 - 06/2011
Nice University
06/2011
Я хочу справиться с годами обучения. Моя грамматика выглядит так:
education:
(section)*
EOF
;
section:
(school | years)+
;
degree: WORD* DEGREE WORD* SEPARATOR;
years: WORD* ( (YEAR_START '-')? YEAR_END) WORD* SEPARATOR;
WS : [ \t\r]+ -> skip;
SEPARATOR : (NEWLINE | COMMA);
COMMA : ',';
NEWLINE : '\n';
SCHOOL : ('university' | 'University' | 'school' | 'School');
WORD : [a-zA-Z'()]+;
YEAR_START : YEAR;
YEAR_END : YEAR;
YEAR : (DIGIT DIGIT '/')? [1-2] DIGIT DIGIT DIGIT;
DIGIT : [0-9];
Я получаю следующие ошибки:
line 1:17 mismatched input '\n' expecting '-'
line 6:17 mismatched input '\n' expecting '-'
Как я могу обработать необязательный начальный год с помощью грамматики?
1 ответ
Лексер может назначить только один тип токена одному шаблону. Вы ожидаете, что он назначит шаблон года трем типам токенов и во время выполнения решит, какой из них является правильным. Это не то, как работает ANTLR.
В вашем случае все годы (не только необязательные) будут учитываться по первому правилу, т.е. YEAR_START
, Это означает, что после токенизации
"Graduated in 2010" -> WORD WORD YEAR_START
Единственное правило соответствия
years: WORD* ( (YEAR_START '-')? YEAR_END) WORD* SEPARATOR;
но "-" отсутствует.
Грамматика должна работать, если удалить YEAR_START
а также YEAR_END
правила и заменить все вхождения YEAR
, Наверное YEAR_START
а также YEAR_END
имеют целью различать начало и конец, но для этого существуют метки.
Если это не работает, пожалуйста, опубликуйте свою полную грамматику, например ту, которую вы опубликовали, например, не содержит правила для DEGREE
,