aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/elixir_math_parser.ex22
-rw-r--r--lib/main.ex1
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