6

Menhirパーサー(Ocamlyaccと同様)を使用して、演算子が動的属性(優先順位と優先順位)を持つ言語を解析しようとしています。字句解析フェーズでは、すべての演算子がOP:stringトークンを入力します(したがって、「+」はなどに変わります(OP "+"))。

演算子の属性は解析時に決定され、演算子とその属性を関連付けるテーブルに入力されます。このテーブルが与えられた場合、このテーブルのデータに基づいて演算子を解析するルールの優先度を動的に変更するようにMenhirに指示するにはどうすればよいですか?

ありがとう、CharlieP。

4

1 に答える 1

13

「やり方が間違ってる」みたいなコメントで申し訳ありません。関連性の高い順に、建設的であることを願っている 3 つの異議があります。

  1. Menhir は、動的な文法の更新を意図したものではありません。解析時に文法を変更する必要がある場合は、GLR パーサーDypgenなど、この機能を提供するツールを使用する必要があります。Dypgen のマニュアルでは、オペレーターの優先順位を動的に更新する可能性について言及していますが、制約のある方法で (新しいオペレーターと対応する優先順位を追加することはできますが、既存の優先順位を変更することはできないようです)、必要に応じて一致する場合と一致しない場合があります。Dypgenマニュアル(PDF)のセクション6.6 、ページ... 42を参照してください。

  2. CFG 文法を動的に更新することは、ユーザー定義の演算子の優先順位を処理する最良の方法ではないと思います。Agda には非常に一般的なユーザー定義の mixfix 演算子があり、その解決策はおおまかに次のとおりです。CFG パーサーを使用して、静的に知られている文法構造を解析します。トークン。たとえば、let x = if foo then x + y * z else barは次のように解析されますLet(x, If(foo, Expr(x, +, y, *, z), bar)。後の特殊化されたパスは、必要な情報を収集して、それらをExprノードに解析し、特殊化された構造にすることができます。パーサー ジェネレーターが適しているもの (静的に知られている豊富な CFG) にはパーサー ジェネレーターを使用し、複雑で未定義の動的なものには後処理パスを使用します。アグダの連中は、このトピックに関する文献をいくつか持っています。たとえば、Mixfix 演算子の解析、Danielsson および Norell、2009 年。

    設計の観点から、字句解析と構文解析をいくつかの異なるパスに分けることを強くお勧めします。各パスは明確に定義されており、独自の動作を動的に変更しようとするのではなく、前の構造で収集された情報のみを使用します。はるかにシンプルで堅牢なものが得られます。

  3. 動的またはユーザー定義の優先順位と優先順位は、私の意見では、少し悪いです。OCaml には、演算子の優先順位が最初の数文字によって決定される別のシステムがあります (たとえば@@@@+はすべて右結合です)。中置演算子を選択する人にとっては少し制限的ですが、新しいコードに目を動的に適応させる必要がなく、学習する文法規則が 1 セットしかないため、コードリーダーの生活がより快適になります。まったく異なる構文を持つワイルドな外部コードの挿入を許可したい場合、クォーテーション メカニズム (たとえば camlp4 <:foo< ... >>) は、演算子レベルの結合性と優先順位をいじるよりもはるかに堅牢であり、解析もはるかに簡単です。

    とはいえ、プロジェクトにはさまざまなニーズがあり、私が知らないアプリケーションの演算子の優先順位と結合性を動的に変更することを主張した場合は、完全に理解できます。それが唯一の方法ではないことを心に留めておいてください.一貫性とシンプルさは絶対的な柔軟性よりも優れている場合があります.

于 2012-07-02T08:30:47.383 に答える