Skip to content

Instantly share code, notes, and snippets.

@NaeosPsy
Last active April 6, 2021 03:20
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 NaeosPsy/254f80bd730d139cfdf92c08cbd03060 to your computer and use it in GitHub Desktop.
Save NaeosPsy/254f80bd730d139cfdf92c08cbd03060 to your computer and use it in GitHub Desktop.
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