コンパイラ作成(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での表示まで行きたいなあ。一回で行けるかな。明日は土曜で時間あるから頑張るか。