1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
|
defmodule ElixirMathParser do
@moduledoc """
Documentation for `ElixirMathParser`.
"""
defp reduce_to_value({:int, _line, value}, _state) do
{:ok, value}
end
defp reduce_to_value({:atom, _line, atom}, state) do
if !Map.has_key?(state, atom) do
{:error, "value not found for " <> to_string(atom)}
else
{:ok, state[atom]}
end
end
defp reduce_to_value({:add_op, lhs, rhs}, state) do
with {:ok, op1} <- reduce_to_value(lhs, state),
{:ok, op2} <- reduce_to_value(rhs, state) do
{:ok, op1 + op2}
end
end
defp reduce_to_value({:sub_op, lhs, rhs}, state) do
with {:ok, op1} <- reduce_to_value(lhs, state),
{:ok, op2} <- reduce_to_value(rhs, state) do
{:ok, op1 - op2}
end
end
defp reduce_to_value({:mul_op, lhs, rhs}, state) do
with {:ok, op1} <- reduce_to_value(lhs, state),
{:ok, op2} <- reduce_to_value(rhs, state) do
{:ok, op1 * op2}
end
end
defp reduce_to_value({:div_op, lhs, rhs}, state) do
with {:ok, op1} <- reduce_to_value(lhs, state),
{:ok, op2} <- reduce_to_value(rhs, state) do
{:ok, op1 / op2}
end
end
defp evaluate_tree([{:assign, {:atom, _line, lhs}, rhs} | tail], state) do
with {:ok, val} <- reduce_to_value(rhs, state) do
evaluate_tree(tail, Map.merge(state, %{lhs => val}))
end
end
defp evaluate_tree([{:eval, expr} | tail], state) do
with {:ok, expr} <- reduce_to_value(expr, state) do
IO.puts(expr)
evaluate_tree(tail, state)
end
end
defp evaluate_tree([], state) do
{:ok, state}
end
def process_tree(tree) do
evaluate_tree(tree, %{})
end
def parse_file(filename) do
text = File.read!(filename)
{:ok, tokens, _line} = :elixir_math_parser_lexer.string(String.to_charlist(text))
{:ok, tree} = :elixir_math_parser.parse(tokens)
process_tree(tree)
end
end
|