2019-11-02 19:34:25 +01:00
|
|
|
defmodule Search.FloatParser do
|
|
|
|
import NimbleParsec
|
2019-12-30 22:14:57 +01:00
|
|
|
|
|
|
|
defp to_number(input), do: Search.Helpers.to_number(input)
|
|
|
|
defp range(input), do: Search.Helpers.range(input)
|
2019-11-02 19:34:25 +01:00
|
|
|
|
2019-11-15 19:27:10 +01:00
|
|
|
space =
|
|
|
|
choice([string(" "), string("\t"), string("\n"), string("\r"), string("\v"), string("\f")])
|
|
|
|
|> ignore()
|
|
|
|
|
2019-11-02 19:34:25 +01:00
|
|
|
fuzz =
|
|
|
|
string("~")
|
|
|
|
|> ignore()
|
|
|
|
|
|
|
|
unsigned_float =
|
|
|
|
ascii_string([?0..?9], min: 1)
|
|
|
|
|> optional(ascii_char('.') |> ascii_string([?0..?9], min: 1))
|
|
|
|
|> reduce({List, :to_string, []})
|
|
|
|
|> reduce(:to_number)
|
|
|
|
|
|
|
|
float =
|
|
|
|
optional(ascii_char('-+'))
|
|
|
|
|> ascii_string([?0..?9], min: 1)
|
|
|
|
|> optional(ascii_char('.') |> ascii_string([?0..?9], min: 1))
|
|
|
|
|> reduce({List, :to_string, []})
|
|
|
|
|> reduce(:to_number)
|
|
|
|
|
|
|
|
float_parser =
|
|
|
|
choice([
|
|
|
|
float |> concat(fuzz) |> concat(unsigned_float) |> reduce(:range) |> unwrap_and_tag(:float_range),
|
|
|
|
float |> unwrap_and_tag(:float)
|
|
|
|
])
|
2019-11-15 19:27:10 +01:00
|
|
|
|> repeat(space)
|
2019-11-02 19:34:25 +01:00
|
|
|
|> eos()
|
2019-11-02 21:31:55 +01:00
|
|
|
|> label("a real number, like `2.7182818' or `-10'")
|
2019-11-02 19:34:25 +01:00
|
|
|
|
|
|
|
defparsec :parse, float_parser
|
2019-12-30 22:14:57 +01:00
|
|
|
end
|