コンパイラ作成(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$
大丈夫そうだね。やっぱりテストはちゃんとやらないと駄目だね。
よーく考えよう テストは大事だよ ルールル ルールル ルルルー♪