Combine.Parsers.Base

This module defines common abstract parsers, i.e. ignore, repeat, many, etc. To use them, just add import Combine.Parsers.Base to your module, or reference them directly.

Summary

Functions

Applies parser1, parser2, and parser3 in sequence, returning the result of parser2

Applies parser1 and parser2 in sequence, then sends their results to the given function to be transformed. The transformed value is then returned as the result of this parser

This parser is a generalized form of either which allows multiple parsers to be attempted

Tries to apply parser1 and if it fails, tries parser2, if both fail, then this parser fails. Returns whichever result was successful otherwise

This parser succeeds if the end of the input has been reached, otherwise it fails

This parser will fail with the given error message

This parser will fail fatally with the given error message

This parser will apply the given parser to the input, and if successful, will ignore the parse result. If the parser fails, this one fails as well

Applies parser. If it fails, it’s error is modified to contain the given label for easier troubleshooting

Applies parser zero or more times. Returns results as a list

Applies parser one or more times. Returns results as a list

Applies a transformation function to the result of the given parser. If the result returned is of the form {:error, reason}, the parser will fail with that reason

Applies a parser and then verifies that the result is not contained in the provided list of matches

Applies a parser and then verifies that the result is contained in the provided list of matches

Applies parser if possible. Returns the parse result if successful or nil if not

Applies both parser1 and parser2, returning both results as a tuple

Applies both parser1 and parser2, returning the result of parser1 only

Applies both parser1 and parser2, returning the result of parser2 only

Applies each parser in parsers, then sends the results to the provided function to be transformed. The result of the transformation is the final result of this parser

This parser applies the given parser, and if successful, passes the result to the predicate for validation. If either the parser or the predicate assertion fail, this parser fails

Applies parser1 zero or more times, separated by parser2. Returns results of parser1 in a list

Applies parser1 one or more times, separated by parser2. Returns results of parser1 in a list

Applies a sequence of parsers and returns their results as a list

Applies parser if possible, ignores the result

Applies parser zero or more times, ignores the result

Applies parser one or more times, ignores the result

Applies parser to the input n many times. Returns the result as a list

This parser will fail with no error

Types

parser :: (Combine.ParserState.t -> Combine.ParserState.t)
predicate :: (term -> boolean)
transform :: (term -> term)
transform2 :: (term, term -> term)

Functions

between(parser1, parser2, parser3)

Specs

between(parser, parser, parser) :: parser

Applies parser1, parser2, and parser3 in sequence, returning the result of parser2.

Example

iex> import Elixir.Combine.Parsers.Base
...> import Combine.Parsers.Text
...> Combine.parse("(234)", between(char("("), integer, char(")")))
[234]
between(parser, parser1, parser2, parser3)

Specs

between(parser, parser, parser, parser) :: parser
both(parser1, parser2, transform)

Specs

Applies parser1 and parser2 in sequence, then sends their results to the given function to be transformed. The transformed value is then returned as the result of this parser.

Example

iex> import Elixir.Combine.Parsers.Base
...> import Combine.Parsers.Text
...> to_int = fn ("-", y) -> y * -1; (_, y) -> y end
...> Combine.parse("1234-234", both(integer, both(char, integer, to_int), &(&1 + &2)))
[1000]
both(parser, parser1, parser2, transform)

Specs

choice(parsers)

Specs

choice([parser]) :: parser

This parser is a generalized form of either which allows multiple parsers to be attempted.

Example

iex> import Elixir.Combine.Parsers.Base
iex> import Combine.Parsers.Text
...> Combine.parse("test", choice([float, integer, word]))
["test"]
choice(parser, parsers)

Specs

choice(parser, [parser]) :: parser
either(parser1, parser2)

Specs

either(parser, parser) :: parser

Tries to apply parser1 and if it fails, tries parser2, if both fail, then this parser fails. Returns whichever result was successful otherwise.

Example

iex> import Elixir.Combine.Parsers.Base
iex> import Combine.Parsers.Text
...> Combine.parse("1234", either(float, integer))
[1234]
either(parser, parser1, parser2)

Specs

either(parser, parser, parser) :: parser
eof()

Specs

eof :: parser

This parser succeeds if the end of the input has been reached, otherwise it fails.

Example

iex> import Elixir.Combine.Parsers.Base
...> import Combine.Parsers.Text
...> Combine.parse("  ", spaces |> eof)
[" "]
eof(parser)

Specs

eof(parser) :: parser
fail(message)

Specs

fail(String.t) :: parser

This parser will fail with the given error message.

fail(parser, message)

Specs

fail(parser, String.T) :: parser
fatal(message)

Specs

fatal(String.t) :: parser

This parser will fail fatally with the given error message.

fatal(parser, message)

Specs

fatal(parser, String.t) :: parser
ignore(parser)

Specs

ignore(parser) :: parser

