defmodule SimpleParser do | |
def parse_digit(<<char, rest::bitstring>>) when char >= 48 and char <= 57, | |
do: {:ok, [char - 48], rest} | |
def parse_digit(<<char, _rest::bitstring>>), do: {:error, {:unexpected_input, <<char>>, 1}} | |
def parse_digit(""), do: {:error, :end_of_string} | |
def choice(fun, fun2) do | |
fn x -> | |
case {fun.(x), fun2.(x)} do | |
{{:ok, parsed, rest}, _} -> {:ok, parsed, rest} | |
{_, {:ok, parsed, rest}} -> {:ok, parsed, rest} | |
{err, _} -> err | |
end | |
end | |
end | |
def concat(fun, fun2) do | |
fn x -> | |
case fun.(x) do | |
{:ok, parsed, rest} -> | |
case fun2.(rest) do | |
{:ok, parsed2, rest2} -> | |
{:ok, parsed ++ parsed2, rest2} | |
{:error, {:unexpected_input, input, pos}} -> | |
{:error, {:unexpected_input, input, String.length(x) - String.length(rest) + pos}} | |
err -> | |
err | |
end | |
err -> | |
err | |
end | |
end | |
end | |
def digit_parser() do | |
fn x -> parse_digit(x) end | |
end | |
def two_digits() do | |
digit_parser() | |
|> concat(digit_parser()) | |
end | |
def three_digits() do | |
digit_parser() | |
|> concat(digit_parser()) | |
|> concat(digit_parser()) | |
end | |
def two_or_three_digits() do | |
choice(three_digits(), two_digits()) | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment