14

私は初めてでBison、シフト/削減の競合に問題があります...ファイルから次の場所にロードしようとしていますarray data[]:

struct  _data
{
  char name[50]; 
  char surname[50]; 
  int year;
} data[1000];

ここに私のバイソンコードの一部があります:

%token ID NUM NL EOF 

%%

File   : List EOF
       ;
List   : Record
       | List Record
       ;
Record : Name Surname Year NL  { count++; }
       | NL                    { count++; }
       | /*empty*/
       ;
Name   : ID                    { strcpy(data[count].name, yytext); }
       ;
Surname: ID                    { strcpy(data[count].surname, yytext); }
       ;
Year   : NUM                   { data[count].year= atoi(yytext); }
       ;

%%            

次のエラーが表示されます。

conflicts: 5 shift/reduce

私がどこで間違ったのか分かりますか?

4

1 に答える 1

28

-vオプションを使用して、シフト/削減の競合を診断するのに役立つ、より多くの情報を含むファイルをbison生成できます。.output特に、アイテムのリストを含むすべてのパーサーの状態を表示し、どの状態に競合があるかも示します。

しかし、この場合、問題は非常に単純です。あなたが持っているその必需品に取り除かれます:

List  : Record

Record: Something
      | /* Nothing */

の定義を無視するSomethingと、問題は、 aListが任意の数の で構成され、RecordsaRecordが空になる可能性があることです。これは、空の任意の数として解析できるものは何もないことを意味しますRecords。これは完全にあいまいです。入力内の連続する 2 つSomethingsは、0、1、2、42、または 273 の empty で区切ることができますRecords。パーサーは、新しい (シフト) の解析を開始するかSomething、空を出力するRecord(削減) かを判断できないため、シフト/削減の競合があると不平を言います。

解決策も非常に簡単です。空でないものは;Somethingで終わらなければならないことがわかります。NLおそらくその意図は、Fileが任意の数の で構成されRecords、それぞれが独自の行にあることでした。したがって、次のように書き換えることができます。

List  : Record
      | List NL Record

Record: Name Surname Year
      | %empty

Record空であろうとなかろうと、 a の後に a またはそれに続く可能NL性のあるものList(この場合は入力終了インジケータですが、通常はそのような規則を明示的に追加する必要はありません) が続く必要があります。直接後に別の を続けることはできませんRecord

于 2013-07-11T15:49:13.690 に答える