aboutsummaryrefslogtreecommitdiffstats
path: root/calc
diff options
context:
space:
mode:
authorAlexander Sulfrian <alexander@sulfrian.net>2010-10-13 11:52:54 +0200
committerAlexander Sulfrian <alexander@sulfrian.net>2010-10-13 11:52:54 +0200
commited7f050a0f6d008b327098ad930c4873d3b3e461 (patch)
tree2fce818b0d6aa0716fce251788b373e1b74f9eb8 /calc
parent69c37e13acd820ef48f949afc795bf01d3690ae1 (diff)
downloaderlang-ed7f050a0f6d008b327098ad930c4873d3b3e461.tar.gz
erlang-ed7f050a0f6d008b327098ad930c4873d3b3e461.tar.xz
erlang-ed7f050a0f6d008b327098ad930c4873d3b3e461.zip
changed repository layout
Diffstat (limited to 'calc')
-rw-r--r--calc/calc.erl164
-rw-r--r--calc/remote.erl22
2 files changed, 186 insertions, 0 deletions
diff --git a/calc/calc.erl b/calc/calc.erl
new file mode 100644
index 0000000..4869104
--- /dev/null
+++ b/calc/calc.erl
@@ -0,0 +1,164 @@
+-module(calc).
+-export([eval/1]).
+
+%% num := [-] 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
+num(Input) ->
+ num(Input, []).
+
+num([Current|Input], Num) when ($0 =< Current) and ($9 >= Current) ->
+ num(Input, Num ++ [Current]);
+num([Head|_], "-") ->
+ {error, {unexpected, list_to_atom([Head])}};
+num(Input, []) ->
+ {ok, {Input, []}};
+num(Input, Num) ->
+ {ok, {Input, list_to_integer(Num)}}.
+
+%% bracket := [-] ( '(' sum '}' | num )
+bracket([$-|Input]) ->
+ case bracket(Input) of
+ {ok, {Tail, []}} ->
+ {error, {expected_number, {before, Tail}}};
+ {ok, {Tail, Result}} ->
+ {ok, {Tail, -1 * Result}};
+ {error, Why} ->
+ {error, Why}
+ end;
+bracket([$(|Input]) ->
+ case sum(Input) of
+ {ok, {Tail, Result}} ->
+ bracketCheck(Tail, Result);
+ {error, Why} ->
+ {error, Why}
+ end;
+bracket(Input) ->
+ num(Input).
+
+bracketCheck([$)|Tail], Result) ->
+ {ok, {Tail, Result}};
+bracketCheck(_, _) ->
+ {error, missing_bracket}.
+
+%% factor := num [ ^ factor ]
+factor(Input) ->
+ case bracket(Input) of
+ {ok, {Tail, Number2}} ->
+ factorExtended(Tail, Number2);
+ {error, Why} ->
+ {error, Why}
+ end.
+
+factor([Head|Input], Number1) ->
+ case bracket([Head|Input]) of
+ {ok, {Tail, Number2}} ->
+ Result = math:pow(Number1, Number2),
+ factorExtended(Tail, Result);
+ {error, Why} ->
+ {error, Why}
+ end;
+factor([], _) ->
+ {error, unexpected_end_of_input}.
+
+factorExtended([$ |Tail], Result) ->
+ factorExtended(Tail, Result);
+factorExtended([$^|Tail], Result) ->
+ factor(Tail, Result);
+factorExtended(Tail, Result) ->
+ {ok, {Tail, Result}}.
+
+%% term := factor [ ( * | / ) term ]
+term(Input) ->
+ case factor(Input) of
+ {ok, {Tail, Result}} ->
+ termExtended(Tail, Result);
+ {error, Why} ->
+ {error, Why}
+ end.
+
+term([Head|Input], Number1, Operator) ->
+ case factor([Head|Input]) of
+ {ok, {Tail, Number2}} ->
+ case calc(Number1, Operator, Number2) of
+ {ok, Result} ->
+ termExtended(Tail, Result);
+ {error, Why} ->
+ {error, Why}
+ end;
+
+ {error, Why} ->
+ {error, Why}
+ end;
+term([], _, _) ->
+ {error, unexpected_end_of_input}.
+
+termExtended([$ |Tail], Result) ->
+ termExtended(Tail, Result);
+termExtended([$*|Tail], Result) ->
+ term(Tail, Result, $*);
+termExtended([$/|Tail], Result) ->
+ term(Tail, Result, $/);
+termExtended(Tail, Result) ->
+ {ok, {Tail, Result}}.
+
+%% sum := term [ ( + | - ) sum ]
+sum([$+|Input]) ->
+ sum(Input);
+sum(Input) ->
+ case term(Input) of
+ {ok, {Tail, Result}} ->
+ sumExtended(Tail, Result);
+ {error, Why} ->
+ {error, Why}
+ end.
+
+sum([Head|Input], Number1, Operator) ->
+ case term([Head|Input]) of
+ {ok, {Tail, Number2}} ->
+ case calc(Number1, Operator, Number2) of
+ {ok, Result} ->
+ sumExtended(Tail, Result);
+ {error, Why} ->
+ {error, Why}
+ end;
+
+ {error, Why} ->
+ {error, Why}
+ end;
+sum([], _, _) ->
+ {error, unexpected_end_of_input}.
+
+sumExtended([$ |Tail], Result) ->
+ sumExtended(Tail, Result);
+sumExtended([$+|Tail], Result) ->
+ sum(Tail, Result, $+);
+sumExtended([$-|Tail], Result) ->
+ sum(Tail, Result, $-);
+sumExtended(Tail, Result) ->
+ {ok, {Tail, Result}}.
+
+%% helper function to do the calculations
+calc(Number1, $+, Number2) ->
+ {ok, Number1 + Number2};
+calc(Number1, $-, Number2) ->
+ {ok, Number1 - Number2};
+calc(Number1, $*, Number2) ->
+ {ok, Number1 * Number2};
+calc(Number1, $/, Number2) when (Number2 /= 0) ->
+ {ok, Number1 / Number2};
+calc(_, $/, _) ->
+ {error, division_zero};
+calc(_,_,_) ->
+ {error, invalid_operator}.
+
+eval(Formular) ->
+ case sum([X || X <- Formular, X /= $ ]) of
+ {ok, {Tail, Result}} ->
+ evalCheck(Tail, Result);
+ {error, Why} ->
+ {error, Why}
+ end.
+
+evalCheck([], Result) ->
+ {ok, Result};
+evalCheck(Tail, _) ->
+ {error, {unexpected_garbage_at_end_of_input, Tail}}.
diff --git a/calc/remote.erl b/calc/remote.erl
new file mode 100644
index 0000000..793c27c
--- /dev/null
+++ b/calc/remote.erl
@@ -0,0 +1,22 @@
+-module(remote).
+-export([start/0, calculate/1]).
+
+rpc(C) ->
+ rechner ! {self(), C},
+ receive
+ {rechner, Reply} ->
+ Reply
+ end.
+
+loop() ->
+ receive
+ {From, {calculate, String}} ->
+ From ! {rechner, calc:eval(String)},
+ loop()
+ end.
+
+start() ->
+ register(rechner, spawn(fun() -> loop() end)).
+
+calculate(String) ->
+ rpc({calculate, String}).