Ваша проблема не имеет ничего общего с операторами присваивания.Дополнения просто не работают вообще - являются ли они частью задания или нет.Таким образом, самый простой ввод для получения ошибки будет x+y;
.Если вы распечатаете поток токенов для этого ввода (например, используя grun
с опцией -tokens
), вы получите следующий вывод:
[@0,0:0='x',<IDENTIFIER>,1:0]
[@1,1:1='+',<'+'>,1:1]
[@2,2:2='y',<IDENTIFIER>,1:2]
[@3,3:3=';',<';'>,1:3]
[@4,4:3='<EOF>',<EOF>,1:4]
line 1:1 no viable alternative at input 'x+'
Теперь сравните это с x*y;
, чтоотлично работает:
[@0,0:0='x',<IDENTIFIER>,1:0]
[@1,1:1='*',<MATH>,1:1]
[@2,2:2='y',<IDENTIFIER>,1:2]
[@3,3:3=';',<';'>,1:3]
[@4,4:3='<EOF>',<EOF>,1:4]
Важным отличием здесь является то, что *
распознается как токен MATH
, а +
- нет.Вместо этого он распознается как токен '+'
.
Это происходит потому, что в альтернативном | ('+' | '-') expression
вы ввели отдельный тип токена '+'
(и '-'
).Поэтому, когда лексер видит +
, он генерирует токен '+'
, а не MATH
, потому что строковые литералы в правилах синтаксического анализатора имеют приоритет над именованными правилами лексера.
Если вы включите MATH
ввместо правила синтаксического анализатора math
(или, возможно, mathOperator
) все операторы будут литералами, и проблема исчезнет.Тем не менее, вам, вероятно, не нужно одно правило для всех математических операторов, потому что это не дает вам желаемого приоритета, но это другая проблема.
PS: что-то вроде x+1
все еще выиграно 'не работает, потому что он будет видеть +1
как один INTEGER
токен.Это можно исправить, удалив ведущие +
и -
из правила INTEGER
(таким образом x = -2
будет проанализирован как унарный минус, примененный к целому числу 2
вместо целого числа -2
,но это не проблема).