13

右辺が空のルールで (「理論的な」) 文法を書く場合、常に ε (または 1) などの記号を使用して、この空を明示します。

A → ε | a A

Yacc などの文法は次のようになります。

a: | 'a' a

または「悪い」

a:       { $$ = new_list(); }
 | a 'a' { $$ = $1; $$->append($1); }
 ;

「現実世界の文法」 (Yacc、Bison など) では、ルールのこの空の右側部分が明示的に空としてマークされていないという事実は、私を悩ませます: rhs が空であるという事実を見逃すのは簡単です。さらに悪いこと|に、規則の途中のアクションを挿入して実際に使用するのを忘れる:

a:       { $$ = new_list(); }
   a 'a' { $$ = $1; $$->append($1); }
 ;

1) 空の rhs を明示的にする手段を提供するツールを知りません。いずれかがあります?

Bison の将来のバージョンでは専用のシンボルがサポートされる可能性があります。空でない rhs で使用するとエラーが発生し、暗黙的に空の rhs が残っていると警告が表示されます。

2) 人々はこれを有用だと考えていますか?

3) あなたが提案する記法は何ですか?

現在、候補者は次の$emptyとおりです。

a: $empty { $$ = new_list(); }
 | a 'a'  { $$ = $1; $$->append($1); }
 ;

編集

選択した構文は%empty次のとおりです。

a: %empty { $$ = new_list(); }
 | a 'a'  { $$ = $1; $$->append($1); }
 ;

確かに、Bison が最初のルールに対して生成する疑似シンボル、またはルールの途中のアクション、またはファイルの終わりに対して$empty疑似シンボルのように見えます。しかし、それは間違いなく記号ではなく、まさに記号の不在です。$accept$@n$eof

一方、 の%ようなディレクティブ (ある種の属性/メタデータ) を明確に示します%pred

したがって、構文の小さな違いですが、全体的な構文との一貫性が向上しています。クレジットは Joel E. Denny にあります。

4

5 に答える 5

7

私は通常、コメントを使用します。

a: /*epsilon*/ { $$ = new_list(); }
 | a 'a'  { $$ = $1; $$->append($1); }
 ;

変更なしで正常に動作し、意図が明確になります....

IMO、これは「壊れていない場合は修正しないでください」という見出しの下にあります

于 2013-02-01T20:35:40.653 に答える
3

次のことをお勧めします。

宣言を定義します。

%empty ID

そのセマンティクスは 2 つあります。

1) IDRHS がイプシロン プロダクションであることを示すために、RHS で唯一の非ルール トークンとして使用できます。と

2) でマークされていないイプシロン生成は、ID構文エラーと見なされます。

したがって、次の宣言を使用します。

%empty epsilon

epsilon 空の RHS をマークするために使用する必要があります。宣言がなければ%empty、空の RHS がマークされていない (おそらくコメントを除いて) 現状が保持されます。

これにより、空の RHS を明示的にマークしたいユーザーは、既存の文法ファイルやこの方法で空の RHS を明示的にマークしたくないユーザーに影響を与えることなく、すぐにマークを付けることができます。

個人的には、おそらくそのような宣言を使用するでしょうが、正直なところ、コメントを使用して空の RHS をマークすることにかなり慣れており、誤って空の RHS を作成したことはないと思います。したがって、私はそれを優先機能要求としてマークしませんが、その実装に反対もしません。

于 2013-02-01T21:14:42.427 に答える
2

私は自分自身を使用しただけでなく、中括弧でいくつかのコードを添付した空のプロダクションのepsilonバリエーションも使用しました。marker

bison 文法の予約記号が役立ちます。ユーザーが名前を付けたシンボルとの衝突を避けるために、提案された $ プレフィックスが気に入っています。

于 2013-02-01T14:59:38.230 に答える
0

もちろん、プロダクションがアクションを含む場合、ある意味では実際には「空」ではありません。Yacc/Bison では、アクションが背後で null 許容の非ターミナルに変換されるという事実を認識しないままでいることは難しいためです。また、あなた (または本) が授業中ずっと「イプシロン」と言っていた場合、おそらく「%イプシロン」は「%空」よりも真実味があります。

これをより一般的なアサーションメカニズムに組み込むことについて考えています。

lines : %assert(epsilon)
      | %assert(on WORD) lines line ;

line : WORD '\n' ;

%assert(nullable(lines))
%assert(!nullable(line))
%assert(WORD in FIRST(lines))
/* etc. */

すべてのヒューリスティックが開始された後、yacc/bison が実際にどの言語を実装したかを正確に把握する手間をわずかに軽減するという考えです。残りは、指定したとおりに多かれ少なかれ機能します。 「空の」ルールには %assert(epsilon) が含まれていました。

優先順位に関しては、bison が入力文法を受け入れられない可能性があるパーサーを作成したことが証明された場合 (たとえば、1 つ以上のプロダクションが起動できないなど) を報告することは、はるかに高い優先順位であると思います。少なくとも、私が最後に見たその能力はありませんでしたが、私はかなり古いバイソンを持っています:-)。そして、埋め込まれたアクションによって異なる共通の左接頭辞を持つプロダクションの問題を英語で説明することにまだ失敗していますか? 大幅に改善されない限り、意図せずに空になったルールをチェックするだけでなく、多くの説明的な改善が残っていると思います。

学生が遭遇する最も一般的なエラーに関するいくつかのデータを見ることは興味深いでしょう (私はこれを候補として選択しなかったと思います!)。これは興味深い実験です。bison の生徒用コピーをハッキングして、すべての実行をデータベースに送信し、いくつかのソフトウェアを使用してクリーンアップし、最も一般的な誤解を分析します。

于 2013-02-07T06:19:01.473 に答える
0

1) まあ、明らかなことがあります

e: a 'b'
あ:あ
 | | 空の
空の:

2) はい、とても参考になります。

3)$acceptと記号は常に定義されて$endおり$undefined、Bison の内部使用専用に予約されています (たとえば、文法には表示されません)。Bison は$@n規則中のアクションを生成しますが、これらはユーザーの文法でも使用できません。

私が間違っていなければ、ユーザーが文法で使用できる唯一の事前定義されたトークンはerror. では、なぜemptyその専用シンボルを提案しないのですか? それはかなり合理的に思えたでしょう。それとも、導入$errorも提案していますか?

検討しましたnothingか?むしろそっちかも。

于 2013-02-01T15:40:35.783 に答える