Erlang Super Liteの宿題が「Erlang Programming」Chapter 3 Ex3.8ですが、ようやくひととおりの機能がまとまりました。
というわけで、以下、3.8の実装案です。
-module(exercise).
-compile(export_all).
%---------------------------------------
evaluator(Exps) ->
evaluator_acc(Exps).
evaluator_acc({plus, Param1, Param2}) ->
evaluator_acc(Param1) + evaluator_acc(Param2);
evaluator_acc({minus, Param1, Param2}) ->
evaluator_acc(Param1) - evaluator_acc(Param2);
evaluator_acc({multi, Param1, Param2}) ->
evaluator_acc(Param1) * evaluator_acc(Param2);
evaluator_acc({divide, Param1, Param2}) ->
evaluator_acc(Param1) / evaluator_acc(Param2);
evaluator_acc({num, Param1}) ->
Param1.
%---------------------------------------
simplifier({Op, Param1, Param2}) ->
EP1 = evaluator(Param1),
EP2 = evaluator(Param2),
case evaluator({Op, Param1, Param2}) of
EP1 -> Param1;
EP2 -> Param2;
1 -> {num, 1};
0 -> {num, 0};
_-> {Op, simplifier(Param1), simplifier(Param2)}
end;
simplifier({num, Param1}) ->
{num, Param1}.
%---------------------------------------
remove_top_brace(ExpChars) ->
[H|T] = ExpChars,
case H of
40 ->
[HH|TT] = lists:reverse(T),
case HH of
41 -> lists:reverse(TT);
_ ->ExpChars
end;
_-> ExpChars
end.
pp(Exps) ->
remove_top_brace(lists:flatten(pp_acc(Exps))).
pp_acc({plus, Param1, Param2}) ->
[ "(" , pp_acc(Param1), "+" , pp_acc(Param2), ")"];
pp_acc({minus, Param1, Param2}) ->
[ "(" , pp_acc(Param1), "-" , pp_acc(Param2), ")"];
pp_acc({multi, Param1, Param2}) ->
[ "(" , pp_acc(Param1), "*" , pp_acc(Param2), ")"];
pp_acc({divide, Param1, Param2}) ->
[ "(" , pp_acc(Param1), "/" , pp_acc(Param2), ")"];
pp_acc({num, Param1}) ->
io_lib:format("~p", [Param1]).
%---------------------------------------
compile({simplify, Exps}) ->
lists:flatten(compile_acc(simplifier(Exps), []));
compile(Exps) ->
lists:flatten(compile_acc(Exps, [])).
compile_acc({Op, Param1,Param2}, Stack) ->
[ compile_acc(Param2, Stack), compile_acc(Param1, Stack), {op, Op} | Stack];
compile_acc({num, Param1}, Stack) ->
[{num, Param1} | Stack].
%---------------------------------------
run(OpStack) ->
[Result | T] = run_acc(OpStack, []),
Result.
run_acc([], DataStack) ->
DataStack;
run_acc([H | T], DataStack) ->
NewDataStack = operate(H, DataStack),
run_acc(T, NewDataStack).
operate({num, Param}, DataStack) ->
[Param | DataStack];
operate({op, plus}, DataStack) ->
[Param1, Param2 | T] = DataStack,
[ Param1 + Param2 | T];
operate({op, minus}, DataStack) ->
[Param1, Param2 | T] = DataStack,
[ Param1 - Param2 | T];
operate({op, multi}, DataStack) ->
[Param1, Param2 | T] = DataStack,
[ Param1 * Param2 | T];
operate({op, divide}, DataStack) ->
[Param1, Param2 | T] = DataStack,
[ Param1 / Param2 | T].
2010年01月07日
この記事へのコメント
コメントを書く
この記事へのトラックバックURL
http://blog.sakura.ne.jp/tb/34599314
この記事へのトラックバック
http://blog.sakura.ne.jp/tb/34599314
この記事へのトラックバック