View Source Elnom.Multi (elnom v0.1.0)

Combinators applying their child parser multiple times

Summary

Functions

Runs the embedded parser count times, gathering the results into a list

Repeats the embedded parser, calling fun to gather the results.

Repeats the embedded parser, calling fun to gather the results.

Repeats the embedded parser m..=n times, calling g to gather the results

Gets a number from the first parser, then applies the second parser that many times.

Gets a number from the parser and returns a substring of the input of that size in utf-8 characters or bytes, depending on the size argument. If the parser returns Incomplete, length_data will return an error.

Gets a number from the first parser, takes a substring of the input of that size in utf-8 characters or bytes (depending on the size argument), then applies the second parser on that substring. If the second parser returns Incomplete, length_value will return an error.

Repeats the embedded parser, gathering the results in a list.

Repeats the embedded parser, counting the results

Runs the embedded parser, gathering the results in a Vec.

Runs the embedded parser, counting the results.

Repeats the embedded parser m..n times

Applies the parser parser until the parser until produces a result.

Alternates between two parsers to produce a list of elements.

Alternates between two parsers to produce a list of elements until Error.

Functions

Runs the embedded parser count times, gathering the results into a list

iex> parser = count(tag("abc"), 2)
iex> parser.("abcabc")
{:ok, "", ["abc", "abc"]}
iex> parser.("abc123")
{:error, %Error{kind: :tag, buffer: "123"}}
iex> parser.("123123")
{:error, %Error{kind: :tag, buffer: "123123"}}
iex> parser.("")
{:error, %Error{kind: :tag, buffer: ""}}
iex> parser.("abcabcabc")
{:ok, "abc", ["abc", "abc"]}
Link to this function

fold_many0(parser, init, fun)

View Source

Repeats the embedded parser, calling fun to gather the results.

This stops on Error. To instead chain an error up, see cut/1.

Warning: the element and accumulator arguments passed to the fun are swapped relative to the Rust library so that they are idiomatic with Enum.reduce/2.

iex> parser = fold_many0(tag("abc"), fn -> [] end, fn x, acc -> [[x] | acc] end)
iex> parser.("abcabc")
{:ok, "", [["abc"], ["abc"]]}
iex> parser.("abc123")
{:ok, "123", [["abc"]]}
iex> parser.("123123")
{:ok, "123123", []}
iex> parser.("")
{:ok, "", []}
Link to this function

fold_many1(parser, init, fun)

View Source

Repeats the embedded parser, calling fun to gather the results.

This stops on Error if there is at least one result. To instead chain an error up, see cut/1.

Warning: the element and accumulator arguments passed to the fun are swapped relative to the Rust library so that they are idiomatic with Enum.reduce/2.

iex> parser = fold_many1(tag("abc"), fn -> [] end, fn x, acc -> [[x] | acc] end)
iex> parser.("abcabc")
{:ok, "", [["abc"], ["abc"]]}
iex> parser.("abc123")
{:ok, "123", [["abc"]]}
iex> parser.("123123")
{:error, %Error{kind: :many1, buffer: "123123"}}
iex> parser.("")
{:error, %Error{kind: :many1, buffer: ""}}
Link to this function

fold_many_m_n(min, max, parser, init, fun)

View Source

Repeats the embedded parser m..=n times, calling g to gather the results

This stops before n when the parser returns Err::Error. To instead chain an error up, see cut.

Warning: the element and accumulator arguments passed to the fun are swapped relative to the Rust library so that they are idiomatic with Enum.reduce/2.

iex> parser = fold_many_m_n(0, 2, tag("abc"), fn -> [] end, fn x, acc -> [[x] | acc] end)
iex> parser.("abcabc")
{:ok, "", [["abc"], ["abc"]]}
iex> parser.("abc123")
{:ok, "123", [["abc"]]}
iex> parser.("123123")
{:ok, "123123", []}
iex> parser.("")
{:ok, "", []}
iex> parser.("abcabcabc")
{:ok, "abc", [["abc"], ["abc"]]}

