Additional Combinators (parsley.combinator)

While many combinators are implemented as methods directly on the Parsley type, some are left as functions within the combinator module. These mostly involve handling repeating parsers. Not all the combinators are discussed here.

The Scaladoc for this page can be found at parsley.combinator.

Iterative Combinators

One of the main classes of combinator are the iterative combinators, which execute parsers multiple times until they cannot match any more; the results of these combinators vary. If the parser being repeated fails having consumed input, iterative combinators will fail; if no input was consumed on failure, the iteration will stop.

The most commonly used of these are the many and some combinators (see Object Parsley), which return a list of the successful results. While some will parse one or more times, manyN generalises to work for any minimum required parses n. When the results are not needed, skipMany, skipSome, and skipManyN can be used instead. To determine how many times the parse was successful, the count and count1 can be used instead.

The manyTill and someTill combinators can be used to parse iteratively until some other parse is successful: this can be used, for instance, to scan comments:

import parsley.character.{string, item, endOfLine}
import parsley.combinator.{manyTill}

val comment = string("//") ~> manyTill(item, endOfLine)
// comment: parsley.Parsley[List[Char]] = parsley.Parsley@1d4ca6a8
comment.parse("// this is a comment\n")
// res0: parsley.Result[String, List[Char]] = Success(List( , t, h, i, s,  , i, s,  , a,  , c, o, m, m, e, n, t))

Separators

There are three variants of the iterative combinators that handle delimited parsing: reading something separated (or ended) by another delimiter:

Optional Combinators

The option, optional, and optionalAs combinators can be used to optionally parse something. The option combinator will inject the result into an Option; the optional combinator just returns Unit; and the optionalAs combinator unconditionally returns any given value.

import parsley.character.digit
import parsley.combinator.option

option(digit.zip(digit)).parse("")
// res1: parsley.Result[String, Option[(Char, Char)]] = Success(None)
option(digit.zip(digit)).parse("0")
// res2: parsley.Result[String, Option[(Char, Char)]] = Failure((line 1, column 2):
//   unexpected end of input
//   expected digit
//   >0
//     ^)
option(digit.zip(digit)).parse("09")
// res3: parsley.Result[String, Option[(Char, Char)]] = Success(Some((0,9)))

Conditional Combinators

The conditional combinators are used for conditional execution of a parser. These include ifP, guard, when, and whileP. As may be expected, ifP models an if-else-expression, whileP models a while-loop, and when models an if-statement. They mostly find their utility when used in conjunction with registers.