Часть ответа - внимательно посмотреть на выходной файл bison -v
. Для вашей первой грамматики я получил следующие выдержки:
State 8 conflicts: 1 shift/reduce
State 9 conflicts: 1 shift/reduce
State 10 conflicts: 1 shift/reduce
State 11 conflicts: 1 shift/reduce
State 12 conflicts: 1 shift/reduce
Grammar
0 $accept: expr $end
1 expr: NUMBER
2 | expr '+' expr
3 | expr '-' expr
4 | expr '*' expr
5 | expr '/' expr
6 | expr expr
Итак, в грамматике 5 конфликтов сдвига / уменьшения. Это менее серьезный тип конфликта; Вы можете заявить, что ожидаете их с %expect 5
в грамматике, если вы уверены, что грамматика делает правильно.
state 0
0 $accept: . expr $end
NUMBER shift, and go to state 1
expr go to state 2
state 1
1 expr: NUMBER .
$default reduce using rule 1 (expr)
state 2
0 $accept: expr . $end
2 expr: expr . '+' expr
3 | expr . '-' expr
4 | expr . '*' expr
5 | expr . '/' expr
6 | expr . expr
$end shift, and go to state 3
'+' shift, and go to state 4
'-' shift, and go to state 5
'*' shift, and go to state 6
'/' shift, and go to state 7
NUMBER shift, and go to state 1
expr go to state 8
state 3
0 $accept: expr $end .
$default accept
state 4
2 expr: expr '+' . expr
NUMBER shift, and go to state 1
expr go to state 9
Состояния 5, 6, 7 имитируют состояние 4, но для других операторов. Состояние 8 является первым из государств с конфликтом сдвига / уменьшения. Помните, что .
(точка) в правилах указывает, где находится анализатор, когда он достигает этого состояния.
state 8
2 expr: expr . '+' expr
3 | expr . '-' expr
4 | expr . '*' expr
5 | expr . '/' expr
6 | expr . expr
6 | expr expr .
NUMBER shift, and go to state 1
NUMBER [reduce using rule 6 (expr)]
$default reduce using rule 6 (expr)
expr go to state 8
state 9
2 expr: expr . '+' expr
2 | expr '+' expr .
3 | expr . '-' expr
4 | expr . '*' expr
5 | expr . '/' expr
6 | expr . expr
'*' shift, and go to state 6
'/' shift, and go to state 7
NUMBER shift, and go to state 1
NUMBER [reduce using rule 2 (expr)]
$default reduce using rule 2 (expr)
expr go to state 8
Существуют различия и сходства между этими двумя состояниями, но состояния 10, 11, 12 соответствуют состоянию 9, за исключением различных точек неопределенности.
Беда в том, что когда грамматика видит:
NUMBER OP NUMBER NUMBER
он не может определить, нужно ли анализировать это как:
(НОМЕР ОП НОМЕР) НОМЕР
expr expr
или как:
NUMBER OP ( NUMBER NUMBER )
expr OP expr
Учитывая, что это конфликт сдвига / уменьшения в каждом случае, он выбирает сдвиг. Если это то, что вы хотите, то добавьте %expect 5
и продолжайте жизнь. Если это не то, что вы хотите, то вам нужно переосмыслить свою грамматику. Что указывает пара соседних чисел, и вы уверены, что вам не нужен какой-нибудь символ оператора (возможно, запятая или двоеточие) для их разделения?
Я попытался повысить приоритет отсутствующего оператора с помощью:
%left MISSING
после других деклараций предшествования, а затем с использованием:
expr expr %prec MISSING
Это ничего не изменило. Ни один из них не делает приоритет MISSING очень низким, перечисляя его перед другими операторами.
Вы получите представление о проблемах, если подумаете, как следует проанализировать подобное выражение:
NUMBER OP NUMBER NUMBER NUMBER OP NUMBER NUMBER OP NUMBER
Где ОП одинаков в каждом внешнем виде. Мой мозг болит! Так же, как и bison
s!