iex> parser = fold_many_m_n(2, 2, tag("abc"), fn -> [] end, fn x, acc -> [[x] | acc] end)
iex> parser.("abcabc")
{:ok, "", [["abc"], ["abc"]]}
iex> parser.("abc")
{:error, %Error{kind: :many_m_n, buffer: ""}}
iex> parser.("")
{:error, %Error{kind: :many_m_n, buffer: ""}}
Link to this function

length_count(length_parser, data_parser)

View Source

Gets a number from the first parser, then applies the second parser that many times.

iex> parser = length_count(u8(), tag("abc"))
iex> parser.(<<2, "abcabcabc">>)
{:ok, "abc", ["abc", "abc"]}
iex> parser.(<<3, "123123123">>)
{:error, %Error{kind: :tag, buffer: "123123123"}}

iex> length_count(integer(), tag("abc")).("2abcabcabc")
{:ok, "abc", ["abc", "abc"]}
Link to this function

length_data(length_parser, size)

View Source

Gets a number from the parser and returns a substring of the input of that size in utf-8 characters or bytes, depending on the size argument. If the parser returns Incomplete, length_data will return an error.

iex> parser = length_data(be_u16(), :utf8)
iex> parser.(<<0, 3, "ab💙efg">>)
{:ok, "efg", "ab💙"}
iex> parser.(<<0, 3, "a">>)
{:error, %Incomplete{needed: 2}}

iex> parser = length_data(be_u16(), :byte)
iex> parser.(<<0, 3, "ab💙efg">>)
{:ok, <<0x9f, 0x92, 0x99, "efg">>, <<"ab", 0xf0>>}
iex> parser.(<<0, 3, "a">>)
{:error, %Incomplete{needed: 2}}
Link to this function

length_value(length_parser, data_parser, size)

View Source

Gets a number from the first parser, takes a substring of the input of that size in utf-8 characters or bytes (depending on the size argument), then applies the second parser on that substring. If the second parser returns Incomplete, length_value will return an error.

iex> parser = length_value(be_u16(), tag("ab💙"), :utf8)
iex> parser.(<<0, 3, "ab💙efg">>)
{:ok, "efg", "ab💙"}
iex> parser.(<<0, 3, "123123">>)
{:error, %Error{kind: :tag, buffer: "123"}}
iex> parser.(<<0, 3, "a">>)
{:error, %Incomplete{needed: 2}}

iex> parser = length_value(be_u16(), tag("abc"), :byte)
iex> parser.(<<0, 3, "abcefg">>)
{:ok, "efg", "abc"}

Repeats the embedded parser, gathering the results in a list.

This stops on Error and returns the results that were accumulated. To instead chain an error up, see cut/1.

iex> parser = many0(tag("abc"))
iex> parser.("abcabc")
{:ok, "", ["abc", "abc"]}
iex> parser.("abc123")
{:ok, "123", ["abc"]}
iex> parser.("123123")
{:ok, "123123", []}
iex> parser.("")
{:ok, "", []}
iex> parser.("abcabcabcxabc")
{:ok, "xabc", ["abc", "abc", "abc"]}

iex> many0(alpha0()).("")
{:error, %Error{kind: :many, buffer: ""}}

Repeats the embedded parser, counting the results

This stops on Error. To instead chain an error up, see cut/1.

iex> parser = many0_count(tag("abc"))
iex> parser.("abcabc")
{:ok, "", 2}
iex> parser.("abc123")
{:ok, "123", 1}
iex> parser.("123123")
{:ok, "123123", 0}
iex> parser.("")
{:ok, "", 0}
iex> parser.("abcabcabcxabc")
{:ok, "xabc", 3}

Runs the embedded parser, gathering the results in a Vec.

This stops on Error if there is at least one result, and returns the results that were accumulated. To instead chain an error up, see cut/1.

