philomena/lib/philomena_query/parse/float_parser.ex

45 lines
1.1 KiB
Elixir
Raw Permalink Normal View History

defmodule PhilomenaQuery.Parse.FloatParser do
@moduledoc false
2019-11-02 19:34:25 +01:00
import NimbleParsec
defp to_number(input), do: PhilomenaQuery.Parse.Helpers.to_number(input)
defp range(input), do: PhilomenaQuery.Parse.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)
2023-09-27 20:16:59 +02:00
|> optional(ascii_char(~c".") |> ascii_string([?0..?9], min: 1))
2019-11-02 19:34:25 +01:00
|> reduce({List, :to_string, []})
|> reduce(:to_number)
float =
2023-09-27 20:16:59 +02:00
optional(ascii_char(~c"-+"))
2019-11-02 19:34:25 +01:00
|> ascii_string([?0..?9], min: 1)
2023-09-27 20:16:59 +02:00
|> optional(ascii_char(~c".") |> ascii_string([?0..?9], min: 1))
2019-11-02 19:34:25 +01:00
|> reduce({List, :to_string, []})
|> reduce(:to_number)
float_parser =
choice([
2020-01-11 05:20:19 +01:00
float
|> concat(fuzz)
|> concat(unsigned_float)
|> reduce(:range)
|> unwrap_and_tag(:float_range),
2019-11-02 19:34:25 +01:00
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
2020-01-11 05:20:19 +01:00
defparsec(:parse, float_parser)
end