Dで書いてなかったかなと
情報工学実験がガイダンスだけで空きコマできたのと、あーまた学期始まったなあと少し気分が昂ぶったのでBFインタプリタでも書いて落ち着くことにする。
一番時間がかかったのは、switchブロックのなかで一つbreakを書き忘れてたところがあったこと。そんなひとはもうswitch使っちゃいけないんじゃないだろうか。
import std.stdio; import std.string; abstract class Exp{ abstract void eval(); } class BasicExp : Exp{ private: void delegate() exp; public: this(void delegate() e) { exp = e; } void eval() { exp(); } } class BlockExp : Exp{ private: Exp[] block; public: void addExp(Exp exp) { block ~= exp; } void eval() { foreach(Exp exp; block){ exp.eval(); } } } class WhileExp : Exp{ private: Exp exp; public: this(Exp e) { exp = e; } void eval() { while(mem[pt]!=0){ exp.eval(); } } } Exp readBlock(FILE* input) { BlockExp block = new BlockExp; while(true){ int c = fgetc(input); switch(c){ case '+': block.addExp(incExp); break; case '-': block.addExp(decExp); break; case '>': block.addExp(nextExp); break; case '<': block.addExp(prevExp); break; case ',': block.addExp(getExp); break; case '.': block.addExp(putExp); break; case '[': block.addExp(new WhileExp(readBlock(input))); break; case ']': case EOF: return block; default: break; } } throw new Exception("Parse Error: readBlock"); } byte mem[30000]; int pt = 0; Exp incExp, decExp, nextExp, prevExp, getExp, putExp; int main(char[][] args) { incExp = new BasicExp({++mem[pt];}); decExp = new BasicExp({--mem[pt];}); nextExp = new BasicExp({++pt;}); prevExp = new BasicExp({--pt;}); getExp = new BasicExp({mem[pt] = cast(byte)getchar();}); putExp = new BasicExp({putchar(mem[pt]);}); if(args.length!=2){ writefln("%s input", args[0]); return 1; } FILE* input = fopen(toStringz(args[1]), toStringz("r")); if(input is null){ writefln("cannot open %s", args[1]); return 1; } try{ Exp mainBlock = readBlock(input); mainBlock.eval(); } catch(Exception e){ fwritefln(stderr, e); } return 0; }