defmodule PhilomenaQuery.Parse.FloatParser do @moduledoc false import NimbleParsec defp to_number(input), do: PhilomenaQuery.Parse.Helpers.to_number(input) defp range(input), do: PhilomenaQuery.Parse.Helpers.range(input) space = choice([string(" "), string("\t"), string("\n"), string("\r"), string("\v"), string("\f")]) |> ignore() fuzz = string("~") |> ignore() unsigned_float = ascii_string([?0..?9], min: 1) |> optional(ascii_char(~c".") |> ascii_string([?0..?9], min: 1)) |> reduce({List, :to_string, []}) |> reduce(:to_number) float = optional(ascii_char(~c"-+")) |> ascii_string([?0..?9], min: 1) |> optional(ascii_char(~c".") |> 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) ]) |> repeat(space) |> eos() |> label("a real number, like `2.7182818' or `-10'") defparsec(:parse, float_parser) end