コンパイラ設計とは何ですか? 種類、構築ツール、例
⚡ スマートサマリー
コンパイラのフェーズでは、ソースコードを機械語に変換する6つの段階(字句解析、構文解析、意味解析、中間コード生成、コード最適化、コード生成)について説明します。これらの段階は、シンボルテーブル管理とエラー処理によってサポートされます。
コンパイラ設計のフェーズは何ですか?
A コンパイラ コンパイラは様々なフェーズで動作し、各フェーズはソースプログラムをある表現形式から別の表現形式に変換します。各フェーズは前のフェーズから入力を受け取り、その出力を次のフェーズに渡します。コンパイラには6つのフェーズがあります。これらの各フェーズは、高水準言語を機械語に変換するのに役立ちます。コンパイラのフェーズは次のとおりです。
- 字句解析
- 構文解析
- 意味解析
- 中間コードジェネレータ
- Code オプティマイザ
- Code ジェネレータ
コンパイラのフェーズ
これらのすべての段階では、ソースコードをトークンに分割し、構文木を作成し、さまざまな段階を経てソースコードを最適化することで、ソースコードを変換します。
フェーズ 1: 字句解析
字句解析は最初の段階で、コンパイラがソースコードをスキャンします。このプロセスは左から右へ、文字ごとに処理され、これらの文字がトークンにグループ化されます。
ここでは、ソースプログラムからの文字ストリームがトークンを識別することによって意味のあるシーケンスにグループ化されます。対応するトークンがシンボルテーブルに登録され、そのトークンが次のフェーズに渡されます。
このフェーズの主な機能は次のとおりです。
- ソースコード内の語彙単位を特定する。
- 語彙単位を定数、予約語などのクラスに分類し、それぞれ異なるテーブルに格納します。ソースプログラム内のコメントは無視されます。
- 言語の一部ではないトークンを特定する。
例: x = y + 10
| Next | タイプ |
|---|---|
| X | 識別子 |
| = | 代入演算子 |
| Y | 識別子 |
| + | 加算演算子 |
| 10 | 数 |
フェーズ 2: 構文分析
構文解析とは、コード内の構造を明らかにすることです。テキストが想定される形式に従っているかどうかを判断します。この段階の主な目的は、プログラマーが記述したソースコードが正しいかどうかを確認することです。
構文解析は、トークンを用いて構文木を構築することにより、特定のプログラミング言語の規則に基づいて行われます。また、ソース言語の構造と、その言語の文法または構文を決定します。
このフェーズで実行されるタスクの一覧は以下のとおりです。
- 語彙解析器からトークンを取得します。
- その表現が構文的に正しいかどうかを確認してください。
- 構文エラーはすべて報告してください。
- 構文解析木と呼ばれる階層構造を構築する。
例:
識別子や数値はすべて式です。xが識別子で、y+10が式である場合、x = y+10は文です。次の例の構文木を考えてみましょう。
(a+b)*c
構文解析ツリー内:
- 内部ノード:演算子フィールドと子ノード用の2つのフィールドを持つレコード。
- リーフ:2つ以上のフィールドを持つレコード。1つはトークン用、もう1つはトークンに関するその他の情報用。
- プログラムの各構成要素が意味のある形で連携するようにする。
- 型情報を収集し、型の互換性をチェックします。
- オペランドがソース言語で許可されているかどうかを確認します。
フェーズ 3: セマンティック分析
セマンティック分析は、コードのセマンティック一貫性をチェックします。 前のフェーズの構文ツリーとシンボル テーブルを使用して、指定されたソース コードが意味的に一貫していることを検証します。 また、コードが適切な意味を伝えているかどうかもチェックします。
セマンティックアナライザーは、型の不一致、互換性のないオペランド、不適切な引数で呼び出された関数、未宣言の変数などをチェックします。
意味解析フェーズの機能は以下のとおりです。
- 収集した型情報を保存し、シンボルテーブルまたは構文ツリーに保存するのに役立ちます。
- 型チェックを実行できます。
- 型が一致しない場合、つまり、目的の操作を満たす正確な型修正規則が存在しない場合は、意味エラーが表示されます。
- 型情報を収集し、型の互換性をチェックします。
- ソース言語がオペランドを許可しているかどうかを確認します。
例:
float x = 20.2; float y = x*30;
上記のコードでは、セマンティックアナライザーは乗算を行う前に、整数30を浮動小数点数30.0に型変換します。
フェーズ4:中級 Code 世代
意味解析フェーズが終了すると、コンパイラはターゲットマシン用の中間コードを生成します。これは、ある絶対値に対するプログラムを表します。tractマシン。
中間コードは、高級言語と機械語の中間に位置するコードです。この中間コードは、ターゲットとなる機械語に容易に変換できるような方法で生成する必要があります。
中間関数の機能 Code 世代:
- それは、ソースプログラムの意味表現から生成されるべきである。
- 翻訳処理中に計算された値を保持します。
- 中間コードをターゲット言語に翻訳するのに役立ちます。
- ソース言語の優先順位を維持できます。
- 命令のオペランドを正しい数だけ保持している。
例:
具体的な例を挙げますと、以下の通りです。
total = count + rate * 5
アドレスコード方式を用いた中間コードは以下のとおりです。
t1 := int_to_float(5)
t2 := rate * t1
t3 := count + t2
total := t3
フェーズ5: Code 最適化
次の段階は、中間コードの最適化です。この段階では、不要なコード行を削除し、ステートメントの順序を調整することで、リソースを無駄にすることなくプログラムの実行速度を向上させます。この段階の主な目的は、中間コードを改善し、より高速に実行され、より少ないメモリ容量で動作するコードを生成することです。
このフェーズの主な機能は次のとおりです。
- これは、実行速度とコンパイル速度の間のトレードオフを確立するのに役立ちます。
- 対象プログラムの実行時間を改善します。
- 中間表現のまま、簡潔なコードを生成します。
- 到達不能なコードを削除し、未使用の変数を消去する。
- 変更されていないステートメントをループから削除します。
例: 次のコードについて考えてみます。
a = intofloat(10)
b = c * a
d = e + b
f = d
なり得るもの:
b = c * 10.0
f = e + b
フェーズ6: Code 世代
Code 生成はコンパイラの最終段階です。コード最適化段階からの入力を受け取り、ページコードまたはオブジェクトコードを生成します。この段階の目的は、記憶領域を割り当て、再配置可能なマシンコードを生成することです。
また、変数用のメモリ位置も割り当てます。中間コード内の命令は機械語命令に変換されます。このフェーズでは、最適化された中間コードがターゲット言語に変換されます。
対象言語は機械語です。そのため、すべてのメモリ位置とレジスタもこの段階で選択され、割り当てられます。この段階で生成されたコードが実行され、入力を受け取り、期待される出力を生成します。
例:
a = b + 60.0 は、レジスタに以下のように変換される可能性があります。
MOVF a, R1 MULF #60.0, R2 ADDF R1, R2
シンボルテーブル管理
シンボルテーブルには、識別子ごとにレコードが格納され、そのレコードには識別子の属性を表すフィールドが含まれています。このコンポーネントにより、コンパイラは識別子レコードを簡単に検索し、迅速に取得できます。シンボルテーブルはスコープ管理にも役立ちます。シンボルテーブルとエラーハンドラはすべてのフェーズと連携し、シンボルテーブルはそれに応じて更新されます。
エラー処理ルーチン
コンパイラ設計プロセスでは、以下のすべての段階でエラーが発生する可能性があります。
- 語彙解析器: スペルミスのあるトークン。
- 構文解析器: 括弧が抜けています。
- 中間コード生成ツール: 演算子に対してオペランドが一致していません。
- Code オプティマイザ: ステートメントにアクセスできない場合。
- Code Generator: メモリがいっぱいの場合、または適切なレジスタが割り当てられない場合は、メモリが割り当てられません。
- シンボルテーブル: 複数の識別子が宣言されています。
最も一般的なエラーは、スキャン時の無効な文字シーケンス、型における無効なトークンシーケンス、スコープエラー、および意味解析における構文解析エラーです。
エラーは上記のどの段階でも発生する可能性があります。エラーが検出された後、コンパイル処理を続行するには、エラーを処理する必要があります。これらのエラーはエラーハンドラに報告され、エラーハンドラがエラーを処理してコンパイル処理を実行します。一般的に、エラーはメッセージの形式で報告されます。



