コンピュータサイエンスにおいて、プリプロセッサ(またはプリコンパイラ)[1]は、入力データを処理して、別のプログラムの入力として使用される出力を生成するプログラムです。出力は入力データの前処理された形式と言われ、コンパイラなどの後続のプログラムでよく使用されます。実行される処理の量と種類はプリプロセッサの性質によって異なります。一部のプリプロセッサは比較的単純なテキスト置換とマクロ展開しか実行できませんが、他のプリプロセッサは本格的なプログラミング言語と同等の機能を備えています。
コンピュータ プログラミングの一般的な例としては、コンパイルの次のステップの前にソース コードに対して実行される処理が挙げられます。一部のコンピュータ言語( CやPL/Iなど) には、前処理と呼ばれる翻訳の段階があります。これには、マクロ処理、ファイルのインクルード、言語の拡張も含まれる場合があります。
字句プリプロセッサ
字句プリプロセッサは、字句解析のみを必要とする最も低レベルのプリプロセッサです。つまり、解析の前に、ユーザー定義のルールに従って、トークン化された文字シーケンスを他のトークン化された文字シーケンスに単純に置き換えることによって、ソース テキストを操作します。通常、マクロ置換、他のファイルのテキストの取り込み、条件付きコンパイルまたは取り込みを実行します。
Cプリプロセッサ
最も一般的な例はC プリプロセッサで、これは '#' で始まる行をディレクティブとして受け取ります。C プリプロセッサは、入力に C 言語の構文が使用されることを想定していません。一部の言語では、異なるアプローチを採用し、組み込みの言語機能を使用して同様のことを実現します。例:
- 一部の言語では、マクロの代わりに積極的なインライン展開とテンプレートを使用します。
- 一部の言語では、インクルードの代わりに、オブジェクト コード内の型情報に依存するコンパイル時のインポートを使用します。
- 一部の言語では、条件付きコンパイルを実現するためにデッドコードの削除を
if-then-else使用します。
その他の字句プリプロセッサ
その他の字句プリプロセッサには、 autoconfなどのクロスプラットフォーム ビルド システムで最もよく使用される汎用m4や、コンテキストのパターンに基づいて動作するオープン ソースのマクロ プロセッサであるGEMA などがあります。
構文プリプロセッサ
構文プリプロセッサはLispファミリーの言語で導入されました。その役割は、ユーザー定義のルールに従って構文ツリーを変換することです。一部のプログラミング言語では、ルールはプログラムと同じ言語で記述されます (コンパイル時の反映)。Lisp と OCaml がこれに該当します。他の言語では、 XMLのXSLTプリプロセッサや、静的に型付けされた対応する CDuce など、完全に外部の言語に依存して変換を定義します。
構文プリプロセッサは通常、言語の構文をカスタマイズしたり、新しいプリミティブを追加して言語を拡張したり、汎用言語内に ドメイン固有のプログラミング言語(DSL) を埋め込んだりするために使用されます。
構文のカスタマイズ
構文のカスタマイズの良い例として、Objective Camlプログラミング言語に2つの異なる構文が存在することが挙げられます。[2]プログラムは「通常の構文」または「修正された構文」を使用して同じように記述でき、必要に応じてどちらかの構文できれいに印刷できます。
同様に、 OCamlで書かれた多くのプログラムは、新しい演算子を追加することで言語の構文をカスタマイズします。
言語の拡張
マクロによる言語拡張の最も優れた例は、 Lispファミリーの言語に見られます。これらの言語自体は、単純な動的型付け関数コアですが、SchemeまたはCommon Lispの標準ディストリビューションでは、命令型またはオブジェクト指向プログラミング、および静的型付けが許可されています。これらの機能のほとんどすべては構文プリプロセスによって実装されていますが、Lisp ではコンパイルの「マクロ拡張」フェーズがコンパイラによって処理されることに注意してください。これは、コンパイルの他のフェーズの前に行われるため、プリプロセスの一種と見なすことができます。
言語の専門化
Lisp言語ファミリーの珍しい特徴の 1 つは、マクロを使用して内部 DSL を作成できることです。通常、大規模なLispベースのプロジェクトでは、モジュールはさまざまなミニ言語で記述されます。たとえば、 SQLベースのLisp方言を使用したものや、 GUIやプリティプリントなどに特化した方言で記述されたものなどがあります。Common Lispの標準ライブラリには、このレベルの構文抽象化の例が LOOP マクロの形で含まれています。これは、複雑な反復を記述するための Algol のようなミニ言語を実装しながら、標準的な Lisp 演算子の使用も可能にします。
MetaOCamlプリプロセッサ/言語は、外部 DSL に同様の機能を提供します。このプリプロセッサは、言語のセマンティクスの記述 (つまり、インタープリタ) を受け取り、コンパイル時の解釈とコード生成を組み合わせることで、その定義を OCamlプログラミング言語へのコンパイラに変換し、その言語からバイトコードまたはネイティブ コードに変換します。
汎用プリプロセッサ
ほとんどのプリプロセッサは、特定のデータ処理タスク (C 言語のコンパイルなど) に特化しています。プリプロセッサは、汎用として宣伝されることがあります。これは、特定の用途やプログラミング言語を対象としておらず、さまざまなテキスト処理タスクに使用することを目的としています。
C プリプロセッサが C に特化しない役割で使用されることもありますが、 M4 はおそらくこのような汎用プリプロセッサの最もよく知られた例です。例:
- JavaScriptの前処理にCプリプロセッサを使用する。[3] [4]
- Linuxカーネル内でデバイスツリー処理にCプリプロセッサを使用する。[5]
- M4 (記事内の例を参照)またはCプリプロセッサ[6]をテンプレートエンジンとして使用し、HTMLを生成します。
- imake は、C プリプロセッサを使用するmakeインターフェイスで、 X Window System用に作成されましたが、現在はautomakeに置き換えられて非推奨となっています。
- grompp は、GROMACS (計算化学のいくつかの問題に対する高速で無料のオープンソース コード) のシミュレーション入力ファイル用のプリプロセッサであり、システム C プリプロセッサ (またはシミュレーション入力ファイルによって決定される他のプリプロセッサ) を呼び出してトポロジを解析し、主に #define および #include メカニズムを使用して、grompp 実行時に有効なトポロジを決定します。
参照
- ディレクティブ(プログラミング) – コンパイラが入力をどのように処理するかを指定する言語構造
- メタプログラミング – プログラミング パラダイム
- マクロ – 設定された入力を設定された出力に置き換えるルール
- ソースツーソースコンパイラ、トランスパイラとも呼ばれる – コンピュータソースコードの翻訳者
- Sass (スタイルシート言語) – スタイルシート言語
- Stylus (スタイルシート言語) – スタイルシートプリプロセッサ言語
- Less (スタイルシート言語) – 動的スタイルシート言語
- スニペット(プログラミング) – 再利用可能なソースコード、マシンコード、またはテキストの小さな領域
- テンプレートエンジン – テンプレートとデータモデルを組み合わせて結果ドキュメントを生成するように設計されたソフトウェア
- Cプリプロセッサ – 複数のプログラミング言語用のマクロ プリプロセッサ
- OCamlプリプロセッサ プリティ プリンタ – プログラミング ソフトウェア システム
- PL /Iプリプロセッサ
- Windowsソフトウェア トレース プリプロセッサ
- 汎用マクロ プロセッサ – 特定の言語またはソフトウェアに関連付けられたり統合されたりしないマクロ プロセッサ。
参考文献
- ^ 「プリコンパイラとは何ですか?」IBM。
- ^ Caml 言語のウェブサイトから改訂された構文
- ^ JavaScript ファイルで C プリプロセッサを使用する方法を示します。「JavaScript は工業的強度ではありません」、T. Snyder 著。
- ^ 「Javascript の C プリプロセッサ?」。espresso-mode。
- ^ 「Kernel/Git/Stable/Linux.git - Linux カーネル安定ツリー」。
- ^ C プリプロセッサをテンプレート エンジンとして使用する方法を示します。「C プリプロセッサを HTML オーサリング ツールとして使用する」、J. Korpela 著、2000 年。
外部リンク
- Lisp での DSL 設計
- ゼロからプログラミングする
- 汎用プリプロセッサ
- 汎用マクロプロセッサ Gema
- PIKT piktc テキスト、スクリプト、および構成ファイル プリプロセッサ
- pyexpander、Python ベースの汎用マクロプロセッサ
- minimac、ミニマリストマクロプロセッサ
- Java コメントプリプロセッサ
