Давайте обозначим ваши альтернативы следующим образом:
a
: b // a1
| a '+' b // a2
;
b
: c // b1
| c '+' '+' // b2
;
Теперь, если парсер только что проанализировал c
, а следующий токен - '+'
, есть две возможности: +
может быть частью c '+' '+'
, и в этом случае следует выбрать b2
или +
может быть частью a '+' b
, в этом случае следует выбрать b1
, а затем будет a2
. Однако парсер не может знать, какой из этих случаев имеет место, не видя второго +
, а YACC, являясь генератором парсера LALR(1)
, может смотреть только на один токен, а не на два.
Так вот почему у вас возникает конфликт. Как уже указывалось, решение этой проблемы - сделать ++
единственным токеном. Это также имеет то преимущество, что пробелы в ++
больше не допускаются, что более точно соответствует синтаксису существующих языков.