埋め込みヘルパー
2007年3月26日
ここ数週間、私はコンパイラーコンパイラーツールで遊んで、そして調べてきました。これらのツールの共通の特徴は、言語の生成規則の記述を中心とした文法ファイルを持っていることです。文法を記述するだけでなく、ファイルはパーサーに、言語要素を認識しながら言語を処理する方法についての情報も提供します。ほとんどのコンパイラーコンパイラーツールでは、これらの命令は文法内のアクションとして表されます。多くの場合、これらのアクションは、高レベル言語のコードフラグメントとしてエンコードされます。
たとえば、私のHelloAntlrの例では、ソースファイルから設定を作成して設定するために、埋め込まれたJavaの断片を見ることができます。(Javaの埋め込みだけが唯一のアプローチではなく、ツリーウォーキングも別のアプローチです。)
汎用言語(GPL)を別のドメイン特化言語(DSL)内に埋め込むこのアプローチは非常に一般的です。ほとんどの読者は、Velocity、JSP、ERBなどのテンプレートシステムを使用してHTMLページを作成するときに、これに出くわしたことがあるでしょう。ここでも、動的データとより複雑な処理を提供するためにGPLのフラグメントを埋め込むことができる、異なる表現(HTML)があります。
このような環境で作業する場合、テンプレート内のJava(または使用しているGPL)の量を最小限に抑えるようにしています。このための一般的な手法は、Javaで別のヘルパークラスを作成し、テンプレート内のすべての埋め込みJavaがこのヘルパーへの単純なメソッド呼び出しを行うようにすることです。
私がこれを行うのが好きな主な理由は、DSLに大量のGPLを埋め込むと、DSLのフローが分かりにくくなってしまうと考えるからです。HTMLにテンプレート言語を使用する目的は、HTMLに集中することなので、そこにJavaを埋め込むたびに邪魔になります。これは、アクションに多くのコードがあるとプロダクションを理解しにくくなる文法ファイルでは特に当てはまります。
埋め込みヘルパーを使用するもう1つの利点は、ツールがジョブを実行しやすくなることです。単純な構文の強調表示であっても、PostIntelliJ IDEのフルパワーであっても、これらのツールは多くの場合、混合言語ファイルではうまく機能しません。たとえば、ANTLRWorksはANTLRの文法を強調表示し、補完を提供しますが、埋め込まれたJavaはプレーンテキストです。
このようなヘルパーを使用する場合、私の通常のスタイルは、ホスト(DSL)ファイルの早い段階にヘルパーを設定するためのコードを含めることです。通常、これはホストにフィールドを宣言し、そこで新しいヘルパーを構築するか、呼び出し元がヘルパーを渡せるようにすることを伴います。(私はこのためにANTLR文法でパブリックフィールドを使用しても構わないと思っています。)その後、ホスト内のすべての埋め込みJavaは、ヘルパーへの単純な呼び出しになります。私はこれらの呼び出しに、ホストファイルの観点から名前を付け、ヘルパーから何が求められているかを示します。
ヘルパーとホストファイルは非常に密接に結合されており、通常は双方向のリンクがあり、多くのやり取りがあります。ヘルパーはホストに関するあらゆる種類の厄介な詳細を知っています。私はHTMLヘルパーがHTMLを出力しても構いませんし、文法ヘルパーは構文木を調べます。
通常、私はクラスの「ヘルパー」という言葉は、不十分に考えられた抽象化を示しているため、レッドフラグとして扱います。ここでは、ヘルパーは実際にはホストファイルのサポートとしてのみ存在するため、この言葉を使用しても構いません。