Skip to content

Instantly share code, notes, and snippets.

@wstucco
Created March 19, 2020 16:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wstucco/a118a97ee2cc7bd03779d9002f00dfa5 to your computer and use it in GitHub Desktop.
Save wstucco/a118a97ee2cc7bd03779d9002f00dfa5 to your computer and use it in GitHub Desktop.
NimbleParser excercise: parse numbers in "it_IT" locale format
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