Как исправить yacc shift / уменьшить конфликты от оператора post-increment?

Я пишу грамматику в YACC (на самом деле Bison), и у меня проблема сдвига/уменьшения. Это происходит из-за включения постфиксных операторов инкремента и декремента. Вот сокращенная версия грамматики:

%token NUMBER ID INC DEC

%left      '+' '-'
%left      '*' '/'
%right     PREINC
%left      POSTINC

%%

expr: NUMBER
|     ID
|     expr '+' expr
|     expr '-' expr
|     expr '*' expr
|     expr '/' expr
|     INC expr %prec PREINC
|     DEC expr %prec PREINC
|     expr INC %prec POSTINC
|     expr DEC %prec POSTINC
|     '(' expr ')'
;

%%

Зубр говорит мне, что есть 12 конфликтов shift/reduce, но если я комментирую строки для постфиксного приращения и уменьшения, он работает нормально. Кто-нибудь знает, как исправить этот конфликт? На данный момент я рассматриваю возможность перехода к генератору парсера LL(k, что делает это намного проще, но грамматики LALR всегда казались гораздо более естественными для написания. Я также рассматриваю GLR, но я не знаю никаких хороших генераторов синтаксического анализатора C/C++ GLR.

5 ответов


Bison/Yacc может генерировать парсер GLR, если вы укажете %glr-parser в разделе Опции.


попробуйте это:

%token NUMBER ID INC DEC

%left       '+' '-'
%left       '*' '/'
%nonassoc   '++' '--'
%left       '('
%%

expr: NUMBER
|     ID
|     expr '+' expr
|     expr '-' expr
|     expr '*' expr
|     expr '/' expr
|     '++' expr 
|     '--' expr 
|     expr '++'
|     expr '--'
|     '(' expr ')'
;

%%

ключ должен объявить операторы postfix как номера ассоциативные. В противном случае вы смогли бы

++var++--

скобки также должны иметь приоритет, чтобы минимизировать смещение / уменьшить предупреждения


Мне нравится определять больше элементов. Вам не нужен материал %left, %right, %prec.

simple_expr: NUMBER
 | INC simple_expr
 | DEC simple_expr
 | '(' expr ')'
;

term: simple_expr
 | term '*' simple_expr
 | term '/' simple_expr
;

expr: term
 | expr '+' term
 | expr '-' term
;

поиграйте с этим подходом.


эта основная проблема заключается в том, что у вас нет приоритета для INC и DEC токены, поэтому он не знает, как разрешить двусмысленности, связанные с lookahead INC или DEC. Если добавить

%right INC DEC

в конце списка приоритетов (вы хотите, чтобы унарные были выше приоритета и постфикс выше префикса), он исправит это, и вы даже можете избавиться от всех PREINC/POSTINC вещи, как это не имеет значения.


операторы preincrement и postincrement имеют nonassoc, поэтому определите, что в разделе приоритета и в правилах сделайте приоритет этих операторов высоким, используя %prec