Created
March 19, 2020 16:34
-
-
Save wstucco/a118a97ee2cc7bd03779d9002f00dfa5 to your computer and use it in GitHub Desktop.
NimbleParser excercise: parse numbers in "it_IT" locale format
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule NumberParser do | |
import NimbleParsec | |
@moduledoc """ | |
In most European countries decimal separator is the , (comma) | |
This is a simple parser for numbers formatted that way | |
""" | |
nat = integer(min: 1) | |
sep = string(",") | |
defcombinatorp( | |
:number, | |
choice([ | |
nat | |
|> concat(sep) | |
|> concat(nat) | |
|> post_traverse(:to_number), | |
nat | |
]) | |
|> eos() | |
) | |
@doc """ | |
Parse numbers in Italian format | |
Returns | |
{:ok, number} in case of success or | |
{:error, reason, rest} if the parser can't make sense of it | |
## Examples | |
iex> NumberParser.parse("89") | |
{:ok, 89} | |
iex> NumberParser.parse("89,91") | |
{:ok, 89.91} | |
iex> NumberParser.parse("89.91") | |
{:error, "expected end of string", ".91"} | |
""" | |
def parse(term) when is_binary(term) do | |
case parse_number(term) do | |
{:error, reason, rest, _, _, _} -> {:error, reason, rest} | |
{:ok, [val], _, _, _, _} -> {:ok, val} | |
end | |
end | |
defparsecp(:parse_number, parsec(:number)) | |
defp to_number(_rest, [right, ",", left], context, _line, _offset) do | |
{[String.to_float("#{left}.#{right}")], context} | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment