Copyright | (c) 2021 Tony Zorman |
---|---|
License | BSD3 |
Maintainer | Tony Zorman <soliditsallgood@mailbox.org> |
Stability | experimental |
Portability | non-portable |
Safe Haskell | Safe-Inferred |
Language | Haskell2010 |
A small wrapper around the ReadP
parser combinator in base
,
providing a more intuitive behaviour. While it's theoretically nice
that ReadP
is actually commutative, this makes a lot of parsing
operations rather awkward—more often than not, one only wants the
argument that's parsed "first".
Due to the left-biased nature of the chosen semigroup implementation,
using functions like many
or optional
from Control.Applicative
now yields more consistent behaviour with other parser combinator
libraries.
Synopsis
- data Parser a
- runParser :: Parser a -> String -> Maybe a
- eof :: Parser ()
- num :: (Read a, Integral a) => Parser a
- char :: Char -> Parser Char
- string :: String -> Parser String
- skipSpaces :: Parser ()
- get :: Parser Char
- look :: Parser String
- satisfy :: (Char -> Bool) -> Parser Char
- choice :: [Parser a] -> Parser a
- many1 :: Parser a -> Parser [a]
- sepBy :: Parser a -> Parser sep -> Parser [a]
- sepBy1 :: Parser a -> Parser sep -> Parser [a]
- endBy :: Parser a -> Parser sep -> Parser [a]
- endBy1 :: Parser a -> Parser sep -> Parser [a]
- munch :: (Char -> Bool) -> Parser String
- munch1 :: (Char -> Bool) -> Parser String
- pfail :: Parser a
Usage
NOTE: This module is mostly intended for developing of other modules. If you are a users, you probably won't find much use here—you have been warned.
The high-level API tries to stay as close to ReadP
as possible. If
you are familiar with that then no functions here should surprise you.
One notable usability difference when forcing left-biasedness is when
one wants to disambiguate a parse. For normal ReadP
usage this
happens after the actual parsing stage by going through the list of
successful parses. For Parser
it does when constructing the relevant
combinators, leading to only one successful parse. As an example,
consider the ReadP
-based parser
pLangle = ReadP.string "<" pLongerSequence = ReadP.char '<' *> ReadP.string "f" <* ReadP.char '>' pCombination = pLangle ReadP.+++ pLongerSequence
Parsing the string "f"
will return
>>>
ReadP.readP_to_S pCombination "<f>"
[("<","f>"),("f","")]
One would now need to, for example, filter for the second (leftover) string being empty and take the head of the resulting list (which may still have more than one element).
With Parser
, the same situation would look like the following
pLangle' = string "<" pLongerSequence' = char '<' *> string "f" <* char '>' pCombination' = pLongerSequence' <> pLangle'
Notice how pLangle'
and pLongerSequence'
have traded places—since we
are not forcing pLangle'
to consume the entire string and (<>)
is
left-biased, pLongerSequence'
parses a superset of pLangle'
!
Running runParser pCombination'
now yields the expected result:
>>>
runParser pCombination' "<f>"
Just "f"
One might also define pLangle'
as string "<" <* eof
, which would
enable a definition of pCombination' = pLangle' <> pLongerSequence'
.
For example uses, see XMonad.Util.EZConfig or XMonad.Prompt.OrgMode.
Running
Instances
Alternative Parser Source # | |
Applicative Parser Source # | |
Functor Parser Source # | |
Monad Parser Source # | |
a ~ String => IsString (Parser a) Source # | When |
Defined in XMonad.Util.Parser fromString :: String -> Parser a # | |
Monoid (Parser a) Source # | |
Semigroup (Parser a) Source # | |
Primitive Parsers
skipSpaces :: Parser () Source #
Skip all whitespace.
look :: Parser String Source #
Look-ahead: return the part of the input that is left, without consuming it.
Combining Parsers
satisfy :: (Char -> Bool) -> Parser Char Source #
Consume and return the next character if it satisfies the specified predicate.
choice :: [Parser a] -> Parser a Source #
Combine all parsers in the given list in a left-biased way.
sepBy :: Parser a -> Parser sep -> Parser [a] Source #
sepBy p sep
parses zero or more occurrences of p
, separated by
sep
. Returns a list of values returned by p
.
sepBy1 :: Parser a -> Parser sep -> Parser [a] Source #
sepBy1 p sep
parses one or more occurrences of p
, separated by
sep
. Returns a list of values returned by p
.
endBy :: Parser a -> Parser sep -> Parser [a] Source #
endBy p sep
parses zero or more occurrences of p
, separated and
ended by sep
.
endBy1 :: Parser a -> Parser sep -> Parser [a] Source #
endBy p sep
parses one or more occurrences of p
, separated and
ended by sep
.
munch :: (Char -> Bool) -> Parser String Source #
Parse the first zero or more characters satisfying the predicate.
Always succeeds; returns an empty string if the predicate returns
False
on the first character of input.