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;
}

test