Лексический анализатор создает токены следующим образом:
- попытаться сопоставить как можно больше символов для одного токена
- если два токена соответствуют одним и тем же символам, пусть один определил первый "выигрыш"
Учитывая информацию из 2 правил выше, вы увидите, что ваши правила:
DIGITS: DIGIT+;
INTLITERAL: (PLUS|MINUS)? DIGITS;
являются проблемой. Для ввода 100
создается токен DIGITS
: здесь применяется правило 2: оба правила соответствуют 100
, но, поскольку DIGITS
определен до INTLITERAL
, создается токен DIGITS
.
Решение 1
Переместите INTLITERAL
выше DIGITS
:
INTLITERAL: (PLUS|MINUS)? DIGITS;
DIGIT: '0'..'9';
DIGITS: DIGIT+;
Но теперь обратите внимание, что DIGIT
и DIGITS
никогда не станут токенами сами по себе, потому что INTLITERAL
всегда будет соответствовать первым. В этом случае вы можете сделать оба этих правила fragment
s, и тогда не имеет значения, где вы их разместите, потому что правила fragment
используются только внутри других правил лексера (не в правилах парсера)
Решение 2
Сделайте DIGIT
и DIGITS
фрагменты
fragment DIGIT: '0'..'9';
fragment DIGITS: DIGIT+;
INTLITERAL: (PLUS|MINUS)? DIGITS;
Решение 3
Или лучше, не приклеивайте оператор к INTLITERAL
, а сопоставить его в унарном выражении:
expression
: (MINUS | PLUS) expression
| expression (MINUS | PLUS) expression
| integerLiteral
;
integerLiteral
: INTLITERAL
;
PLUS: '+';
MINUS: '-';
fragment DIGIT: '0'..'9';
INTLITERAL: DIGIT+;