2008-07-03 [長年日記]
λ. A brainf*ck interpreter in Erlang
HelloWorld を書いたので、次は brainf*ck のインタプリタでも。
-module(brainfuck).
-export([brainfuck/1]).
brainfuck(Src) ->
Prog=parse(Src), seq(Prog, {[], [0]}).
parse(X) -> {Y,_} = parse(X, []), Y.
parse([], Acc) -> {lists:reverse(Acc), []};
parse([H|T], Acc) ->
case H of
$] -> {lists:reverse(Acc), T};
$> -> parse(T, ['>'|Acc]);
$< -> parse(T, ['<'|Acc]);
$+ -> parse(T, ['+'|Acc]);
$- -> parse(T, ['-'|Acc]);
$. -> parse(T, ['.'|Acc]);
$, -> parse(T, [','|Acc]);
$[ -> {Prog,X}=parse(T, []), parse(X,[{Prog}|Acc]);
_ -> parse(T, Acc)
end.
seq(Prog, T) ->
lists:foldl(fun (P,T1) -> step(P,T1) end, T, Prog).
step('>', {L,[X|R]}) ->
{[X|L], case R of [_|_] -> R; _ -> [0] end};
step('<', {[X|L],R}) -> {L, [X|R]};
step('+', {L,[X|R]}) ->
{L, [ case X of 255 -> 0; _ -> X+1 end | R ]};
step('-', {L,[X|R]}) ->
{L, [ case X of 0 -> 255; _ -> X-1 end | R ]};
step('.', {L,[X|R]}) ->
io:put_chars([X]), {L, [X|R]};
step(',', {L,[_|R]}) ->
[X] = io:get_chars("", 1), {L, [X|R]};
step({W}, T) -> while(W, T).
while(_, {_,[0|_]}=T1) -> T1;
while(W, T) -> while(W, seq(W, T)).
といっても、前にPrologで書いたもの を適当に翻訳しただけ。
Erlang shell から実行してみる。
% erl
Eshell V5.6.3 (abort with ^G)
1> c(brainfuck).
{ok,brainfuck}
2> brainfuck:brainfuck("
>+++++++++[<++++++++>-]<.>+++++++[<++++>-]<+.+++++++..+++.[-]>++++++++[<++
++>-]<.>+++++++++++[<+++++>-]<.>++++++++[<+++>-]<.+++.------.--------.[-]>
++++++++[<++++>-]<+.[-]++++++++++.").
Hello World!
{[],[10,0]}
[ツッコミを入れる]
