This library provides reasonably fast parser combinators.
At their core, Parsers are functions from a Context to a
tuple of a Result and a new Context.
myParseFn : ParseFn Int
myParseFn c = (Done 1, c)
myParser : Parser Int
myParser = Parser myParseFn
parse myParser "a" ==
(Done 1, { input = "a", position = 0 })The contex over which ParseFns operate.
Running a Parser results in one of two states:
Done when the parser has successfully parsed the input (or part of
it) to a result, orFail when the parser has failed with a list of error messages.Parse a string.
Unwrap a parser so it can be applied to a context.
Defer a parser's evaluation.
type E = ETerm String | EList (List E)
whitespace : Parser String
whitespace = regex "[ \t\r\n]*"
term : Parser E
term = ETerm `map` (whitespace *> regex "[a-zA-Z]+" <* whitespace)
list : Parser E
list = rec (\() -> EList `map` (string "(" *> many (term `or` list) <* string ")"))
parse list "" ==
(Fail ["expected \"(\""], { input = "", position = 0 })
parse list "()" ==
(Done (EList []), { input = "", position = 2 })
parse list "(a (b c))" ==
(Done (EList [ETerm "a", EList [ETerm "b", ETerm "c"]]), { input = "", position = 9 })Transform both the result and error message of a parser.
Transform the result of a parser.
parse (map String.toUpper (string "a")) "a" ==
(Done "A", { input = "", position = 1 })Transform the error of a parser.
parse (mapError (\_ -> ["bad input"]) (string "a")) "b" ==
(Fail ["bad input"], { input = "b", position = 0 })Sequence two parsers by passing in the results of the first parser to the second.
Sequence two parsers.
import Maybe
import Result
import String
num : Parser Int
num = (Maybe.withDefault 0 << Result.toMaybe << String.toInt) `map` regex "[0-9]+"
sum : Parser Int
sum = (+) `map` (num <* string "+") `andMap` num
parse sum "1+2" ==
(Done 3, { input = "", position = 3 })Fail without consuming any input.
Return a value without consuming any input.
parse (succeed 1) "a" ==
(Done 1, { input = "a", position = 0 })Parse an exact string match.
parse (string "hello") "hello world" ==
(Done "hello", { input = " world", position = 5 })
parse (string "hello") "goodbye" ==
(Fail ["expected \"hello\""], { input = "goodbye", position = 0 })Parse a Regex match.
Regular expressions must match from the beginning of the input and their
subgroups are ignored. A ^ is added implicitly to the beginning of
every pattern unless one already exists.
parse (regex "a+") "aaaaab" ==
(Done "aaaaa", { input = "b", position = 5 })Consume input while the predicate matches.
parse (while ((/=) ' ')) "test 123" ==
(Done "test", { input = " 123", position = 4 })Fail when the input is not empty.
parse end "" == (Done (), { input = "", position = 0 })
parse end "a" == (Fail ["expected end of input"], { input = "a", position = 0 })Choose between two parsers.
parse (string "a" `or` string "b") "a" ==
(Done "a", { input = "", position = 1 })
parse (string "a" `or` string "b") "b" ==
(Done "b", { input = "", position = 1 })
parse (string "a" `or` string "b") "c" ==
(Fail ["expected \"a\"", "expected \"b\""], { input = "c", position = 0 })Choose between a list of parsers.
parse (choice [string "a", string "b"]) "a" ==
(Done "a", { input = "", position = 1 })
parse (choice [string "a", string "b"]) "b" ==
(Done "b", { input = "", position = 1 })Return a default value when the given parser fails.
letterA : Parser String
letterA = optional "a" (string "a")
parse letterA "a" == (Done "a", { input = "", position = 1 })
parse letterA "b" == (Done "a", { input = "b", position = 0 })Wrap the return value into a Maybe. Returns Nothing on failure.
parse (maybe (string "a")) "a" ==
(Done (Just "a"), { input = "", position = 1 })
parse (maybe (string "a")) "b" ==
(Done Nothing, { input = "b", position = 0 })Apply a parser until it fails and return a list of the results.
parse (many (string "a")) "aaab" ==
(Done ["a", "a", "a"], { input = "b", position = 3 })
parse (many (string "a")) "" ==
(Done [], { input = "", position = 0 })Parse at least one result.
parse (many1 (string "a")) "a" ==
(Done ["a"], { input = "", position = 1 })
parse (many1 (string "a")) "" ==
(Fail ["expected \"a\""], { input = "", position = 0 })Parser zero or more occurences of one parser separated by another.
parse (sepBy (string ",") (string "a")) "b" ==
(Done [], { input = "b", position = 0 })
parse (sepBy (string ",") (string "a")) "a,a,a" ==
(Done ["a", "a", "a"], { input = "", position = 5 })
parse (sepBy (string ",") (string "a")) "a,a,b" ==
(Done ["a", "a"], { input = ",b", position = 3 })Parse one or more occurences of one parser separated by another.
Apply a parser and skip its result.
Apply a parser and skip its result many times.
Apply a parser and skip its result at least one.
Parse one or more occurences of p separated by op, recursively
apply all functions returned by op to the values returned by p. See
the examples/Calc.elm file for an example.
Similar to chainl but functions of op are applied in
right-associative order to the values of p.
Parse n occurences of p.
Parse something between two other parsers.
The parser
between (string "(") (string ")") (string "a")is equivalent to the parser
string "(" *> string "a" <* string ")"Parse something between parentheses.
Parse something between brackets.
Parse something between square brackets.
A wrapper type around
ParseFns used to differentiate between eager and lazy parsers.