aboutsummaryrefslogtreecommitdiffstats
path: root/calc.erl
diff options
context:
space:
mode:
authorAlexander Sulfrian <alexander@sulfrian.net>2010-10-12 07:35:40 +0200
committerAlexander Sulfrian <alexander@sulfrian.net>2010-10-12 07:35:40 +0200
commit04a0775f1aa9bc33b3bfff88e60ea8cc2a6917f3 (patch)
tree675769df63353194a29014f265f360c459161543 /calc.erl
parentd61edeb7473237c97df58409d32b710c0fabcf82 (diff)
downloaderlang-04a0775f1aa9bc33b3bfff88e60ea8cc2a6917f3.tar.gz
erlang-04a0775f1aa9bc33b3bfff88e60ea8cc2a6917f3.tar.xz
erlang-04a0775f1aa9bc33b3bfff88e60ea8cc2a6917f3.zip
added final equation parser
Diffstat (limited to '')
-rw-r--r--calc.erl195
1 files changed, 150 insertions, 45 deletions
diff --git a/calc.erl b/calc.erl
index 7b7c56f..b7981a1 100644
--- a/calc.erl
+++ b/calc.erl
@@ -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}}.