3、動作例とその説明 (1)、siki_1.txt x := 3; y := 5; z := x * y - (y - x); この対象言語は先生にもらった資料に記述されているもので、まずはこれをコンパイルにより解析してみる。 今回作ったコンパイラは、同じつづりのものを同じ字句として解析することができないため、同じであってもそれぞれ前から読んでいき、順次別の字句とアドレスを設定していっている。 以下の例では、 z := x * y - (y - x); のxとyは、それぞれ式の中に2回づつ使われているが、今回のプログラムでは前から順に以下のようにアドレスを設定しているのがわかる。 kigou1 kigou2 address z i1.3 004128DC x i2.3 00412960 y i3.3 004129E4 y i4.3 00412B70 x i5.3 00412BF4 このように、したことでメモリをムダに使ってる感が否めないが、計算の結果は同様のものが得られるためによしとした。 しかし、字句解析としてはこれは不十分な場所だといえる。 時間があれば、これも同じつづりのものは同じ字句・同じアドレスとして設定するようにしたい。 また、資料の4.2.3の課題3-1の問題も1行目と2行目のコード生成を見る限りでは、クリアしていることが分かる。 とりあえず、出力されたテキストファイルのコンパイラのデータの説明を個別にしておく。 (@)【1-gyoume】 読み込んだ対象言語のテキストファイルの1行目を示している。 つまり、この動作結果の場合は1行目の解析は 'x := 3;' の解析を示している。 (A)【motono-siki】 読み込んだ対象言語を字句解析により解析し、その解析した字句で元の対象言語を書き直したものになっている。 1行目の解析を例にあげると、 x → i1.1 3 → num1.1 と字句解析し、対象言語を解析した字句と置き換えて i1.1 := num1.1 と表現している。 (B)【gyakupooranndokihou-siki】 字句解析した対象言語を、構文解析により逆ポーランド記法で表したものに書き換えている。 1行目の解析を例にあげると、元の対象言語が以下なので、 i1.1 := num1.1 これを逆ポーランド記法で書き換える事で、以下のように表現される。 i1.1 num1.1 := (C)【kigouhyou/teisuuhyou】 ここで、字句解析によって解析された識別子と定数の表を表示している。 1行目の例では、上記で説明した通り、 x → i1.1 3 → num1.1 と字句が表現し直されているので、以下のような記号表と定数表が表示されている。 【kigouhyou/teisuuhyou】 kigou1 kigou2 address x i1.1 004128DA teisu1 teisu2 address 3 num1.1 00412960 ここで、 kigou1 → 元の対象言語におけるつづり kigou2 → 字句解析によって表現し直された字句 adress → 字句解析によって設定された字句が格納されているメモリ上のアドレス(パソコン環境によって当然変わる) となっている。 (D)【code-generation】 コード生成の結果が表示されている。 コードはアセンブリ言語で表現されており、アドレスは記号表・定数表で設定されているメモリ上のアドレスに対応している。 1行目のコード生成を例にあげると、コードが、 LOAD 00412960 STORE 004128DA となっていて、アドレスと字句の対応が、 kigou1 kigou2 address x i1.1 004128DA teisu1 teisu2 address 3 num1.1 00412960 となっているので、 まず、'LOAD 00412960'により、ACCにアドレス'00412960'上のデータ、記号表より'3'が置かれる。 次に、'STORE 004128DA'により、ACC上のデータつまりは、'LOAD 00412960'によって読み込まれた'3'が、アドレス'004128DA'のメモリに読み込まれる。 このときアドレス'004128DA'は、'x'が置かれているために、'x := 3;'という意味になり、マシンが'x := 3;'という対象言語をアセンブリ言語により理解したことになる。 ここで、個別に各コードの説明をしておく。 命令コード 意味 LOAD M (M) → ACC STORE M (ACC) → M ADD M (ACC) + (M) → ACC SUB M (ACC) - (M) → ACC MUL M (ACC) * (M) → ACC DIV M (ACC) / (M) → ACC ※()はそのアドレス上に置かれているデータの事を示している。 【siki_1.txt】の動作結果をみると、上記に説明した内容を表現できているようだ。 ↓【siki_1.txt】の動作結果ここから --------------------------------------------------- 【1-gyoume】 【motono-siki】 i1.1 := num1 【gyakupooranndokihou-siki】 i1.1 num1.1 := 【kigouhyou/teisuuhyou】 kigou1 kigou2 address x i1.1 004128DA teisu1 teisu2 address 3 num1.1 00412960 【code-generation】 LOAD 00412960 STORE 004128DA 【2-gyoume】 【motono-siki】 i1.2 := num1.2 【gyakupooranndokihou-siki】 i1.2 num1.2 := 【kigouhyou/teisuuhyou】 kigou1 kigou2 address y i1.2 004128DB teisu1 teisu2 address 5 num1.2 00412963 【code-generation】 LOAD 00412963 STORE 004128DB 【3-gyoume】 【motono-siki】 i1.3 := i2.3 * i3.3 - (i4.3 - i5.3) 【gyakupooranndokihou-siki】 i1.3 i2.3 i3.3 * i4.3 i5.3 - - := 【kigouhyou/teisuuhyou】 kigou1 kigou2 address z i1.3 004128DC x i2.3 00412960 y i3.3 004129E4 y i4.3 00412B70 x i5.3 00412BF4 teisu1 teisu2 address 【code-generation】 LOAD 00412960 MUL 004129E4 STORE 00412D71 LOAD 00412B70 SUB 00412BF4 STORE 00412D72 LOAD 00412D71 SUB 00412D72 STORE 004128DC --------------------------------------------------- ↑【siki_1.txt】の動作結果ここまで。 --------------------------------------------------- (2)、siki_2.txt abc := e3 * 256 - abc / e3; これは、指導書に書かれている例の対象言語である。 相変わらず同じつづりのものを同じ識別子・定数として表現はできていないが、それ以外の問題はないと思われる。 一時的にデータを置いて置くアドレス(以下の例でいうと'00412BEE'や'00412BED'など)も、記号表と定数表で設定されている字句のアドレスと重複されることなく設定されているのがわかる。 ↓【siki_2.txt】の動作結果ここから --------------------------------------------------- 【1-gyoume】 【motono-siki】 i1.1 := i2.1 * num1.1 - i3.1 / i4.1 【gyakupooranndokihou-siki】 i1.1 i2.1 num1.1 * i3.1 i4.1 / - := 【kigouhyou/teisuuhyou】 kigou1 kigou2 address abc i1.1 004128DA e3 i2.1 0041295E abc i3.1 00412AEA e3 i4.1 00412B6E teisu1 teisu2 address 256 num1.1 004129E4 【code-generation】 LOAD 0041295E MUL 004129E4 STORE 00412BED LOAD 00412AEA DIV 00412B6E STORE 00412BEE LOAD 00412BED SUB 00412BEE STORE 004128DA --------------------------------------------------- ↑【siki_2.txt】の動作結果ここまで。 --------------------------------------------------- (3)、siki_3.txt abc := def * 256 - e8; abc := def * 256 - (e8 + 512); abc := def * 256 + (e8 + 512); abc := def * 256 / (e8 + 512); abc := def * 256 * (e8 + 512); 【siki_3.txt】では、スタック上のACCの位置によるコード生成の場合分けを全てふまえたような対象言語を設定して、全ての場合において、正確にコード生成ができているかを調べてみた。 指導書における、表4の命令コード生成表を参考にした。 1行目は命令コード生成表の1、2、5の命令を使って生成している。生成されたコードをみると正確に生成されている。 2行目は命令コード生成表の1、4、5の命令を使って生成している。生成されたコードをみると正確に生成されている。 3行目は命令コード生成表の1、3、5の命令を使って生成している。生成されたコードをみると正確に生成されている。 4行目は命令コード生成表の1、4、5の命令を使って生成している。生成されたコードをみると正確に生成されている。 5行目は命令コード生成表の1、3、5の命令を使って生成している。生成されたコードをみると正確に生成されている。 ↓【siki_3.txt】の動作結果ここから --------------------------------------------------- 【1-gyoume】 【motono-siki】 i1.1 := i2.1 * num1.1 - i3.1 【gyakupooranndokihou-siki】 i1.1 i2.1 num1.1 * i3.1 - := 【kigouhyou/teisuuhyou】 kigou1 kigou2 address abc i1.1 00412906 def i2.1 0041298A e8 i3.1 00412B16 teisu1 teisu2 address 256 num1.1 00412A10 【code-generation】 LOAD 0041298A MUL 00412A10 SUB 00412B16 STORE 00412906 【2-gyoume】 【motono-siki】 i1.2 := i2.2 * num1.2 - (i3.2 + num2.2) 【gyakupooranndokihou-siki】 i1.2 i2.2 num1.2 * i3.2 num2.2 + - := 【kigouhyou/teisuuhyou】 kigou1 kigou2 address abc i1.2 00412907 def i2.2 0041298B e8 i3.2 00412B9B teisu1 teisu2 address 256 num1.2 00412A13 512 num2.2 00412C23 【code-generation】 LOAD 0041298B MUL 00412A13 STORE 00412D1D LOAD 00412B9B ADD 00412C23 STORE 00412D1E LOAD 00412D1D SUB 00412D1E STORE 00412907 【3-gyoume】 【motono-siki】 i1.3 := i2.3 * num1.3 + (i3.3 + num2.3) 【gyakupooranndokihou-siki】 i1.3 i2.3 num1.3 * i3.3 num2.3 + + := 【kigouhyou/teisuuhyou】 kigou1 kigou2 address abc i1.3 00412908 def i2.3 0041298C e8 i3.3 00412B9C teisu1 teisu2 address 256 num1.3 00412A16 512 num2.3 00412C26 【code-generation】 LOAD 0041298C MUL 00412A16 STORE 00412D9D LOAD 00412B9C ADD 00412C26 ADD 00412D9D STORE 00412908 【4-gyoume】 【motono-siki】 i1.4 := i2.4 * num1.4 / (i3.4 + num2.4) 【gyakupooranndokihou-siki】 i1.4 i2.4 num1.4 * i3.4 num2.4 + / := 【kigouhyou/teisuuhyou】 kigou1 kigou2 address abc i1.4 00412909 def i2.4 0041298D e8 i3.4 00412B9D teisu1 teisu2 address 256 num1.4 00412A19 512 num2.4 00412C29 【code-generation】 LOAD 0041298D MUL 00412A19 STORE 00412E1D LOAD 00412B9D ADD 00412C29 STORE 00412E1E LOAD 00412E1D DIV 00412E1E STORE 00412909 【5-gyoume】 【motono-siki】 i1.5 := i2.5 * num1.5 * (i3.5 + num2.5) 【gyakupooranndokihou-siki】 i1.5 i2.5 num1.5 * i3.5 num2.5 + * := 【kigouhyou/teisuuhyou】 kigou1 kigou2 address abc i1.5 0041290A def i2.5 0041298E e8 i3.5 00412B9E teisu1 teisu2 address 256 num1.5 00412A1C 512 num2.5 00412C2C 【code-generation】 LOAD 0041298E MUL 00412A1C STORE 00412E9D LOAD 00412B9E ADD 00412C2C MUL 00412E9D STORE 0041290A --------------------------------------------------- ↑【siki_3.txt】の動作結果ここまで。 (4)、エラー表示・不完全な部分。 ・対象言語に式の終わりを表す記号';'がないと、無限ループになってしまう。 ・(()のような対象言語の場合でも、(()→()と判断し解析してしまう。 ・':'の次に'='がこなかったとき字句解析エラーを表示する。 ・逆ポーランド記法において、最初に識別子か定数がこなかった場合、コード生成エラーを表示する。