コンパイラ作成(41) while文

今回の目標

久々に機能追加。

// while文
int main()
{
    int i = 0;
    puts("start");
    while(i < 5) {
        printf("%d * %d = %d\n",i,i,i*i);
        i = i + 1;
    }
    puts("end");
    return 0;
}

while文だよ。if文とそんなに変わらないんで簡単にできると思うよ。

statement

今回の修正はここだけ。

    elsif kind == TK::RESERVE && str == "while" then
      # while文の処理
      @labelcnt += 1
      cond_label = ".LBB_" + @funcname + "_" + @labelcnt.to_s
      @labelcnt += 1
      exit_label = ".LBB_" + @funcname + "_" + @labelcnt.to_s
      codegen cond_label + ":"
      kind, str = @lex.gettoken
      if kind != TK::SYMBOL || str != "(" then perror end
      kind, str = @lex.gettoken
      kind, str = expr kind, str
      if kind != TK::SYMBOL || str != ")" then perror end
      codegen "  jz   " + exit_label
      kind, str = @lex.gettoken
      if kind == TK::SYMBOL && str == "{" then
        kind, str = @lex.gettoken
        loop do
          kind, str = statement kind, str
          if kind == TK::SYMBOL && str == "}" then
            kind, str = @lex.gettoken
            break
          end
        end
      else
        kind, str = statement kind, str
      end
      codegen "  jmp  " + cond_label
      codegen exit_label + ":"
      return kind, str

やってることはif文とだいたい同じ。

動作テスト

どうかな。

~/myc$ myc n4.myc
~/myc$ ./n4
start
0 * 0 = 0
1 * 1 = 1
2 * 2 = 4
3 * 3 = 9
4 * 4 = 16
end
~/myc$

動いたよ。もうちょっと複雑なのもテストしてみる。whileを入子にして九九の表を出力してみるよ。

// while文
int main()
{
    int i = 1, j;
    while(i <= 9) {
        j = 1;
        while(j <= 9) {
            printf("%2d ",i*j);
            j = j + 1;
        }
        printf("\n");
        i = i + 1;
    }
    return 0;
}

どうかな。

~/myc$ myc n7.myc
~/myc$ ./n7
 1  2  3  4  5  6  7  8  9 
 2  4  6  8 10 12 14 16 18 
 3  6  9 12 15 18 21 24 27 
 4  8 12 16 20 24 28 32 36 
 5 10 15 20 25 30 35 40 45 
 6 12 18 24 30 36 42 48 54 
 7 14 21 28 35 42 49 56 63 
 8 16 24 32 40 48 56 64 72 
 9 18 27 36 45 54 63 72 81 
~/myc$

できた。これで大分C言語っぽくなってきたよ。ちなみに今myc.rbは840行だよ。次はfor文か。while文よりちょっと複雑だけどなんとかなるかな。
あ、そだ今回のコーディングだとif文と同じでwhile(1)みたいな場合上手くいかないよ。これも宿題だな。