data v0.5.0 Data.Parser
Higher-order functions to create and modify parsers.
Link to this section Summary
Functions
Takes a parser p and creates a parser that will successfully parse lists of values that all satisfy p.
Takes a parser and transforms it so that it works 'inside' Maybe.t values.
Creates a parser that behaves exactly the same as the list/1 parser, except
that it will return the domain error :empty_list if applied to an empty list.
Takes a list of values, elements, and returns a parser that returns
successfully if its input is present in elements.
Takes a boolean function p (the predicate), and returns a parser
that parses successfully those values for which p is true.
Takes a boolean function p (the predicate) and a default value, and returns
a parser that parses successfully those values for which p is true.
Takes a parser p and creates a parser that will successfully parse sets of
values that all satisfy p.
Takes a list of parsers and creates a parser that returns the first successful parse result, or an error listing the parsers and the failed input.
Link to this section Types
A parser is a function that takes any value as input and produces a Result.t.
More specifically, a parser(a,b) is a fuction that takes any input and
returns {:ok, a} on a successful parse or {:error, b} if parsing failed.
Link to this section Functions
kv(fields)
See Data.Parser.KV.new/1.
Takes a parser p and creates a parser that will successfully parse lists of values that all satisfy p.
Specifically, the input:
1) Must be a list
2) p must parse successfully all elements in the input
If this is the case, the output will be {:ok, list_of_parsed_values}.
If not all values can be parsed with p, the result will be the original
parse error, enriched with the field :failed_element in the error details.
If the input is not a list, the domain error :not_a_list will be returned.
Examples
iex> Data.Parser.list(Data.Parser.BuiltIn.integer()).([])
{:ok, []}
iex> Data.Parser.list(Data.Parser.BuiltIn.integer()).([1,2,3])
{:ok, [1, 2, 3]}
iex> {:error, e} = Data.Parser.list(Data.Parser.BuiltIn.integer()).(%{a: :b})
...> Error.reason(e)
:not_a_list
iex> {:error, e} = Data.Parser.list(Data.Parser.BuiltIn.integer()).([1, :b, 3])
...> Error.reason(e)
:not_an_integer
...> Error.details(e)
%{failed_element: :b}
Takes a parser and transforms it so that it works 'inside' Maybe.t values.
If the original parser works on String.t(), the new one will work on
Maybe.t(String.t()).
Successful parses on just() values return {:ok, {:just, result_of_parse}}.
Unsuccessful parses on just() values reutrn {:error, parse_error}.
The parser will successfully return {:ok, :nothing} when applied to :nothing.
Examples
iex(2)> Data.Parser.maybe(
...> Data.Parser.predicate( &String.valid?/1, :invalid)).({:just, "good"})
{:ok, {:just, "good"}}
iex> Data.Parser.maybe(
...> Data.Parser.predicate( &String.valid?/1, :invalid)).({:just, 'bad'})
{:error, :invalid}
iex> Data.Parser.maybe(
...> Data.Parser.predicate( &String.valid?/1, :invalid)).(:nothing)
{:ok, :nothing}
Creates a parser that behaves exactly the same as the list/1 parser, except
that it will return the domain error :empty_list if applied to an empty list.
Examples
iex> Data.Parser.nonempty_list(Data.Parser.BuiltIn.integer()).([1, 2, 3])
{:ok, [1, 2, 3]}
iex> {:error, e} = Data.Parser.nonempty_list(Data.Parser.BuiltIn.integer()).([1, :b, 3])
...> Error.reason(e)
:not_an_integer
...> Error.details(e)
%{failed_element: :b}
iex> {:error, e} = Data.Parser.nonempty_list(Data.Parser.BuiltIn.integer()).([])
...> Error.reason(e)
:empty_list
one_of(elements, default)
one_of([a], b | (a -> b)) :: t(a, b) when a: var, b: var
Takes a list of values, elements, and returns a parser that returns
successfully if its input is present in elements.
If the input is not a member of elements and default is a value, the
parser fails with {:error, default}. If default is a unary function, the
parser fails with {:error, default.(input)}.
Examples
iex> Data.Parser.one_of([:he, :ne, :ar, :kr, :xe, :rn], "not a noble gas").(:he)
{:ok, :he}
iex> Data.Parser.one_of([:he, :ne, :ar, :kr, :xe, :rn], "not a noble gas").(:n)
{:error, "not a noble gas"}
iex> Data.Parser.one_of([:he, :ne, :ar, :kr, :xe, :rn],
...> fn x -> "not a noble gas: #{inspect x}" end).(:o)
{:error, "not a noble gas: :o"}
Takes a boolean function p (the predicate), and returns a parser
that parses successfully those values for which p is true.
If the predicate returns false the parser will return a domain Error
with the input value and the predicate functions listed in the error details.
Examples
iex> {:error, e} = Data.Parser.predicate(&String.valid?/1).('charlists are not ok')
...> e.reason
:predicate_not_satisfied
...> e.details
%{input: 'charlists are not ok', predicate: &String.valid?/1}
iex> Data.Parser.predicate(&String.valid?/1).("this is fine")
{:ok, "this is fine"}
iex> Data.Parser.predicate(&(&1<10)).(5)
{:ok, 5}
iex> {:error, e} = Data.Parser.predicate(&(&1<10)).(55)
...> e.details.input
55
predicate(p, default)
Takes a boolean function p (the predicate) and a default value, and returns
a parser that parses successfully those values for which p is true.
If the predicate function applied to the input returns true, the parser
wraps the input in an {:ok, input} tuple.
If the predicate function returns false, and default is a value, the
parser returns {:error, default}
If the predicate returns false and default is a unary function, the
parser returns {:error, default.(the_failed_input)}.
Examples
iex> Data.Parser.predicate(&String.valid?/1, "invalid string").('charlists are not ok')
{:error, "invalid string"}
iex> Data.Parser.predicate(&String.valid?/1, "invalid string").(<<"neither are invalid utf sequences", 99999>>)
{:error, "invalid string"}
iex> Data.Parser.predicate(&String.valid?/1, "invalid string").("this is fine")
{:ok, "this is fine"}
iex> Data.Parser.predicate(&String.valid?/1, fn x -> "the bad value is: #{inspect x}" end).(12345)
{:error, "the bad value is: 12345"}
Takes a parser p and creates a parser that will successfully parse sets of
values that all satisfy p.
Specifically, the input:
1) must be a MapSet
2) all elements of the input set must be parsed correctly by p
If this is the case, the output will be {:ok, set_of_parsed_values}.
If not all values can be parsed with p, the result will be the original parse
error, enriched with the field :failed_element in the error details.
If the input is not a MapSet, the domain error :not_a_set will be returned.
Examples
iex> {:ok, s} = Data.Parser.set(Data.Parser.BuiltIn.integer()).(MapSet.new())
...> s
#MapSet<[]>
iex> {:ok, s} = Data.Parser.set(Data.Parser.BuiltIn.integer()).(MapSet.new([1,2,3]))
...> s
#MapSet<[1, 2, 3]>
iex> {:error, e} = Data.Parser.set(Data.Parser.BuiltIn.integer()).(%{a: :b})
...> Error.reason(e)
:not_a_set
iex> {:error, e} = Data.Parser.set(Data.Parser.BuiltIn.integer()).(MapSet.new([1, :b, 3]))
...> Error.reason(e)
:not_an_integer
...> Error.details(e)
%{failed_element: :b}
Takes a list of parsers and creates a parser that returns the first successful parse result, or an error listing the parsers and the failed input.
Examples
iex> Data.Parser.union(
...> [Data.Parser.BuiltIn.integer(),
...> Data.Parser.BuiltIn.boolean()]).(true)
{:ok, true}
iex> Data.Parser.union(
...> [Data.Parser.BuiltIn.integer(),
...> Data.Parser.BuiltIn.boolean()]).(1)
{:ok, 1}
iex> {:error, e} = Data.Parser.union(
...> [Data.Parser.BuiltIn.integer(),
...> Data.Parser.BuiltIn.boolean()]).(:atom)
...> Error.reason(e)
:no_parser_applies
...> Error.details(e).input
:atom