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 })Run a list of parsers in sequence, accumulating the results.
parse (sequence [string "a", string "b"]) "ab" ==
(Ok ["a", "b"], { input = "", position = 2 })
parse (sequence [string "a", string "b"]) "ac" ==
(Err ["expected \"b\"", { input = "c", position = 1 })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.
Parse zero or more occurences of one parser separated and optionally ended by another.
parse (sepEndBy (string ",") (string "a")) "a,a,a," ==
(Ok ["a", "a", "a"], { input = "", position = 6 })Parse one or more occurences of one parser separated and optionally ended by another.
parse (sepEndBy1 (string ",") (string "a")) "" ==
(Err ["expected \"a\""], { input = "", position = 0 })
parse (sepEndBy1 (string ",") (string "a")) "a" ==
(Ok ["a"], { input = "", position = 1 })
parse (sepEndBy1 (string ",") (string "a")) "a," ==
(Ok ["a"], { input = "", position = 2 })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.