中置記法(a+b)前置記法(+ab)ポーランド記法ともいう後置記法(ab+)逆ポーランド記法ともいう後置記法の性質は、計算機で計算する時に都合がいい。)演算子を読んだら、スタックの上にそれより優先順位の高い演算子があればそれを(あるだけ順に)スタックから降ろして出力し、読んだ演算子をスタックに積む。目的プログラムは別々のファイルに出力されることになる。年にプログラム言語としては初めて国際的な組織で開発されたものであるが、その構文がバッカス記法によって定義されている。それ以来、多くのプログラム言語の構文規則はバッカス記法、またはそれを拡張した記法で記述されるようになった末端に現れる記号を終端記号、それ以外のものを非終端記号と呼ぶ。つの生成規則の左辺に現れていなければならない文がどのような生成規則から生成されたか、構造を調べることを構文解析という。通り以上存在すれば、その文はあいまいであるという。字句の形は文脈自由文法よりも簡単な正規表現で定義できる字句の定義を正規表現で表現したものから、その字句を読み取る有限オートマトンを機械的に作成する方法を述べる字句解析の流れ読み込んだ原始プログラムの中で最後に返した文字の位置を覚えていて呼ばれたら、その次の文字を返す。返す文字がなかったらファイルから次のひとかたまりを読み込んで、その最初の文字を返す本書では、字句解析の結果として得られる字句の内部表現のことをトークンまたは符と呼ぶ。複数の遷移の可能性がない。(1)各集合を遷移の種類によって分割する。(2)各集合を遷移先によって分割する。構文解析ここでは、まず構文解析の理論と実際の歴史を述べる。探索の際、ある組み合わせが解でなかったなら、戻って別の組み合わせを試す。LL(k)文法という。原始プログラムを左から右に走査しながら、還元できるものを順次還元していく方法。解析をした結果はスタックに積んでおき、スタックの中に還元できるものがそろったら、それを還元しその結果で置き換えるという方法がとられるシフトと還元の操作を適宜行う構文解析をシフト還元構文解析と呼ぶコンパイラで使われるシフト還元構文解析法は、各時点でシフトか還元か間違いなく決められるもので、後戻りなど必要ないもの。還元競合があると、そのどちらを実行すればよいか一般には決まらない。右辺に非終端記号が複数個あるときは、必ずその間に終端記号が入る。意味解析を行うためには、宣言された情報をまとめておく必要があり、一般に表の形にまとめられる。grammer)がある。記号表は、表の探索が効率良くできるように、一般には配列の形で実現される。回の探索が必要になる。大きい場合、探索の速度は線形探索よりずっと速くなるが、プログラムは少し複雑になる。衝突を起こしたものどうしをポインタでつなぐ方式。解析木の上から下に値が決まっていくのは相続属性と呼ばれる。原始プログラムの誤りを発見したら、それを使用者に知らせなければならない。回のコンパイルでできるだけ多くの誤りを見つけるのが望ましい。そのためには誤りがあったらそこのコンパイルは正常に続けられないが、その処理をした後では、できるだけ早く正常の処理に復帰する必要がある。通常のレジスタマシンでは、どのレジスタに対してもその番号を指定して操作できるが、スタックでは常にその先頭に対してしか操作できない。目的コードの生成ここでは目的コードとして、仮想マシンのコードではなく、機械語のコードを生成する方法を述べる原始プログラムが構文解析され、意味解析された結果は中間語と呼ばれる形で表現される。条件の場合などでは、わかった時点で直ちに分岐を決定できる場合がある。最後まで評価するものを「数値表現」と呼ぶ手続きの最初に実行されるコードをプロローグと呼ぶ。最後に実行されるコードはエピローグと呼ぶコード生成器生成系いろんなマッチングがありうる時は、一般にはできるだけ大きいパターンにマッチするほうを選んだほうが良い。コンパイラ)動的コード生成では、原始プログラムのどの部分に、動的コード生成を適用するかという問題がある。最適化とは目的プログラムの最適化とは、効率の良い目的プログラムとすること一般には最も良い目的コードを作り出すことは不可能であり、より良いコートとする努力をする全然最適化していないものと比べれば、少しの努力でも相当な効果が得られる。命令の実行回数を減らすより速い命令を使う並列度を上げる効果的な最適化を行うためには、プログラムの中で最も頻度高く実行される部分を最適化すれば良いループ内の命令ができるだけ並列実行されるようにする手法をソフトウェアパイプライニングというベクトル計算機は、一般にベクトル命令とスカラ命令を備えており、ベクトル命令による実行はスカラ命令のループによる実行よりも非常に高速。ベクトル計算機の性能を生かすためには、できるだけ多くのループをベクトル化する必要がある並列計算機で効率よくプログラムを実行するためには、計算のロードをバランス良く各プロセッサに分配することと、各プロセッサでのメモリアクセスの局所性を高める必要がある共有メモリ型の場合は、すべてのプロセッサからすべての変数に直接アクセスできる。プログラムのどの部分を並列に実行するか指定するだけで、並列実行が可能になる分散メモリ型の並列計算機は、各プロセッサが独立のメモリを持ち、他のプロセッサのメモリにアクセスするためにはデータの転送(メッセージ転送)が必要。プログラムのごく一部を解析して最適化するのは「局所的最適化」と呼ばれる最適化が行われるのは、コンパイラの中では、構文解析と意味解析が終わった後である。各繰り返しに要する時間が一定でない場合は、最初に全部の繰り返しを割り当ててしまうのではなく、一部分を各プロセッサに割り当てる。本章では、プログラムの大域的な解析の基本的な方法として、制御の流れの解析とデータの流れの解析方法を述べる制御フローグラフ制御の流れをグラフで表現したものを制御フローグラフという制御フローグラフは、プログラムの分岐や合流の様子をグラフで表現するも。分岐も合流もない部分を節点として、それらの間を分岐や合流を表す有向辺で結んだ有向グラフデータの流れの解析とは、どこの代入文によって定義された値がどこで使われるかといったことを解析することである。共通部分式を見つけるためには、同じ形の式で同じ値を持つものを探せば良い。副作用があるか、すなわち呼ばれた手続きでどの引数の値が変わるか、どの引数の値は変わらないか引数は定数か。章までに述べてきた最適化の手法は主として中間コードに適用して、より効率の良い中間コードを得るためのものであったが、中間コードから機械語の目的語のコードを生成するにはレジスタ割付けが必要になる目的コードを生成するためには、どんな命令語を使うかという命令語の選択と、それにどのレジスタを使うかというレジスタ割付けが必要。両者の前後関係もいろいろあるまたどれだけの範囲を考慮して行うかも問題。広い範囲を考慮したほうがよりよい結果が得られる可能性がある。対象とするプログラムの範囲の先頭から順次割り付けていく方法もある。同じレジスタを割り付けることができる。実行順序が変わっても結果に関係はなく、プログラム変換をする場合に考慮する必要はない。同様に実行することを意味するベクトル化は一般に次のような手順で行えば良いループ内の変数のデータ依存関係を調べるデータ依存関係のグラフ(依存グラフ)を作る依存グラフにサイクルがない場合は、必要ならば文を適当に並べ替えて、依存関係の矢印がすべて下向きになるようにする(このように並べ替えるのはトポロジカルソーティングと呼ばれる)。その結果をベクトル化できる依存グラフにサイクルがあるときは、名前替えによるサイクルの解消を試みる。今までのループ変換では主として単一計算機でスカラ演算をする場合を考えていた。つのループに変換する。効果ループ分配の逆の効果となるデータの局所性が良くなり、ループの判定の回数が減る。data)型のプログラムを考えるこの場合、各プロセッサでは同じプログラムが並列に実行される。型のプログラムを実行するためには、各プロセッサで必要とするデータはできるだけそのプロセッサに配置しておくことが重要である大きな配列データを扱うプログラムでは、その配列のどの部分をどのプロセッサに置けば最も効率良い計算ができるかを考える必要がある。Fortran)のような言語で配列の分散を指定した場合は、それによって、配列のどの部分がどのプロセッサに置かれるかが決まる(配列分散の解析)配列を各プロセッサに分散し、そのインデックス集合の計算ができたら、次には配列ループの繰り返し点を各プロセッサに分散する(計算分散の解析)各プロセッサへの計算の分散ができたら、次に各プロセッサでの計算に必要なデータが各プロセッサにそろっているかどうかを解析し、必要なデータの転送命令を挿入する(通信の解析)データの転送命令は、そのデータを必要とする計算の前に実行される必要がある。転送のオーバーヘッドを減らすために、できるだけまとめて転送するのがよい。形式を使う方法であった。その方に応じて変わる可能性がある。ないとわかったときに、仮想メソッドテーブルを経由した仮想呼び出しを利用しないようにする。オブジェクトの生存区間が、そのオブジェクトを生成したメソッド内で閉じているかどうかの解析である。閉じていない場合は、そのメソッドから脱出しているといわれる脱出していなければ、そのオブジェクトはヒープではなく、スタックに割り付けることが可能である。オブジェクト指向言語での。