{-|
Module : Parsing
Description : Simple Monadic Parsing Library
Maintainer : Thomas Hallgren
A Simple Monadic Parsing Library
Used in the course Functional Programming GU/Chalmers.
Original author: David Sands.
-}moduleParsing(-- * The Parser typeParser-- exports the type name but not the constructors,parse-- * Basic parsers,sat,item,digit,readsP-- behaves as reads :: Read a => [(a,String)],char,failure-- * Combining parsers,oneOrMore,zeroOrMore,chain,(<:>)-- * More general operators useful in parser construction-- ** Try two alternatives,(<|>)-- ** Apply a function to the result of a parser,(<$>),(<*>)-- ** Parse two things, return only the first,(<*)-- ** Parse two things, return only the second,(*>)-- ** Return a result without consuming any input,return){----------------------
Aim: reusable Parser combinators including
a new type for the Parser,
but no export of the constructor
Changes (v3 2016) Thomas Hallgren
Export <* and *> from class Applicative instead of the combinators <-< and >->
Export <|> from class Alternative instead of +++
Changes (v2 2015)
For compatibility with GHC>=7.10 Parser
is now also instance Applicative
Removal: Class Functor, Applicative and Monad provide a number of
functions that were previously exported explicitly, in particular
(>*>) is available as the bind operation (>>=),
success is return, pmap is fmap.
Additional function:
readsP :: Read a => Parser a
-- satisfies
-- parse readsP s == listToMaybe (reads s)
----------------------}whereimportData.CharimportData.Maybe(listToMaybe)-- boilerplate for GHC 10.7 compatibility:importControl.Applicative(Applicative(..),Alternative(..))importControl.Monad(liftM,ap)-------------------- | The abstract data type representing a ParsernewtypeParsera=P(String->Maybe(a,String))-- | Runs the parser on the given string -- to return maybe a thing and a stringparse::Parsera->String->Maybe(a,String)parse(Pf)s=fs-- | A parser for anything in the Read class,-- satisfying---- prop> parse readsP s == listToMaybe (reads s)readsP::Reada=>ParserareadsP=P$listToMaybe.reads------------------- -- | Parser than can never succeedfailure::Parsera-- always failsfailure=P$\s->Nothing-- | Parser that succeeds without looking at the Stringsuccess::a->Parserasuccessa=P$\s->Just(a,s)-- | Parse any single characteritem=P$\s->casesof(c:s')->Just(c,s')""->Nothinginfixr3+++-- | Try the first parser and if it fails try the second(+++)::Parsera->Parsera->Parserap+++q=P$\s->caseparsepsofNothing->parseqsr->r-- (p >*> f) parse using p to produce a. -- Then parse using f a infixl1>*>(>*>)::Parsera->(a->Parserb)->Parserbp>*>f=P$\s->caseparsepsofJust(a,s')->parse(fa)s'Nothing->Nothing------------------------------------------------- Parsers below do not depend on the internal -- representation of Parser-- | parse a single character satisfying property psat::(Char->Bool)->ParserCharsatp=item>*>\a->ifpathensuccessaelsefailure-- | parse a digit characterdigit::ParserChardigit=satisDigit-- | Parse a specific charactercharc=sat(==c)-- example: parse any lowercase letter -- followed by its uppercase equivalent aA or bB etc.ex1=satisAsciiLower>*>char.toUpper-- pmap modifies the result of a parser-- | Parse a thing, then parse a list of things, and -- return the first thing followed by the list of things(<:>)::Parsera->Parser[a]->Parser[a]p<:>q=p>*>\a->fmap(a:)q-- | Parse zero or more things zeroOrMore::Parsera->Parser[a]zeroOrMorep=oneOrMorep+++success[]-- | Parse one or more things oneOrMore::Parsera->Parser[a]oneOrMorep=p<:>zeroOrMorep-- | Parse a list of as, separated by bschain::Parsera->Parserb->Parser[a]chainpq=p<:>zeroOrMore(q*>p)-- example: comma separated digits "1,2,3"-- Standard definition for Functor and Applicative for -- GHC>=7.10 compatibility instanceFunctorParserwherefmap=liftMinstanceApplicativeParserwherepure=success(<*>)=apinstanceMonadParserwhere(>>=)=(>*>)return=pureinstanceAlternativeParserwhereempty=failure(<|>)=(+++)