Skip to content

Instantly share code, notes, and snippets.

@coproduto
Created April 21, 2021 23:00
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save coproduto/44785b8384e9508cdab3378931c89958 to your computer and use it in GitHub Desktop.
Save coproduto/44785b8384e9508cdab3378931c89958 to your computer and use it in GitHub Desktop.
defmodule Parser do
def numero() do
fn
<<c::utf8>> <> rest ->
case c do
c when c in ?0..?9 -> {:ok, c - ?0, rest}
_ -> {:error, {:numero, :no_parse, c}, <<c::utf8>> <> rest}
end
end
end
def caractere(<<c::utf8>>) do
fn
<<^c::utf8>> <> rest -> {:ok, <<c::utf8>>, rest}
str -> {:error, {:caractere, :no_parse}, str}
end
end
def caractere_condicional(condicao) do
fn
<<c::utf8>> <> rest ->
if condicao.(<<c::utf8>>) do
{:ok, <<c::utf8>>, rest}
else
{:error, {:caractere_condicional, :condition_failed}, <<c::utf8>> <> rest}
end
str -> {:error, {:caractere_condicional, :no_parse}, str}
end
end
def whitespace() do
caractere_condicional(&Regex.match?(~r/\s/, &1))
end
def ignorar(parser) do
fn str ->
{_, _, rest} = parser.(str)
{:ok, nil, rest}
end
end
def sequencia(parsers) do
fn str ->
case Enum.reduce(parsers, {:ok, [], str}, fn
_parser, {:error, err, rest} ->
{:error, err, rest}
parser, {:ok, acc, str} ->
case parser.(str) do
{:ok, result, rest} ->
{:ok, [result | acc], rest}
{:error, err, rest} ->
{:error, err, rest}
end
end) do
{:error, err, rest} -> {:error, err, rest}
{:ok, results, rest} -> {:ok, Enum.reverse(results), rest}
end
end
end
def sequencia_opcionais(parsers) do
fn str ->
Enum.filter(sequencia(parsers).(str), fn r -> not is_nil(r) end)
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment