Как видно из отчета о бизонах, конфликты происходят с терминалами true
и false
, которые не перечислены в отношениях предшествования.Следовательно, правила приоритета не применяются к этим конфликтам.
Напомним, что отношение приоритета определено между производством и терминалом.Он не связан ни с двумя терминалами, ни с двумя производственными процессами (и поэтому не может быть использован для разрешения конфликтов уменьшения-уменьшения).Сравнение между приоритетом производства, которое может быть уменьшено, и терминалом прогнозирования определяет, произойдет ли уменьшение или сдвиг.Для удобства обозначения продукция представлена именем терминала, обычно единственного терминала в продукции;это соответствует общему варианту использования, но иногда сбивает с толку.В частности, объявление %prec
служит только для того, чтобы дать правилу имя для использования в объявлениях предшествования, и, вероятно, лучше подумать об этом, а не как о «явном» объявлении.
ВКороче говоря, конфликт в упрощенной грамматике в вашем вопросе может быть разрешен путем явного добавления соответствующих терминалов в отношения предшествования:
%precedence "if"
%precedence "true" "false"
%%
Hungry
: NoHungry
| Hungry NoHungry
| "if" Hungry "then" Hungry "else" Hungry %prec "if"
NoHungry
: "true"
| "false"
Выдержка из -v
output:
State 12
2 Hungry: Hungry . NoHungry
3 | "if" Hungry "then" Hungry "else" Hungry .
"true" shift, and go to state 2
"false" shift, and go to state 3
$default reduce using rule 3 (Hungry)
NoHungry go to state 8
Используя -r solved
вместо -v
, вы можете увидеть разрешение более явно:
Conflict between rule 3 and token "true" resolved as shift ("if" < "true").
Conflict between rule 3 and token "false" resolved as shift ("if" < "false").
Я мог бы использовать "else"
в качестве имени для if
продукции, которая была быпо умолчанию без объявления %prec
, но "if"
кажется более интуитивным.
Объявление %precedence
(доступно в последних версиях бизонов) не подразумевает левую или правую ассоциативность;в этом случае ассоциативность не применяется, потому что нет случая, когда конфликт включает производство и терминал равного приоритета.Если Happy не реализует его, то по той же причине можно использовать либо %left
, либо %right
(ассоциативность не имеет значения), но я думаю, что %precedence
лучше документирует ситуацию.
Поскольку это, несомненно, сниженнаяНапример, стоит отметить, что более полная грамматика потребует некоторого грамматического анализа.В частности, список терминалов с приоритетом, превышающим "if"
, должен был бы включать все терминалы в FIRST(NoHungry)
, и bison не предоставляет автоматического инструмента для выполнения этих вычислений, хотя обычно вы можете извлечь список из shift-lowerотчеты о конфликтах.(Может даже быть, что "if"
является частью набора, в этом случае ассоциативность будет иметь значение.)