A monadic parser combinator library based on Haskell's Parsec.
Install parsing
with Spago:
spago install parsing
Here is a basic tutorial introduction to monadic parsing with this package.
A parser turns a string into a data structure. Parsers in this library have the type Parser s a
, where s
is the type of the input string, and a
is the type of the data which the parser will produce on success. Parser s a
is a monad. It’s defined in the module Text.Parsing.Parser
.
Monads can be used to provide context for a computation, and that’s how we use them in monadic parsing. The context provided by the Parser
monad is the parser’s current location in the input string. Parsing starts at the beginning of the input string.
Parsing requires two more capabilities: choice and failure.
We need choice to be able to make decisions about what kind of thing we’re parsing depending on the input which we encouter. This is provided by the Alt
typeclass instance of Parser
monad, particularly the <|>
operator. That operator will first try the left parser and if that fails, then it will backtrack the input string and try the right parser.
We need failure in case the input stream is not parseable. This is provided by the fail
function, which calls the throwError
function of the MonadThrow
typeclass instance of the Parser
monad. The result of running a parser has type Either ParseError a
, so if the parse succeeds then the result is Right a
and if the parse fails then the result is Left ParseError
.
To run a parser, call the function runParser :: s -> Parser s a -> Either ParseError a
in the Text.Parsing.Parser
module, and supply it with an input string and a parser.
Each type of input string needs primitive parsers. Primitive parsers for input string type String
are in the Text.Parsing.Parser.String
module. We can use these primitive parsers to write other String
parsers.
Here is a parser ayebee :: Parser String Boolean
which will accept only two input strings: "ab"
or "aB"
. It will return true
if the b
character is uppercase. It will return false
if the b
character is lowercase. It will fail with a ParseError
if the input string is anything else. This parser is written in terms of the primitive parser char :: Parser String Char
.
ayebee :: Parser String Boolean
ayebee = do
_ <- char 'a'
b <- char 'b' <|> char 'B'
pure (b == 'B')
We can run the parser ayebee
like so
runParser "aB" ayebee
and then the parser will succeed and return Right true
.
When you write a real parser you will usually want to return a more complicated data structure than a single Boolean
. See Parse, don't validate.
There are other String
parsers in the module Text.Parsing.Parser.Token
, for example the parser letter :: Parser String Char
which will accept any single alphabetic letter.
A parser combinator is a function which takes a parser as an argument and returns a new parser. The many
combinator, for example, will repeat a parser as many times as it can. So the parser many letter
will have type Parser String (Array Char)
. Parser combinators are in this package in the module Text.Parsing.Parser.Combinators
.
Here is the original short classic FUNCTIONAL PEARLS Monadic Parsing in Haskell by Graham Hutton and Erik Meijer.
Revisiting Monadic Parsing in Haskell by Vaibhav Sagar is a reflection on the Hutton, Meijer FUNCTIONAL PEARL.
Parse, don't validate by Alexis King is about what it means to “parse” something, without any mention of monads.
There are lots of other great monadic parsing tutorials on the internet.
parsing-dataview
primitive parsers for binary parsing ofArrayBuffer
.parsing-replace
for finding text patterns, and also replacing or splitting on the found patterns.
parsing
documentation is stored in a few places:
- Module documentation is published on Pursuit.
- Written documentation is kept in the docs directory.
- Usage examples can be found in the test suite.
If you get stuck, there are several ways to get help:
- Open an issue if you have encountered a bug or problem.
- Ask general questions on the PureScript Discourse forum or the PureScript Discord chat.
You can contribute to parsing
in several ways:
-
If you encounter a problem or have a question, please open an issue. We'll do our best to work with you to resolve or answer it.
-
If you would like to contribute code, tests, or documentation, please read the contributor guide. It's a short, helpful introduction to contributing to this library, including development instructions.
-
If you have written a library, tutorial, guide, or other resource based on this package, please share it on the PureScript Discourse! Writing libraries and learning resources are a great way to help this library succeed.