Вот цитата из другого ответа Я писал об алгоритме приоритета yacc / bison. Я не знаю, понятнее ли это, чем документация или описание в Книге Дракона, но это лучшее, что я смог сделать до сих пор. Пожалуйста, дайте мне знать, если вас это смущает:
Напомним, что отношение приоритета определяется между производством и
терминал. Это не касается двух терминалов или двух производств (и
поэтому не может быть использован для разрешения конфликтов уменьшения-уменьшения). Сравнение
между приоритетом производства, которое может быть уменьшено, и
Терминал предпросмотра определяет, произойдет ли уменьшение или смещение.
Для удобства записи продукция представлена названием
терминал, обычно единственный терминал в производстве; этот
соответствует общему варианту использования, но иногда сбивает с толку. В
в частности, объявление %prec
служит только для присвоения правилу имени
для использования в декларациях предшествования, и, вероятно, лучше подумать
об этом таким образом, а не как «явное» объявление.
Поскольку сравнение приоритетов никогда не проводится между двумя правилами - они всегда между правилом и токеном предварительного просмотра - объявления порядка приоритета должны включать как правила (неявно или явно), так и имена токенов. Итак, в вашем первом примере порядок старшинства между F_T
и P_T
никак не влияет. Аналогично, во втором примере PREFIX_OP
и POSTFIX_OP
являются приоритетами, связанными только с правилами, поэтому порядок приоритетов не имеет значения.
Если возможны как сдвиг, так и уменьшение, и сравнение правила с маркером предпросмотра может выявить, что правило имеет более высокий приоритет, то будет создано действие сокращения. Если жетон предпросмотра имеет более высокий приоритет, будет сгенерировано действие сдвига. Но с заявлениями можно ознакомиться только в том случае, если возможны как сдвиг, так и сокращение. Если грамматика может выполнять только одно действие, то это действие, которое она будет выполнять, независимо. (Исключение: %nonassoc
объявления фактически запретят определенные сокращения.)
Если сравнение приводит к равенству - и правило, и токен находятся в одной и той же группе приоритетов - тогда сдвиг будет предпочтительным для групп %left
и уменьшением для групп %right
. Этот случай обычно не применяется в случае унарных операторов, будь то префикс или постфикс, потому что в таком контексте возможно только одно действие.
Если вставка токенов в правила предшествования создаст конфликт с порядком приоритета в другой части грамматики, то вы не можете использовать объявления приоритета в качестве ярлыка; вам просто нужно написать свою грамматику, чтобы сделать явный приоритет. Это обычно не сложно. С другой стороны, противоречивые приоритеты в двух разных грамматических контекстах могут быть очень запутанными для людей, поэтому вы, возможно, захотите пересмотреть.
Что касается вывода конечного автомата в файле .output
, то печатается все состояние, а не только та часть, которая вызывает конфликты. Конфликты указываются в действиях; действия, заключенные в […]
, конфликтовали с другими действиями и были устранены с помощью механизма разрешения конфликтов по умолчанию bison (предпочитайте shift, чтобы уменьшить; предпочитайте shift, правило которого находится ранее в файле). Грубо говоря, правило смены имеет .
перед токеном; Правило сокращения имеет .
в конце правила.