party
A simple parser combinator library. Party is stable, though breaking changes might come in a far-future 2.0 or 3.0 release.
Types
The custom error type for the parser,
which can itself be parameterized by a user-defined error type.
The user-defined error type is useful for, for example,
adding a int.parse call into your parser pipeline.
See try for using this feature.
pub type ParseError(e) {
Unexpected(pos: Position, error: String)
UserError(pos: Position, error: e)
}
Constructors
-
Unexpected(pos: Position, error: String) -
UserError(pos: Position, error: e)
The parser type, parameterized by the type it parses and the user-defined error type it can return.
pub opaque type Parser(a, e)
Functions
pub fn all(ps: List(Parser(a, b))) -> Parser(a, b)
Do each parser in the list, returning the result of the last parser.
pub fn choice(ps: List(Parser(a, b))) -> Parser(a, b)
Parse with the first parser in the list that doesn’t fail.
pub fn do(
p: Parser(a, b),
f: fn(a) -> Parser(c, b),
) -> Parser(c, b)
A monadic bind for pleasant interplay with gleam’s use syntax.
example:
fn identifier() -> Parser(String, e) {
use pos <- do(pos())
use first <- do(lowercase_letter())
use rest <- do(many(alt(alphanum(), char("_"))))
return(Ident(pos, first <> string.concat(rest)))
}
pub fn either(p: Parser(a, b), q: Parser(a, b)) -> Parser(a, b)
Parse the first parser, or the second if the first fails.
pub fn end() -> Parser(Nil, a)
Parses successfully only when at the end of the input string.
pub fn error_map(p: Parser(a, b), f: fn(b) -> c) -> Parser(a, c)
Transform the user-defined error type with a user-provided conversion function.
pub fn go(
p: Parser(a, b),
src: String,
) -> Result(a, ParseError(b))
Apply a parser to a string.
pub fn lazy(p: fn() -> Parser(a, b)) -> Parser(a, b)
Run a parser as normal, but the parser itself isn’t evaluated until it is used.
This is needed for recursive grammars, such as E := n | E + E where n is a number.
Example: lazy(digit) instead of digit().
pub fn many(p: Parser(a, b)) -> Parser(List(a), b)
Keep trying the parser until it fails, and return the array of parsed results. This cannot fail because it parses zero or more times!
pub fn many1(p: Parser(a, b)) -> Parser(List(a), b)
Keep trying the parser until it fails, and return the array of parsed results. This can fail, because it must parse successfully at least once!
pub fn many1_concat(p: Parser(String, a)) -> Parser(String, a)
Parse a certain string as many times as possible, returning everything that was parsed. This can fail, because it must parse successfully at least once!
pub fn many_concat(p: Parser(String, a)) -> Parser(String, a)
Parse a certain string as many times as possible, returning everything that was parsed. This cannot fail because it parses zero or more times!
pub fn map(p: Parser(a, b), f: fn(a) -> c) -> Parser(c, b)
Do p, then apply f to the result if it succeeded.
pub fn not(p: Parser(a, b)) -> Parser(Nil, b)
Negate a parser: if it succeeds, this fails, and vice versa.
Example: seq(string("if"), not(either(alphanum(), char("_"))))
pub fn perhaps(p: Parser(a, b)) -> Parser(Result(a, Nil), b)
Try running a parser, but still succeed (with Error(Nil)) if it failed.
pub fn return(x: a) -> Parser(a, b)
A monadic return for pleasant interplay with gleam’s use syntax.
see do for more details and an example.
This is redundant if the last do is a map instead.
But I prefer using it, stylistically.
pub fn satisfy(
when pred: fn(String) -> Bool,
) -> Parser(String, a)
Parse a character if it matches the predicate.
pub fn sep(
parser: Parser(a, b),
by s: Parser(c, b),
) -> Parser(List(a), b)
Parse a sequence separated by the given separator parser.
pub fn sep1(
parser: Parser(a, b),
by s: Parser(c, b),
) -> Parser(List(a), b)
Parse a sequence separated by the given separator parser. This only succeeds if at least one element of the sequence was parsed.
pub fn seq(p: Parser(a, b), q: Parser(c, b)) -> Parser(c, b)
Do the first parser, ignore its result, then do the second parser.
pub fn try(
p: Parser(a, b),
f: fn(a) -> Result(c, b),
) -> Parser(c, b)
Do p, the apply f to the result if it succeeded.
f itself can fail with the user-defined error type,
and if it does the result is a UserError with the error.