コンパイラ作成(26) Lexerクラス修正

moduletest

色々テストしてたらLexerにバグを見っけた。一件目はmoduletest。

  # モジュールテスト
  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::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::UNKNOWN then
        print "TK::UNKNOWN ",str,"\n"
        break
      end
    end
  end

予約語を組み込んだときに修正するの忘れてたよ。これは大したことないバグ。

gettoken

二件目はgettokenのSymbolの処理。

      # symbolの切り出し
      elsif m = @line[@idx,@line.length].match(/^[==|=|\+|\-|\*|\/|:|;|\(|\)|\{|\}]/)  then
        str = m.to_s
        @idx += str.length
        return TK::SYMBOL, str
      end

サポートしてない演算子とかがあったときTK::UNKNOWNを返す仕様なんだけど、間違って変なトークンを返す場合があったよ。等価演算子をサポートしたときにバグが紛れ込んでた。一件目と違って、場合によってはコンパイル結果がおかしくなる困ったちゃんのバグだよ。分かりづらいけど変更箇所はmatchのパターンね。

動作テスト

二件続けてテストいくよ。

~/myc$ myc -l c.myc
TK::ID      main
TK::SYMBOL  (
TK::SYMBOL  )
TK::SYMBOL  {
TK::RESERVE print
TK::SYMBOL  (
TK::NUMBER  42
TK::SYMBOL  )
TK::SYMBOL  ;
TK::SYMBOL  }
~/myc$ myc -l err9.myc
TK::RESERVE int
TK::ID      main
TK::SYMBOL  (
TK::SYMBOL  )
TK::SYMBOL  {
TK::NUMBER  10
TK::UNKNOWN #
~/myc$

大丈夫そうだね。やっぱりテストはちゃんとやらないと駄目だね。

よーく考えよう テストは大事だよ ルールル ルールル ルルルー♪