Intcode assembler: start expression evaluation
This commit is contained in:
parent
fe5bc1de7c
commit
458210f513
|
@ -0,0 +1,93 @@
|
|||
defmodule ExpressionEvaluator do
|
||||
def eval(expr, vars) do
|
||||
expr
|
||||
|> String.to_charlist()
|
||||
|> tokenize()
|
||||
|> run(vars)
|
||||
|
||||
# |> parse()
|
||||
|
||||
# |> run(vars)
|
||||
end
|
||||
|
||||
@digits ?0..?9
|
||||
@alpha ?a..?z
|
||||
@operators [?+, ?-, ?*]
|
||||
|
||||
def do_tokenize([first | _] = str) when first in @digits do
|
||||
{digits, rest} = Enum.split_while(str, &(&1 in @digits))
|
||||
num = digits |> to_string() |> String.to_integer()
|
||||
{{:number, num}, rest}
|
||||
end
|
||||
|
||||
def do_tokenize([?( | rest]) do
|
||||
{:lparen, rest}
|
||||
end
|
||||
|
||||
def do_tokenize([?) | rest]) do
|
||||
{:rparen, rest}
|
||||
end
|
||||
|
||||
def do_tokenize([op | rest]) when op in @operators do
|
||||
atom = [op] |> to_string() |> String.to_atom()
|
||||
{{:operator, atom}, rest}
|
||||
end
|
||||
|
||||
def do_tokenize([first | _] = str) when first in @alpha do
|
||||
{var, rest} = Enum.split_while(str, &(&1 in @alpha))
|
||||
{{:variable, var}, rest}
|
||||
end
|
||||
|
||||
def tokenize([]), do: []
|
||||
|
||||
def tokenize(str) do
|
||||
{token, rest} =
|
||||
str
|
||||
|> Enum.drop_while(&(&1 == ?\s))
|
||||
|> do_tokenize()
|
||||
|
||||
[token | tokenize(rest)]
|
||||
end
|
||||
|
||||
# def to_rpn([{:number, _} = num | rest]) do
|
||||
# [num | to_rpn(rest)]
|
||||
# end
|
||||
#
|
||||
# def to_rpn([{:operator, _} = op | rest]) do
|
||||
# [op | to_rpn(rest)]
|
||||
# end
|
||||
#
|
||||
# def to_rpn
|
||||
|
||||
# def parse(tokens) do
|
||||
# {expr, rest} = do_parse(tokens)
|
||||
# [expr |
|
||||
# end
|
||||
|
||||
def run([:lparen | _] = tokens, vars) do
|
||||
paren_tokens =
|
||||
tokens
|
||||
|> Enum.drop(1)
|
||||
|> Enum.reduce_while({1, []}, fn token, {count, paren_tokens} ->
|
||||
count =
|
||||
case token do
|
||||
:lparen -> count + 1
|
||||
:rparen -> count - 1
|
||||
_ -> count
|
||||
end
|
||||
|
||||
if count == 0 do
|
||||
{:halt, Enum.reverse(paren_tokens)}
|
||||
else
|
||||
{:cont, {count, [token | paren_tokens]}}
|
||||
end
|
||||
end)
|
||||
|
||||
# paren_expr = run(paren_tokens)
|
||||
rest_tokens = Enum.drop(tokens, length(paren_tokens))
|
||||
|
||||
paren_res = run(paren_tokens, vars)
|
||||
|
||||
run([{:number, paren_res} | rest_tokens])
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue