コンパイラ設計の高レベル概観


イントロ


それで、あなたはシニアJavaScript WEB 3で10年の経験をします.0 SteamPunkソフトウェア、あなたは起業家、コンサルティングスターとエンジニアです…しかし、あなたはどのようにあなたのコンピュータが「どう読むか」と解釈して、「プログラム」を実行しますか?CSのこの重要な部分を理解しやすくする私の試みは、ここにあります.
私は少し簡素化し、おそらくいくつかの不適切な比較を行うことを実現しますが、私はちょうど自分自身と他の人々に精神的なモデルをしようとしている.今、免責事項が行われ、我々はウサギの穴に掘り始めることができる、私の手を取ると飛ぶことができます!

ハイレベル概要


したがって、コンパイラの非常に高いレベルの概観のための時間

高レベルの言語-それはJavaScript、Python、C++、あなたの素敵な言語の名前などをすることができますので、一言で言えば、それは文字列です.
コンパイラ-前の手順に基づいて、コンパイラの入力が文字列であり、結果がアセンブリ言語であるという考えをすでに考えています.したがって、コンパイラは、単に文字列を取り、別の文字列を生成する単純な関数として考えることができます.
Assembly code string = compiler(high level language string)
最後の質問は-アセンブリコードとは何ですか?
アセンブラ-別のオペレーティングシステムのマニュアルのようです言い換えると、それはいくつかの特定のアーキテクチャを備えたマシンのための命令セットです
そして最後の動きです
マシンコード-実際にはゼロと
しかし、あなたは私が最後のブロック2つの部分-ローダ/リンカに配置することができます.
ちょうどあなたの情報のために、彼らを少しカバーしましょう.
リンカ-はコンパイラ/アセンブラによって生成されたオブジェクトファイルと他のビットコードを結合して実行可能ファイルを.exe拡張で生成するプログラムです.オブジェクトファイルでは、リンカはファイルの実行に必要なすべてのライブラリを検索して追加します.これは、各モジュールからコードを保持するメモリ空間を調整します.
そして、ローダはリンカから実行可能ファイルの入力をとって、それを主記憶装置にロードして、コンピュータによって実行されるこのコードを準備する特別なプログラムです.ローダはメモリ空間をプログラムに割り当てる.も、オブジェクト間の記号参照を解決します.これは、オペレーティングシステムの読み込みプログラムやライブラリを担当している.埋め込まれたコンピューターシステムは、ローダを持っていません.
(これらの2つの定義をthis siteからコピーした)

ウサギ穴に深く


それでは、別のステップを踏んでコンパイラの部品を掘りましょう.
そして、探検するもう一つのイメージ

語彙解析-空白、無駄なシンボルを削除し、トークンのストリームを返します.例えば、
入力文字列
SELECT * FROM "docs";
次のトークンを引くことができるイテレータとしてストリームを考えることができます.以下に擬似コードを示します:
Lexer.next() -> { kind: Keyword, type: "SELECT" }
Lexer.next() -> { kind: Asterisk  }
Lexer.next() -> { kind: Keyword, type: "FROM" }
Lexer.next() -> { kind: Char, value: "\"" }
Lexer.next() -> { kind: String, value: "docs" }
Lexer.next() -> { kind: Char, value: "\"" }
それで、lexerは我々の言語またはアルファベットから有効な文字を表します.
よりよく理解するために、単純な文字列の構文解析を開始しましょう.
x = a + b * c;
人間として、我々は簡単に解析し、そのようなステートメントを理解することができますが、それはコンピュータのために容易ではない.パーサーの目的を既にカバーしており、上記の文を解析しましょう.簡単にしましょう.
id = id + id * id
idは識別子で、配列として表現しようとすると、以下のようになります.
[
  { type: 'id', value: x },
  { type: 'symbol', value: '=' },
  { type: 'id', value: 'a' },
  { type: 'symbol', value: '+' }, 
  { type: 'id', value: 'b' },
  { type: 'symbol', value: '*' },
  { type: 'id', value: 'c' },
  { type: 'symbol', value: ';' },
]
Parser -文脈自由文法を使用します(parse treeを作成するために、次の部分でこの定義をカバーします).
神経質になる必要はありません、我々は多くの複雑な定義と条件を導入するつもりです、そして、あなたが少し失われているとわかるならば、それはOKです.我々は、次の章で構文解析に関連するすべてをカバーします.
それで、言語文法パーサーに基づいて解析木を作成します.
BNF notationのいくつかの文法の例を見てみましょう.
S ⭢ id = E
E ⭢ E + T
  |  T
T ⭢ T * F
  | F
F ⭢ id

この文法に基づいて、解析木を構築できます.

セマンティックアナライザ-文法エラーを見つけるために解析木を検証します.
中間コード発生器
例えば、以下のようになります.
t1 = b * c;
t2 = a + t1;
x = t2;
コードオプティマイザー(CO)- 3つのアドレスコードを最適化します.
t1 = b * c;
x = a + t1;
ターゲットコードジェネレータ-アセンブラが理解できるコードを作成します.
ランダムな擬似アーキテクチャ
mul R1, R2
add R0, R2
mov R2, x
ここで、a = r 0、b = r 1、c = r 2
質問をしたり、意見や懸念を表明したり、ビューのあなたの視点を議論してください.共有、購読、およびコードを、戦争ではない.❤️
あなたがエラーを見つけるならば、私はそれを修理するか、あなたから学ぶことがうれしいです-ちょっと私に知らせてください.
あなたは私をDMまたは接続することができます.私は常に新しい接続、人々、機会に開いている.