This parser will apply the given parser to the input, and if successful, will ignore the parse result. If the parser fails, this one fails as well.

Example

iex> import Elixir.Combine.Parsers.Base
...> import Combine.Parsers.Text
...> parser = ignore(char("h"))
...> Combine.parse("h", parser)
[]
...> parser = char("h") |> char("i") |> ignore(space) |> char("!")
...> Combine.parse("hi !", parser)
["h", "i", "!"]
ignore(parser, parser)

Specs

ignore(parser, parser) :: parser
label(parser, name)

Specs

label(parser, String.t) :: parser

Applies parser. If it fails, it’s error is modified to contain the given label for easier troubleshooting.

Example

iex> import Elixir.Combine.Parsers.Base
...> import Combine.Parsers.Text
...> Combine.parse("abc", label(integer, "year"))
{:error, "Expected `year` at line 1, column 1."}
label(parser, parser, name)

Specs

many(parser)

Specs

many(parser) :: parser

Applies parser zero or more times. Returns results as a list.

Example

iex> import Elixir.Combine.Parsers.Base
...> import Combine.Parsers.Text
...> Combine.parse("abc", many(char))
[["a", "b", "c"]]
...> Combine.parse("", many(char))
[[]]
many(parser, parser)

Specs

many(parser, parser) :: parser
many1(parser)

Specs

many1(parser) :: parser

Applies parser one or more times. Returns results as a list.

Example

iex> import Elixir.Combine.Parsers.Base
...> import Combine.Parsers.Text
...> Combine.parse("abc", many1(char))
[["a", "b", "c"]]
...> Combine.parse("abc", many1(ignore(char)))
[[]]
...> Combine.parse("12abc", digit |> digit |> many1(ignore(char)))
[1, 2, []]
many1(parser, parser)

Specs

many1(parser, parser) :: parser
map(parser, transform)

Specs

Applies a transformation function to the result of the given parser. If the result returned is of the form {:error, reason}, the parser will fail with that reason.

Example

iex> import Elixir.Combine.Parsers.Base
...> import Combine.Parsers.Text
...> Combine.parse("1234", map(integer, &(&1 * 2)))
[2468]
map(parser, parser, transform)

Specs

none_of(parser, items)

Specs

none_of(parser, Range.t | list) :: parser

Applies a parser and then verifies that the result is not contained in the provided list of matches.

Example

iex> import Elixir.Combine.Parsers.Base
...> import Combine.Parsers.Text
...> parser = none_of(char, ?a..?z |> Enum.map(&(<<&1::utf8>>)))
...> Combine.parse("ABC", parser)
["A"]
...> parser = upper |> none_of(char, ["i", "I"])
...> Combine.parse("Hello", parser)
["H", "e"]
none_of(parser, parser, items)

Specs

none_of(parser, parser, Range.t | list) :: parser
one_of(parser, items)

Specs

one_of(parser, Range.t | list) :: parser

Applies a parser and then verifies that the result is contained in the provided list of matches.

Example

iex> import Elixir.Combine.Parsers.Base
...> import Combine.Parsers.Text
...> parser = one_of(char, ?a..?z |> Enum.map(&(<<&1::utf8>>)))
...> Combine.parse("abc", parser)
["a"]
...> parser = upper |> one_of(char, ["i", "I"])
...> Combine.parse("Hi", parser)
["H", "i"]
one_of(parser, parser, items)

Specs

one_of(parser, parser, Range.t | list) :: parser
option(parser)

Specs

option(parser) :: parser

Applies parser if possible. Returns the parse result if successful or nil if not.

Example

iex> import Elixir.Combine.Parsers.Base
...> import Combine.Parsers.Text
...> Combine.parse("Hi", option(integer) |> word)
[nil, "Hi"]
option(parser, parser)

Specs

option(parser, parser) :: parser
pair_both(parser1, parser2)

Specs

pair_both(parser, parser) :: parser

Applies both parser1 and parser2, returning both results as a tuple.

Example

iex> import Elixir.Combine.Parsers.Base
...> import Combine.Parsers.Text
...> Combine.parse("-234", pair_both(char, integer))
[{"-", 234}]
pair_both(parser, parser1, parser2)

Specs

pair_both(parser, parser, parser) :: parser
pair_left(parser1, parser2)

Specs

pair_left(parser, parser) :: parser

Applies both parser1 and parser2, returning the result of parser1 only.

Example

iex> import Elixir.Combine.Parsers.Base
...> import Combine.Parsers.Text
...> Combine.parse("234-", pair_left(integer, char))
[234]
pair_left(parser, parser1, parser2)

Specs

pair_left(parser, parser, parser) :: parser
pair_right(parser1, parser2)

Specs

pair_right(parser, parser) :: parser

Applies both parser1 and parser2, returning the result of parser2 only.

Example

