This library provides reasonably fast parser combinators.
The contex over which Parsers operate.
Construct a new primitive Parser.
If you find yourself reaching for this function often consider opening a Github issue with the library to have your custom Parsers included in the standard distribution.
Parse a string.
import Combine.Num exposing (int)
parse int "123" ==
(Ok 123, { input = "", position = 3 })
parse int "abc" ==
(Err ["expected an integer"], { input = "abc", position = 0 })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 "" ==
(Err ["expected \"(\""], { input = "", position = 0 })
parse list "()" ==
(Ok (EList []), { input = "", position = 2 })
parse list "(a (b c))" ==
(Ok (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" ==
(Ok "A", { input = "", position = 1 })Transform the error of a parser.
parse (mapError (\_ -> ["bad input"]) (string "a")) "b" ==
(Err ["bad input"], { input = "b", position = 0 })Sequence two parsers, passing the result of the first parser to a function that returns the second parser. The value of the second parser is returned on success.
import Combine.Num exposing (int)
choosy : Parser String
choosy =
int
`andThen` \x -> if x % 2 == 0
then string " is even"
else string " is odd"
parse choosy "1 is odd" ==
(Ok " is odd", { input = "", position = 8 })
parse choosy "1 is even" ==
(Err ["expected \" is odd\""], { input = " is even", position = 1 })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" ==
(Ok 3, { input = "", position = 3 })Fail without consuming any input.
Return a value without consuming any input.
parse (succeed 1) "a" ==
(Ok 1, { input = "a", position = 0 })Parse an exact string match.
parse (string "hello") "hello world" ==
(Ok "hello", { input = " world", position = 5 })
parse (string "hello") "goodbye" ==
(Err ["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" ==
(Ok "aaaaa", { input = "b", position = 5 })Consume input while the predicate matches.
parse (while ((/=) ' ')) "test 123" ==
(Ok "test", { input = " 123", position = 4 })Fail when the input is not empty.
parse end "" == (Ok (), { input = "", position = 0 })
parse end "a" == (Err ["expected end of input"], { input = "a", position = 0 })Choose between two parsers.
parse (string "a" `or` string "b") "a" ==
(Ok "a", { input = "", position = 1 })
parse (string "a" `or` string "b") "b" ==
(Ok "b", { input = "", position = 1 })
parse (string "a" `or` string "b") "c" ==
(Err ["expected \"a\"", "expected \"b\""], { input = "c", position = 0 })Choose between a list of parsers.
parse (choice [string "a", string "b"]) "a" ==
(Ok "a", { input = "", position = 1 })
parse (choice [string "a", string "b"]) "b" ==
(Ok "b", { input = "", position = 1 })Return a default value when the given parser fails.
letterA : Parser String
letterA = optional "a" (string "a")
parse letterA "a" == (Ok "a", { input = "", position = 1 })
parse letterA "b" == (Ok "a", { input = "b", position = 0 })Wrap the return value into a Maybe. Returns Nothing on failure.
parse (maybe (string "a")) "a" ==
(Ok (Just "a"), { input = "", position = 1 })
parse (maybe (string "a")) "b" ==
(Ok Nothing, { input = "b", position = 0 })Apply a parser until it fails and return a list of the results.
parse (many (string "a")) "aaab" ==
(Ok ["a", "a", "a"], { input = "b", position = 3 })
parse (many (string "a")) "" ==
(Ok [], { input = "", position = 0 })Parse at least one result.
parse (many1 (string "a")) "a" ==
(Ok ["a"], { input = "", position = 1 })
parse (many1 (string "a")) "" ==
(Err ["expected \"a\""], { input = "", position = 0 })Apply parser p zero or more times until parser end
succeeds. On success, the list of p's results is returned.
string "<!--" *> manyTill anyChar (string "-->")Parser zero or more occurences of one parser separated by another.
parse (sepBy (string ",") (string "a")) "b" ==
(Ok [], { input = "b", position = 0 })
parse (sepBy (string ",") (string "a")) "a,a,a" ==
(Ok ["a", "a", "a"], { input = "", position = 5 })
parse (sepBy (string ",") (string "a")) "a,a,b" ==
(Ok ["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 once.
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 braces {}.
Parse something between square brackets [].
The Parser type.
At their core,
Parsers simply wrap functions from aContextto a tuple of aResult resand a newContext.