お脳の病気れす

戯れにBrainf*ckインタプリタ書いてみた。適当に書いたのになんかC++標準ライブラリの見本市みたいなコードになった。認識できないデータは無視する。あとsrcはstringである意味がないので、vector<char>でもよかったような気がしないでもないvector<char>にしといた。あとなんか違和感あるなーと思ったら名前のつけ方が自分好みじゃなかったからそこも直しといた。それにしても作ったものに対して使ったものが贅沢なこと。

使い方:コマンドラインからBrainf*ckソースファイル名を渡す。


#include <iostream>
#include <fstream>
#include <map>
#include <vector>
#include <algorithm>
#include <iterator>

template<char start, char end>
struct findBracketPred {
    unsigned long count_;
    bool operator()(char ch) {
        if (ch == end) {
            if (!count_) {
                return true;
            }
            --count_;
            return false;
        } else if (ch == start) {
            ++count_;
        }
        return false;
    }
    findBracketPred() : count_() {}
};

int main(int argc, char* argv[]) {
    using std::cout;
    using std::cin;
    using std::endl;
    typedef std::vector<char> SourceCode;

    if (argc < 2) {
        cout << "usage : bfi sourcefile" << endl;
        return 0;
    }

    std::ifstream srcFile(argv[1]);
    if (!srcFile) {
        cout << argv[1] << "is not found" << endl;
        return 0;
    }

    SourceCode const src)((std::istream_iterator<char>(srcFile))(, (std::istream_iterator<char>()));
    std::map<unsigned long, char> mem;
    unsigned long ptr = 0;
    SourceCode::const_iterator const end = src.end();
    SourceCode::const_iterator const begin = src.begin();
    SourceCode::const_reverse_iterator const rend = src.rend();

    for (SourceCode::const_iterator iter = begin; iter != end; ++iter) {
        switch (*iter) {
        case '>':
            ++ptr;
            continue;
        case '<':
            --ptr;
            continue;
        case '+':
            ++mem[ptr];
            continue;
        case '-':
            --mem[ptr];
            continue;
        case '.':
            cout << mem[ptr];
            continue;
        case ',':
            cin >> mem[ptr];
            continue;
        case '[':
            if (mem[ptr]) {
                continue;
            }
            iter = std::find_if(iter, end, findBracketPred<'[', ']'>());
            if (iter == end) {
                return 0;
            }
            continue;
        case ']':
            if (!mem[ptr]) {
                continue;
            }
            {
                SourceCode::const_reverse_iterator const openBracket =
                    std::find_if(SourceCode::const_reverse_iterator(iter), rend, findBracketPred<']', '['>());
                if (openBracket == rend) {
                    return 0;
                }
                iter = begin + (rend - openBracket - 1);
            }
            continue;
        default:
            continue;
        }
    }
    return 0;
}