iex> parser = many1(tag("abc"))
iex> parser.("abcabc")
{:ok, "", ["abc", "abc"]}
iex> parser.("abc123")
{:ok, "123", ["abc"]}
iex> parser.("123123")
{:error, %Error{kind: :tag, buffer: "123123"}}
iex> parser.("")
{:error, %Error{kind: :tag, buffer: ""}}

Runs the embedded parser, counting the results.

This stops on Error if there is at least one result. To instead chain an error up, see cut/1.

iex> parser = many1_count(tag("abc"))
iex> parser.("abcabc")
{:ok, "", 2}
iex> parser.("abc123")
{:ok, "123", 1}
iex> parser.("123123")
{:error, %Error{kind: :tag, buffer: "123123"}}
iex> parser.("")
{:error, %Error{kind: :tag, buffer: ""}}
Link to this function

many_m_n(min, max, parser)

View Source

Repeats the embedded parser m..n times

This stops before n when the parser returns Error and returns the results that were accumulated. To instead chain an error up, see cut/1.

iex> parser = many_m_n(0, 2, tag("abc"))
iex> parser.("abcabc")
{:ok, "", ["abc", "abc"]}
iex> parser.("abc123")
{:ok, "123", ["abc"]}
iex> parser.("123123")
{:ok, "123123", []}
iex> parser.("")
{:ok, "", []}
iex> parser.("abcabcabc")
{:ok, "abc", ["abc", "abc"]}

iex> parser = many_m_n(2, 2, tag("abc"))
iex> parser.("abcabc")
{:ok, "", ["abc", "abc"]}
iex> parser.("abc")
{:error, %Error{kind: :many_m_n, buffer: ""}}
iex> parser.("")
{:error, %Error{kind: :many_m_n, buffer: ""}}
Link to this function

many_till(parser, until)

View Source

Applies the parser parser until the parser until produces a result.

Returns a tuple of the results of parser in a list and the result of until.

parser keeps going so long as until produces Error. To instead chain an error up, see cut/1.

iex> parser = many_till(tag("abc"), tag("end"))
iex> parser.("abcabcend")
{:ok, "", {["abc", "abc"], "end"}}
iex> parser.("abc123end")
{:error, %Error{kind: :tag, buffer: "123end"}}
iex> parser.("123123end")
{:error, %Error{kind: :tag, buffer: "123123end"}}
iex> parser.("")
{:error, %Error{kind: :tag, buffer: ""}}
iex> parser.("abcendefg")
{:ok, "efg", {["abc"], "end"}}
iex> parser.("endabc")
{:ok, "abc", {[], "end"}}
Link to this function

separated_list0(separator, parser)

View Source

Alternates between two parsers to produce a list of elements.

This stops when either parser returns Error and returns the results that were accumulated. To instead chain an error up, see cut/1.

iex> parser = separated_list0(tag("|"), tag("abc"))
iex> parser.("abc|abc|abc")
{:ok, "", ["abc", "abc", "abc"]}
iex> parser.("abc123abc")
{:ok, "123abc", ["abc"]}
iex> parser.("abc|def")
{:ok, "|def", ["abc"]}
iex> parser.("")
{:ok, "", []}
iex> parser.("def|abc")
{:ok, "def|abc", []}

iex> parser = separated_list0(map(digit1(), &String.to_integer/1), tag("abc"))
iex> parser.("abc23abc")
{:ok, "", ["abc", "abc"]}
Link to this function

separated_list1(separator, parser)

View Source

Alternates between two parsers to produce a list of elements until Error.

Fails if the element parser does not produce at least one element.

This stops when either parser returns Error and returns the results that were accumulated. To instead chain an error up, see cut/1.

iex> parser = separated_list1(tag("|"), tag("abc"))
iex> parser.("abc|abc|abc")
{:ok, "", ["abc", "abc", "abc"]}
iex> parser.("abc123abc")
{:ok, "123abc", ["abc"]}
iex> parser.("abc|def")
{:ok, "|def", ["abc"]}
iex> parser.("")
{:error, %Error{kind: :tag, buffer: ""}}
iex> parser.("def|abc")
{:error, %Error{kind: :tag, buffer: "def|abc"}}