diff options
| -rw-r--r-- | example/input.txt | 2 | ||||
| -rw-r--r-- | lib/elixir_math_parser.ex | 5 | ||||
| -rw-r--r-- | lib/math/calc.ex (renamed from lib/math/Calc.ex) | 0 | ||||
| -rw-r--r-- | lib/math/conversion.ex | 18 | ||||
| -rw-r--r-- | src/elixir_math_parser.yrl | 12 | ||||
| -rw-r--r-- | src/elixir_math_parser_lexer.xrl | 2 |
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. |
