diff options
Diffstat (limited to 'calc.erl')
-rw-r--r-- | calc.erl | 195 |
1 files changed, 150 insertions, 45 deletions
@@ -1,55 +1,160 @@ -module(calc). --export([factor/1]). +-export([eval/1]). -factor(Input) -> - {Tail, Number2} = parseNumber(Input, []), - {_, Result} = factorExtended(Tail, Number2), - Result. +%% num := [-] 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 +num(Input) -> + num(Input, []). -factor(Input, Number1) when is_integer(Number1) or is_float(Number1) -> - {Tail, Number2} = parseNumber(Input, []), - Result = math:pow(Number1, Number2), - factorExtended(Tail, Result); +num([Current|Input], Num) when ($0 =< Current) and ($9 >= Current) -> + num(Input, Num ++ [Current]); +num([Head|_], "-") -> + {error, {unexpected, list_to_atom([Head])}}; +num(Input, Num) -> + {ok, {Input, list_to_integer(Num)}}. + +%% bracket := [-] ( '(' sum '}' | num ) +bracket([$-|Input]) -> + case bracket(Input) of + {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). -factor([], Number) -> - {[], Number}. +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) -> - {Tail, Result}. - - -parseNumber([$ |Input], []) -> - %% skip spaces at start - parseNumber(Input, []); -parseNumber([$-|Input], []) -> - parseNumber(Input, "-"); -parseNumber([Current|Input], Number) when ($0 =< Current) and ($9 >= Current) -> - parseNumber(Input, Number ++ [Current]); -parseNumber(Input, Number) -> - {Input, list_to_integer(Number)}. - -%% eval(Formular) -> -%% term(Formular,[]). - -%% term([" "|Input], Parsed) -> -%% term(Input, Parsed); -%% term([Current|Formular], Parsed) -> -%% {ParsedFirst, Number1} = parseNumber([Current|Formular], []). - -%% parseOperator([$ |Input]) -> -%% parseOperator(Input); -%% parseOperator([Operator|Input]) -> -%% {ok, list_to_atom(Operator)}; -%% parseOperator([]) -> -%% {error, unexpected_end_of_input}. - -%% sum(Number1, Number2, '+') -> -%% {ok, Number1 + Number2}; -%% sum(Number1, Number2, '-') -> -%% {ok, Number1 - Number2}; -%% sum(_, _, _) -> -%% {error, invalid_operator}. + {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}}. |