Вы уверены, что конфликты включают только эти два правила? Первый должен иметь больше конфликтов, чем второй. По крайней мере, с одним символом прогнозирования решение перейти в состояние со стеком addOp проще во второй раз.
Обновление (Полагаю, я могу доказать свою теорию ...: -):
$ cat q2.y
%% expr: '1' | expr '+' expr | expr '-' expr;
$ cat q3.y
%% expr: '1' | expr addOp expr;
addOp: '+' | '-';
$ yacc q2.y
conflicts: 4 shift/reduce
$ yacc q3.y
conflicts: 2 shift/reduce
Сказав все это, для грамматик yacc нормально иметь неоднозначности, и любая реальная система, вероятно, будет иметь не только несколько, но буквально десятков конфликтов сдвига / уменьшения. По определению, этот конфликт возникает, когда имеется совершенно корректный доступный сдвиг, поэтому, если вы не возражаете, парсер принимает этот сдвиг, тогда не беспокойтесь об этом.
Теперь, в yacc
вы должны предпочесть леворекурсивные правила. Вы можете добиться того, чтобы и избавились от неоднозначности грамматики с помощью:
$ cat q4.y
%% expr: expr addOp '1' | '1';
addOp: '+' | '-';
$ yacc q4.y
$
Примечание: в приведенном выше примере нет конфликтов. Если вам нравится ваша грамматика такой, какая она есть, просто сделайте:
%expect 2
%% expr: '1' | expr addOp expr;
addOp: '+' | '-';