det-parse is a library of deterministic parser combinators. It is based on the material presented in Frank Huch's functional programming lecture at Kiel University. To use it, you build a
Parser a using the provided combinators and then apply it to a string using
parse. The simplest parsers are provided by the primitives
yield always results in the given value, consuming no input.
yield 1 will successfully parse the empty string to the value
failure is a parser that always fails.
anyChar is a parser that consumes a single character and uses it as the parse result.
check takes a parser and a predicate on the result type of the parser. From these, it builds a new parser that applies the existing parser and succeeds only if the predicate holds for the parse result.
word build parsers for single characters and whole strings from these primitives.
char 'c' is a parser that consumes the single character
c and results in the unit value
word "hello" consumes the string
hello and results in the unit value.
empty is a parser that recognizes an empty string and results in the unit value.
<* are provided to combine parsers into more comples ones.
*> applies two parsers and returns the result of the second one if both were successful.
char 'a' *> yield 1 is successful if applied to the string
a and results in the value
<* applies two parsers in the same order, i.e. left to right, but returns the result of the first one.
<|> combines two parsers by applying them both. If the first one is successful, it returns its result. If it is not, but the second one is, then it returns the result of the second one. If both are unsuccessful, the combined parser is unsuccessful as well. The parser
char 'a' *> yield 1 <|> char 'b' *> yield 2 parses the string
a to the value
1 and the string
b to the value
<!> works similarly to
<|>, but does not backtrack. That is, it only tries the second parser if the first one was unsuccessful, and only on the remaining input. It can be used if the alternatives do not overlap. The above example would also work if
<|> were replaced by
word "ab" *> yield 1 <!> word "abc" *> yield 2 would fail to parse
abc into the value
2 since the first alternative has already consumed
<$> builds a new parser from an existing parser by applying a function to the result of that parser. For example,
(+ 1) <$> (char 'a' *> yield 1) is a parser that parses the string
a into the value
<*> :: Parser (a -> b) -> Parser a -> Parser b combines two parsers, one that results in a function from
b, and one that results in an
a value. It applies the parsers in order and then applies the function result of the first parser to the value result of the second parser.
many :: Parser a -> Parser [a] builds a parser that parses whatever the original parser parses arbitrarily many times.
some is similar, but requires that the original parser succeed at least once. Applying
many (char 'a' *> yield 1) to the string
aaaa results in the value