From ed7f050a0f6d008b327098ad930c4873d3b3e461 Mon Sep 17 00:00:00 2001 From: Alexander Sulfrian Date: Wed, 13 Oct 2010 11:52:54 +0200 Subject: changed repository layout --- calc/calc.erl | 164 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 164 insertions(+) create mode 100644 calc/calc.erl (limited to 'calc/calc.erl') 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}}. -- cgit v1.2.3