data v0.5.2 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