diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/elixir_math_parser.ex | 22 | ||||
| -rw-r--r-- | lib/main.ex | 1 |
2 files changed, 20 insertions, 3 deletions
diff --git a/lib/elixir_math_parser.ex b/lib/elixir_math_parser.ex index f7f916f..863ecd8 100644 --- a/lib/elixir_math_parser.ex +++ b/lib/elixir_math_parser.ex @@ -10,9 +10,9 @@ defmodule ElixirMathParser do {:ok, value <~> 1} end - defp reduce_to_value({:var, _line, var}, state) do + defp reduce_to_value({:var, line, var}, state) do if !Map.has_key?(state, var) do - {:error, "value not found for " <> to_string(var)} + {:error, line, "value not found for " <> to_string(var)} else {:ok, state[var]} end @@ -46,9 +46,25 @@ defmodule ElixirMathParser do end end - defp evaluate_tree([{:assign, {:var, _line, lhs}, rhs} | tail], state) do + defp reduce_to_value({:factor_op, lhs}, state) do + with {:ok, op} <- reduce_to_value(lhs, state), + true <- Ratio.denominator(op) == 1, + true <- Ratio.numerator(op) >= 0 do + {:ok, factor(Ratio.numerator(op), 1)} + else + {:error, line, reason} -> {:error, line, reason} + false -> {:error, "must have a positive integer for the factorial"} + end + end + + defp factor(n, acc) when n > 0, do: factor(n - 1, acc * n) + defp factor(0, acc), do: acc + + defp evaluate_tree([{:assign, {:var, line, lhs}, rhs} | tail], state) do with {:ok, val} <- reduce_to_value(rhs, state) do evaluate_tree(tail, Map.merge(state, %{lhs => val})) + else + {:error, reason} -> {:error, line, reason} end end diff --git a/lib/main.ex b/lib/main.ex index 99c25ca..5e7cf55 100644 --- a/lib/main.ex +++ b/lib/main.ex @@ -11,6 +11,7 @@ defmodule ElixirMathParser.Main do case ElixirMathParser.process_tree(tree) do {:ok, _} -> :ok + {:error, line, reason} -> reason <> " (line " <> to_string(line) <> ")" {:error, reason} -> reason end end |
