1

文法のルールのいくつかに問題があります。

文法は次のようなものです。

defLINES : carrRet
         | defLine carrRet
         | defLines defLine carrRet
         ;

defLine  : error carrRet                             {yyerrok();}
         | "DEF" kwType attrbt ID
         | "DEF" kwType ID fieldSuff
         ;

kwType   : "INT"
         | "REAL"
         ;

fieldSuff: "[" expr "]"
         | "[" expr "," expr "]"
         ;

attrbt   : /* nothing */
         | "PHU" intValue
         ;

チェックする入力を使用して:

DEF INT testvar1
DEF REAL testvar2

この入力には、「defLine」というヘッドを持つプロダクションの 2 番目のルールを使用する必要があります。

なぜそうしないのですか?3 番目のルールが常に使用され、エラーがスローされます

Unexpected 'carRet', '[' expected.

助けてくれてありがとう、アレックス

4

1 に答える 1

1

その文法は、少なくとも 1 つの shift/reduce の競合を確実に生成しattrbt: /* nothing */、競合のために生成が役に立たないという警告を出しました。(そうでない場合は、GPPG が bison ほど多くの警告を提供しないためです。しかし、少なくともシフト/削減の競合にフラグを立てることは確実です。)

競合はルールで発生します。

defLine  : "DEF" kwType attrbt ID
defLine  : "DEF" kwType ID fieldSuff

なぜならattrbt、空にすることはできますがID、2 番目の規則で前に置くことはできません。パーサーが遭遇DEF INTし、次のシンボルが であるとしIDます。この時点で、パーサーは 2 つのプロダクションのどちらdefLineを使用するかわかりませんが、違いは重要です。attrbt最初のケースでは、パーサーは をシフトする前に空を減らす必要がありIDます。2 番目のケースでは、 を作成するのattrbtは間違いです。

Yacc のようなパーサー ジェネレーターは常に、シフトを優先してシフト/リデュースの競合を解決します (優先順位の宣言がない限り)。したがって、この場合、IDは常にシフトされます。つまり、生産量を減らすことは不可能attrbt: /* nothing */です。(少なくともバイソンは、この事実について警告するでしょう。

さらに、IDその場合は のシフトが発生するため、 の 2 番目のプロダクションしかdefLine使用できないため、パーサーはfieldStuffをたどる必要がありID、 でfieldStuff開始する必要があり[ます。したがって、発生する解析エラーです。

これを修正するには、shift/reduce の競合を削除する必要があります。簡単な方法の 1 つはattrbt、両方のdefLineプロダクションで許可することです (セマンティック アクションでエラーを検出できます)。もう 1 つの可能性は、空のプロダクションを削除しattrbt、明示的に欠落を許可することです。

attrbt   : "PHU" intValue

defLine  : "DEF" kwType ID
         | "DEF" kwType attrbt ID
         | "DEF" kwType ID fieldSuff
于 2016-04-07T16:27:53.277 に答える