Не удается найти «2 правила никогда не уменьшаются» и «конфликты: 2 сдвига / уменьшения» в файле yacc

#bison #yacc #context-free-grammar

#bison #yacc #контекстно-свободная грамматика

Вопрос:

Кажется, я не могу найти вышеуказанные ошибки, когда пытаюсь «скомпилировать» свой файл yacc. Я надеюсь, что кто-нибудь может указать строки и сообщить мне, что мне нужно сделать, чтобы исправить проблему (проблемы). Я перечислил свой файл:

 %token Identifier Int Real_Num And Array
%token Begin Boolean Div Do Else
%token End False For Goto If
%token Imply Integer Label Not Or
%token Own Procedure Real Step String
%token Then True Until Value While
%token Plus Minus Mult Divide Less
%token LessEq Great GreatEq Eq NotEq
%token Comma Colon Semi LParan RParan
%token LBrak RBrak Assign

%{

%}

%start program

%%

program
        : block
        ;

block
        : Begin optdecls stmts End
        ;

optdecls
        : /* empty */
        | decl Comma optdecls
        ;

decl
        : vardecl
        | arraydecl
        ;

vardecl
        : type idlist
        ;

type
        : Real
        | Integer
        | Boolean
        ;

idlist
        : Identifier
        | Identifier Comma idlist
        ;

arraydecl
        : Array arraylist
        | type Array arraylist
        ;

arraylist
        : arrayseg
        | arrayseg Comma arraylist
        ;

arrayseg
        : Identifier LBrak a_expr Colon a_expr RBrak

stmts
        : stmt
        | stmt Semi stmts
        ;

stmt
        : u_stmt
        | if_stmt
        | for_stmt
        ;

u_stmt
        : assign
        | dummy
        | block
        ;

assign
        : var Assign expr
        | var Assign assign
        ;

dummy
        : /* empty */
        ;

for_stmt
        : For var Assign a_expr Step a_expr Until a_expr Do stmt
        ;

if_stmt
        : If expr Then u_stmt
        | If expr Then u_stmt Else stmt
        | If expr Then for_stmt
        ;

var
        : Identifier
        | Identifier LBrak a_expr RBrak
        ;

factor
        : Int
        | Real_Num
        | var
        | LParan expr RParan
        ;

term
        : factor
        | term Mult factor
        | term Divide factor
        | term Div factor
        ;

sum
        : term
        | Plus term
        | Minus term
        | sum Plus term
        | sum Minus term
        ;

brel
        : sum
        | True
        | False
        | sum relation sum
        ;

relation
        : Less
        | LessEq
        | Great
        | GreatEq
        | Eq
        | NotEq
        ;

bsecond
        : brel
        | Not brel
        ;

bfactor
        : bsecond
        | bfactor And bsecond
        ;

bterm
        : bfactor
        | bterm Or bfactor
        ;

expr
        : bterm
        | If expr Then bterm Else expr
        ;

a_expr
        : sum
        | If expr Then sum Else a_expr
        ;

%%
  

Извините за длинный пост, но я считаю, что весь код имеет отношение к делу. Спасибо за помощь.

Ответ №1:

Используйте -v опцию to bison , которая сгенерирует .output файл с информацией обо всех состояниях и конфликтах. С вашей грамматикой это приводит к конфликтам в состояниях 16 и 30.

Состояние 16 равно:

 state 16

   15 arraylist: arrayseg .
   16          | arrayseg . Comma arraylist

    Comma  shift, and go to state 34

    Comma  [reduce using rule 15 (arraylist)]
  

Это говорит вам о том, что он не знает, следует ли сдвигать запятую после просмотра arrayseg , чтобы проанализировать больше arraylist , или если он должен уменьшить arraylist и разрешить запятой быть частью какого-либо другого правила (например, optdecls ), которое допускает запятую после arraylist .

Состояние 30 равно:

 state 30

   11 idlist: Identifier .
   12       | Identifier . Comma idlist

    Comma  shift, and go to state 59

    Comma  [reduce using rule 11 (idlist)]
  

что, по сути, одно и то же.

Основная проблема заключается в том, что ваша грамматика описывает списки объектов, разделенных запятыми, которые содержат списки, разделенные запятыми, поэтому требуется больше времени, чтобы определить, принадлежат ли запятые внутреннему списку или внешнему списку.

Возможно, вам следует иметь Semi , а не Comma между decl?

Комментарии:

1. К сожалению, я не могу изменить грамматику. Итак, я думаю, что еще можно сделать?