aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--example/input.txt2
-rw-r--r--lib/elixir_math_parser.ex5
-rw-r--r--lib/math/calc.ex (renamed from lib/math/Calc.ex)0
-rw-r--r--lib/math/conversion.ex18
-rw-r--r--src/elixir_math_parser.yrl12
-rw-r--r--src/elixir_math_parser_lexer.xrl2
6 files changed, 34 insertions, 5 deletions
diff --git a/example/input.txt b/example/input.txt
index 1f4789b..909e250 100644
--- a/example/input.txt
+++ b/example/input.txt
@@ -1,4 +1,4 @@
-a = 7;; b = 4
+a = 10.5;; b = .5
(a + b) * 10 / 2
x = 2_0
diff --git a/lib/elixir_math_parser.ex b/lib/elixir_math_parser.ex
index 4a96daf..286829e 100644
--- a/lib/elixir_math_parser.ex
+++ b/lib/elixir_math_parser.ex
@@ -4,11 +4,16 @@ defmodule ElixirMathParser do
"""
alias ElixirMathParser.Math.Rational
alias ElixirMathParser.Math.Calc
+ alias ElixirMathParser.Math.Conversion
defp reduce_to_value({:int, _line, value}, _state) do
{:ok, Rational.new(value)}
end
+ defp reduce_to_value({:float, _line, value}, _state) do
+ {:ok, to_string(value) |> Conversion.literal_float_to_rational()}
+ end
+
defp reduce_to_value({:var, line, var}, state) do
if !Map.has_key?(state, var) do
{:error, line, "value not found for " <> to_string(var)}
diff --git a/lib/math/Calc.ex b/lib/math/calc.ex
index 7dc5fcc..7dc5fcc 100644
--- a/lib/math/Calc.ex
+++ b/lib/math/calc.ex
diff --git a/lib/math/conversion.ex b/lib/math/conversion.ex
new file mode 100644
index 0000000..65ddf8f
--- /dev/null
+++ b/lib/math/conversion.ex
@@ -0,0 +1,18 @@
+defmodule ElixirMathParser.Math.Conversion do
+ alias ElixirMathParser.Math.Rational
+
+ def literal_float_to_rational(value) do
+ {int, dec} = Integer.parse(value)
+
+ String.graphemes(dec)
+ |> Enum.reduce(Rational.new(int), fn v, acc ->
+ if v != "." do
+ num = Rational.numerator(acc) * 10
+ den = Rational.denominator(acc) * 10
+ Rational.new(num + String.to_integer(v), den)
+ else
+ acc
+ end
+ end)
+ end
+end
diff --git a/src/elixir_math_parser.yrl b/src/elixir_math_parser.yrl
index 4e8e9e9..635ebd3 100644
--- a/src/elixir_math_parser.yrl
+++ b/src/elixir_math_parser.yrl
@@ -7,7 +7,7 @@ Nonterminals
.
Terminals
- int
+ int float
var
break
'+' '-' '*' '/' '!' '^'
@@ -42,6 +42,7 @@ exprs -> expr : '$1'.
exprs -> expr exprs : {mul_op, '$1', '$2'}.
expr -> int : unwrap('$1').
+expr -> float : unwrap('$1').
expr -> var : '$1'.
expr -> exprs '+' exprs : {add_op, '$1', '$3'}.
expr -> exprs '-' exprs : {sub_op, '$1', '$3'}.
@@ -54,6 +55,9 @@ expr -> '-' exprs : {sub_op, {int, 0, 0}, '$2'}.
Erlang code.
-unwrap({int, Line, Value}) ->
- Match = fun(X) -> not(X == 95) end,
- {int, Line, list_to_integer(lists:filter(Match, Value))}.
+% 95 is the unicode of "_"
+numberMatch(X) -> not(X == 95).
+
+unwrap({int, Line, Value}) -> {int, Line, list_to_integer(lists:filter(fun numberMatch/1, Value))};
+% 48 is the unicode of "0"
+unwrap({float, Line, Value}) -> {float, Line, [48 | lists:filter(fun numberMatch/1, Value)]}.
diff --git a/src/elixir_math_parser_lexer.xrl b/src/elixir_math_parser_lexer.xrl
index c418c02..4073958 100644
--- a/src/elixir_math_parser_lexer.xrl
+++ b/src/elixir_math_parser_lexer.xrl
@@ -1,5 +1,6 @@
Definitions.
INT = [0-9_]+
+FLOAT = [0-9_]*\.[0-9]+
NAME = [a-zA-Z_][a-zA-Z0-9_]*
WHITESPACE = [\s\t\r]
COMMENT = #[^\n]*\n?
@@ -17,6 +18,7 @@ Rules.
\^ : {token, {'^', TokenLine}}.
{BREAK}+ : {token, {break, TokenLine}}.
{NAME} : {token, {var, TokenLine, TokenChars}}.
+{FLOAT} : {token, {float, TokenLine, TokenChars}}.
{INT} : {token, {int, TokenLine, TokenChars}}.
{WHITESPACE}+ : skip_token.
{COMMENT}+ : skip_token.