iex> import Elixir.Combine.Parsers.Base
...> import Combine.Parsers.Text
...> Combine.parse("-234", pair_right(char, integer))
[234]
pair_right(parser, parser1, parser2)

Specs

pair_right(parser, parser, parser) :: parser
pipe(parsers, transform)

Specs

pipe([parser], transform) :: parser

Applies each parser in parsers, then sends the results to the provided function to be transformed. The result of the transformation is the final result of this parser.

Example

iex> import Elixir.Combine.Parsers.Base
...> import Combine.Parsers.Text
...> Combine.parse("123", pipe([digit, digit, digit], fn digits -> {n, _} = Integer.parse(Enum.join(digits)); n end))
[123]
pipe(parser, parsers, transform)

Specs

pipe(parser, [parser], transform) :: parser
satisfy(parser, predicate)

Specs

satisfy(parser, predicate) :: parser

This parser applies the given parser, and if successful, passes the result to the predicate for validation. If either the parser or the predicate assertion fail, this parser fails.

Example

iex> import Elixir.Combine.Parsers.Base
...> import Combine.Parsers.Text
...> parser = satisfy(char, fn x -> x == "H" end)
...> Combine.parse("Hi", parser)
["H"]
...> parser = char("H") |> satisfy(char, fn x -> x == "i" end)
...> Combine.parse("Hi", parser)
["H", "i"]
satisfy(parser, parser, predicate)

Specs

satisfy(parser, parser, predicate) :: parser
sep_by(parser1, parser2)

Specs

sep_by(parser, parser) :: parser

Applies parser1 zero or more times, separated by parser2. Returns results of parser1 in a list.

Example

iex> import Elixir.Combine.Parsers.Base
...> import Combine.Parsers.Text
...> Combine.parse("1, 2, 3", sep_by(digit, string(", ")))
[[1, 2, 3]]
...> Combine.parse("", sep_by(digit, string(", ")))
[[]]
sep_by(parser, parser1, parser2)

Specs

sep_by(parser, parser, parser) :: parser
sep_by1(parser1, parser2)

Specs

sep_by1(parser, parser) :: parser

Applies parser1 one or more times, separated by parser2. Returns results of parser1 in a list.

Example

iex> import Elixir.Combine.Parsers.Base
...> import Combine.Parsers.Text
...> Combine.parse("1, 2, 3", sep_by1(digit, string(", ")))
[[1, 2, 3]]
sep_by1(parser, parser1, parser2)

Specs

sep_by1(parser, parser, parser) :: parser
sequence(parsers)

Specs

sequence([parser]) :: parser

Applies a sequence of parsers and returns their results as a list.

Example

iex> import Elixir.Combine.Parsers.Base
...> import Combine.Parsers.Text
...> Combine.parse("123", sequence([digit, digit, digit]))
[[1, 2, 3]]
...> Combine.parse("123-234", sequence([integer, char]) |> map(sequence([integer]), fn [x] -> x * 2 end))
[[123, "-"], 468]
sequence(parser, parsers)

Specs

sequence(parser, [parser]) :: parser
skip(parser)

Specs

skip(parser) :: parser

Applies parser if possible, ignores the result.

Example

iex> import Elixir.Combine.Parsers.Base
...> import Combine.Parsers.Text
...> Combine.parse("   abc", skip(spaces) |> word)
["abc"]
...> Combine.parse("", skip(spaces))
[]
skip(parser, parser)

Specs

skip(parser, parser) :: parser
skip_many(parser)

Specs

skip_many(parser) :: parser

Applies parser zero or more times, ignores the result.

Example

iex> import Elixir.Combine.Parsers.Base
...> import Combine.Parsers.Text
...> Combine.parse("   abc", skip_many(space) |> word)
["abc"]
...> Combine.parse("", skip_many(space))
[]
skip_many(parser, parser)

Specs

skip_many(parser, parser) :: parser
skip_many1(parser)

Specs

skip_many1(parser) :: parser

Applies parser one or more times, ignores the result.

Example

iex> import Elixir.Combine.Parsers.Base
...> import Combine.Parsers.Text
...> Combine.parse("   abc", skip_many1(space) |> word)
["abc"]
...> Combine.parse("", skip_many1(space))
{:error, "Expected space, but hit end of input."}
skip_many1(parser, parser)

Specs

skip_many1(parser, parser) :: parser
times(parser, n)

Specs

times(parser, pos_integer) :: parser

Applies parser to the input n many times. Returns the result as a list.

Example

iex> import Elixir.Combine.Parsers.Base
...> import Combine.Parsers.Text
...> Combine.parse("123", times(digit, 3))
[[1,2,3]]
times(parser, parser, n)

Specs

times(parser, parser, pos_integer) :: parser
zero()

Specs

zero :: parser

This parser will fail with no error.

zero(parser)

Specs

zero(parser) :: parser