BrainF**k

某スレにネタがあったので、具象化してみる。

BrainF**kテンプレート。
以下仕様。


BidirectionalIterator1の型は以下の4つの実装が必要、

  1. operator *(単項演算子)
  2. operator ++,--(単項演算子)
  3. operator <<(*BidirectionalIterator1), operator >>(*BidirectionalIterator1)

BidirectionalIterator2の型は、

  1. char型の+ - > < . , [ ]との比較ができること。
  2. char型との引き算で0になるときは両者が等しいこと。

とかが必要っぽい。
なんか型の制限が気持悪いので、改造予定。
(生ポインタしか満たさない風味だし。)

#include <iosfwd>

template<
	typename BidirectionalIterator1,
	typename BidirectionalIterator2,
	typename CharType,
	typename CharTraits
>
//BidirectionalIterator
void
brainfuck(
	BidirectionalIterator1 mem_begin,
	BidirectionalIterator1 mem_end,
	BidirectionalIterator2 code_begin,
	BidirectionalIterator2 code_end,
	std::basic_istream<CharType,CharTraits>& in,
	std::basic_ostream<CharType,CharTraits>& out
)
{
	BidirectionalIterator1 p = mem_begin;
	BidirectionalIterator2 ip = code_begin;

	while(*ip && ip != code_end){
		switch(*ip){
		case '>' :	++p;		break;
		case '<' :	--p;		break;
		case '+' :	++*p;		break;
		case '-' :	--*p;		break;
		case '.' :	out<<*p;	break;
		case ',' :	in >>*p;	break;
		case '[' :
			if(!*p)
				for(int c=0; (*ip-']' || --c) && ip != code_end; ++ip)
					*ip == '[' && ++c;
			break;
		case ']' :
			if(*p)
				for(int c=0; (*ip-'[' || --c) && ip != code_begin; --ip)
					*ip == ']' && ++c;
			break;
		default	:	goto bad_command_error;
		}
		if(!(mem_begin<=p && p<mem_end)) goto bad_pointer_error;
		ip++;
	}
	return;

bad_command_error:
	out << "\n\n" "invalid code. [" << (*ip) << "]\n";
	dump(mem_begin, mem_end, out);
	return;

bad_pointer_error:
	out << "\n\n" "memory buffer overrun.\n";
	dump(mem_begin, mem_end, out);
	return;
}

template<
	typename BidirectionalIterator1,
	typename CharType,
	typename CharTraits
>
void dump(
	BidirectionalIterator1 mem_begin,
	BidirectionalIterator1 mem_end,
	std::basic_ostream<CharType,CharTraits>& out
)
{
	out << "memory dump\n";
	for(BidirectionalIterator1 i = mem_begin; i != mem_end; ++i)
		out << (int)(*i) << ' ';
}