コンパイラ構成論はまだ終了してないぜ

いつの間にかShift/Reduce競合を直しなさいの項目が消えていました。また私が困る層の読者が増えていないことを祈ります。

3.変数のポストインクリメント(CやJavaでは x++)を実現 しなさい.
4.repeat-until文を実現しなさい.

まず字句解析器の部分に新たなトークンの定義を追加し、そのトークンを識別して返すようにし、コメントにある文法定義を追加し、それに合わせて構文解析器の動作を追加し、それの吐くAST*1のノード定義を追加し、エミッタ(出力器)に対応する機械語*2を吐くコードを追加する作業。これ面倒なんだよおおおおおおおお。
まあまずその前に中間出力のJavaアセンブラファイル*3を読んで文法とJava仮想マシンの性質と挙動を把握する作業。元のオリジナル言語のソースコードと出力されたアセンブラファイルを見比べていれば耐える。これ1回休んだ時にやってたのかな…?その時入院の秘孔を突かれてたからな…。誰だよyappyはバイナリでJavaバイトコードを読み書きできるって言ったやつ…。


Java仮想マシンはスタックマシン。計算は例えば足し算なら2個値をpushして足し算命令をすると2個の値がpopされて答えが1個pushされる的なアレ。メソッドの最初には.limit stackでこの関数内でスタックが伸びる最大値っぽいものと、.limit localsでこの関数のローカル変数の個数を指定するっぽい。レジスタマシンでのレジスタがスタックで、メモリがローカル変数と考えるとだいたいいいっぽい。iload kやistore kでスタックトップへのローカル変数のpush、スタックトップをpopしてのローカル変数への保存ができるっぽい。kはローカル変数番号で1から始まるっぽい。あとは即値push命令やスタックマシンらしくオペランドなしの加減乗除命令とか分岐命令とか。

The iinc instruction takes two integer parameters:
iinc
for example:
iinc 3 -10 ; subtract 10 from local variable 3

ウホッいい命令。後置++とかそもそもJavaにあるんだから当然か…。


なぜdo-whileでなくてrepeat-untilなのかと思ったらwhileからの生成コードが条件式condが偽の時にジャンプするものだったので、それを流用できる有情設定でした(condが偽の時にrepeatの始まりに飛べばいいからね)。……と思わせておいてcondの出力関数が勝手に次の新規ラベル番号を取得してその番号に条件ジャンプするコードを吐いてその番号を返すという仕様。ループ開始位置にラベルを吐き、ループ本体を出力し、条件式とそこからループ開始位置への条件ジャンプを吐かなければいけないので無理ゲーです。ああ…なぜ…。まあ理論的に何とかなるので無条件ジャンプとラベルを組み合わせて無理やり「正しく」動くようにしました。なにこのゴミコンパイラ。

5. for文を実現しなさい(どのような構文でもよい).
6. x ** y によって,xのy乗を計算するような演算子**を実 現しなさい.
7. 関数を定義できるようにしなさい.
8. 関数の入れ子定義ができるようにしなさい.

7と8はさすがに賢者*4安定かな…。


……4時半か。久しぶりだなこういうのも。天子を分からせるかこういうことをしているときのみ生を実感できる*5…。

*1:抽象構文木

*2:以下全部Javaバイトコードのこと。

*3:Jasminのもの。

*4:ベタオリ。

*5:まあ前半は冗談だが