1

Menhir を使用してパーサーを作成していますが、常につまずく動作があり、理解できません。それを示すために、次の最小限の例を作成しました。これは、Go 言語 ( http://golang.org/ref/spec#Method_declarations )のメソッド宣言でのレシーバー引数の宣言を示しています。

%{

%}

%token <string> T_identifier
%token T_star

%start <unit> demo


%%


(* This rule has a shift/reduce conflict
demo:
| option(T_identifier) option(T_star) T_identifier { () } 
*)

(* This rule is okay. *)
demo:
| T_identifier T_star T_identifier { () }
| T_identifier T_identifier        { () }
| T_star T_identifier              { () }
| T_identifier                     { () }

私が見る限り、両方のルールは意味的に同等です。オプションの識別子 (レシーバーの名前)、オプションのスター (ポインターかどうか)、および必須の型名 (レシーバーの型) を探しています。ただし、最初のルール (コメント アウトされたルール) ではシフト/リデュースの競合が発生しますが、2 番目のルールは正常に機能します。

これが発生するたびに複数のルールに置き換えることでパーサーを進歩させることができましたがoption、なぜそれが起こっているのか理解できないことに悩まされています.

(menhir を知らない場合、これは LR(1) パーサー ジェネレーターなので、他の同様のツールがどのように機能するかについての知識がおそらく適用されます。)

4

2 に答える 2

1

2 番目のルールでは、あいまいさを解決する順序を明示的に指定しました。実際、節を並べ替えるだけで、いくつかの異なる方法で 2 番目の規則を書き直すことができます。それがメンヒルが不平を言う理由です、彼はあなたがどの順序を好むのかわかりません。

于 2014-10-03T18:19:45.117 に答える