Я работаю над грамматикой в стиле C для моего личного удовольствия. Однако я столкнулся с конфликтами сдвига / уменьшения и уверен, что их можно разрешить.
Прямо сейчас мои expressions
выглядят так, в упрощенном виде, без действий:
%left '+' '-'
%%
expr
: NUMBER
| IDENTIFIER
| expr '+' expr
| expr '-' expr
/* other operators like '*', '/', etc. */
| expr '(' expr ')' /* function call */
%%
Однако это приводит к конфликтам сдвига / уменьшения: синтаксический анализатор не уверен, как обращаться с круглыми скобками. Из того, что -v
говорит мне, неясно, должно ли выражение типа expr '+' expr '('
уменьшать expr '+' expr
до expr
или сдвигать скобки.
Очевидно, я хочу, чтобы скобки были сдвинуты. foo % bar(4)
не должно в конечном итоге быть (foo % bar)(4)
. Однако я не добился успеха, используя директиву %prec
для этого значения. Добавление %left FUNCALL
и %prec FUNCALL
после правила не приводит к изменениям.
Я знаю, что путь парсера Bison LALR по умолчанию при обнаружении сдвига / уменьшения будет означать сдвиг, и что я мог бы просто использовать %expect
to fix , чтобы обойти проблему. Однако для каждого выражения генерируется один конфликт, и если мне когда-нибудь понадобится изменить этот список, мне также нужно будет изменить объявление %expect
, что для меня выглядит довольно некрасивым решением. Кроме того, я уверен, что у одного из вас, мудрых детей, есть решение этой проблемы.
Моя цель состоит в том, чтобы иметь правило, подобное приведенному выше, для которого Бизон будет знать, что всякий раз, когда он встречает '('
из правила вызова функции, он сдвигает скобки, без возможного конфликта сдвига / уменьшения. Для справки, я использую директиву %prec
следующим образом, так что, если я просто делаю это неправильно, вы можете исправить меня. У него есть конфликт сдвига / уменьшения.
%left '+' '-'
%left FUNCALL
%%
expr
: NUMBER
| IDENTIFIER
| expr '+' expr
| expr '-' expr
/* other operators like '*', '/', etc. */
| expr '(' expr ')' %prec FUNCALL /* function call */
%%