コンパイラ作成(78) double型

今回の目標

IEEE754内部形式への変換は中途半端になってるけど、とりあえず先に進むことにしたよ。当面サポートするのはRubyで変換できるdouble型だけにするよ。

// double型

int main()
{
    double d = 10.78;
    double e = 0.13e-3;
    printf("d = %f\n", d);
    printf("e = %f\n", e);
}

今回は字句解析の変更を頑張る。

Lexerクラス

まずgettokenを修正。

      # floatの切り出し
      elsif m = @line[@idx,@line.length].match(/^\p{digit}+\.\p{digit}*[e|E][+|-]?\p{digit}+/) then
        str = m.to_s
        @idx += str.length
        return TK::FLOAT, str
      # floatの切り出し
      elsif m = @line[@idx,@line.length].match(/^\p{digit}+\.\p{digit}*/) then
        str = m.to_s
        @idx += str.length
        return TK::FLOAT, str

トークンの種類を増やしたんでここも修正。

# トークンの種類 enumの代わり
module TK
  EOF     = 1    # End of file
  ID      = 2    # Identifier
  NUMBER  = 3    # Number
  FLOAT   = 4    # Float
  SYMBOL  = 5    # Symbol
  STRING  = 6    # String
  RESERVE = 7    # Reserved word
  TYPE    = 8    # Type word
  UNKNOWN = 9    # Unkown token
end

おまけでここも。

  # モジュールテスト
  def moduletest()
    i = 0
    loop do
      i += 1
      kind, str = gettoken
#     fname, lineno, pos = position
#     print fname,":",lineno,":",pos," "
      if kind == TK::EOF then
        break
      elsif kind == TK::ID      then
        print "TK::ID      ",str,"\n"
      elsif kind == TK::NUMBER  then
        print "TK::NUMBER  ",str,"\n"
      elsif kind == TK::FLOAT   then
        print "TK::FLOAT   ",str,"\n"
      elsif kind == TK::STRING  then
        print "TK::STRING  ",str,"\n"
      elsif kind == TK::SYMBOL  then
        print "TK::SYMBOL  ",str,"\n"
      elsif kind == TK::RESERVE then
        print "TK::RESERVE ",str,"\n"
      elsif kind == TK::TYPE    then
        print "TK::TYPE    ",str,"\n"
      elsif kind == TK::UNKNOWN then
        print "TK::UNKNOWN ",str,"\n"
        break
      end
    end
  end
動作テスト
~/myc$ myc -l p7.myc
TK::TYPE    int
TK::ID      main
TK::SYMBOL  (
TK::SYMBOL  )
TK::SYMBOL  {
TK::ID      double
TK::ID      d
TK::SYMBOL  =
TK::FLOAT   10.78
TK::SYMBOL  ;
TK::ID      double
TK::ID      e
TK::SYMBOL  =
TK::FLOAT   0.13e-3
TK::SYMBOL  ;
TK::ID      printf
TK::SYMBOL  (
TK::STRING  d = %f\n
TK::SYMBOL  ,
TK::ID      d
TK::SYMBOL  )
TK::SYMBOL  ;
TK::ID      printf
TK::SYMBOL  (
TK::STRING  e = %f\n
TK::SYMBOL  ,
TK::ID      e
TK::SYMBOL  )
TK::SYMBOL  ;
TK::SYMBOL  }
~/myc$

上手くいったよ。次回はdouble型変数への代入と参照、printfでの表示まで行きたいなあ。一回で行けるかな。明日は土曜で時間あるから頑張るか。