コンパイラ作成(6) 色々修正

コンパイルはできるようになったけど、問題ありありだったんで修正してくよ。まずは構文解析、コード生成をParserクラスに分離した。前回のコードはさぼりだったね。んで、アセンブリコードの出力先もファイルへ変更。この辺は簡単なんでさっくりできたよ。(だったら最初からそうしとけよ、俺)

~/myc$ ./myc.rb err1.myc 
Syntax error
~/myc$ cat err1.s
.intel_syntax noprefix
.global main
main:
  mov rax, 42
  ret
~/myc$

できたできた。ついでなんでエラーの表示もちょっとだけ分かりやすくするか。

~/myc$ ./myc.rb err1.myc 
err1.myc:3:14 error: expected ';' after return statement
~/myc$

やってみたらちょこっとした修正でできたよ。

  # コンパイルエラーを表示
  def perror(emsg = "Syntax error" )
    fname, lineno, pos = @lex.position
    print fname,":",lineno,":",pos," error: ", emsg, "\n"
    exit -1;    # コンパイル処理を打ち切る
  end

Lexerクラスでgettokenが呼ばれた時の行、桁情報を保持するようにして、perrorでそれを表示してる。

  # 文の構文解析
  def statement()
    kind, str = @lex.gettoken
    if kind == TK::SYMBOL && str == "}" then return false end
    if kind == TK::ID && str == "return" then
      # return文の処理
      kind, str = @lex.gettoken
      if kind == TK::NUMBER then
        codegen "  mov rax, "+str
        codegen "  ret"
      end
      kind, str = @lex.gettoken
      if kind == TK::SYMBOL && str == ";" then return false end
      perror "expected ';' after return statement"
      return true;
    end
    perror
    return true;
  end

return文の処理のところ。perrorにエラーメッセージを渡してる。他のところのperrorもおいおい修正してく必要あるなあ。とりあえずまあこんなところかな。次はもうちょっと複雑なプログラムのコンパイルに挑戦したいなあ。