{-# LANGUAGE MultiParamTypeClasses #-} -- | It will help in using this library if you are familiar with -- Parsec. (The best way to become familiar with Parsec is to read the -- source. See also ) module Text.ParserCombinators.Parsely.Class where import Control.Monad import qualified Text.ParserCombinators.Parsec as P infix 0 infixr 1 <|> -- | This is just a type-restricted version of 'mplus' (as in Parsec) (<|>) :: Parsely m => m a -> m a -> m a (<|>) = mplus class (Functor m, MonadPlus m) => Parsely m where -- | Give a name to a parser (used in error messages, hopefully) () :: m a -> String -> m a () = const -- | This parser didn't expect that input. Try other branch of -- '<|>'? Nearly the same as 'mzero', but 'mzero' may produce a -- less informative message in case of error. unexpected :: String -> m a unexpected _ = mzero -- | Run given parser as many times as possible, returning -- results. In the typeclass because Parsec needs them as -- primitives to avoid stack overflow. (XXX how will we preserve -- space properties with monad transformers?) many :: m a -> m [a] many p = go [] where go xs = do x <- p; go (x:xs) <|> return (reverse xs) -- | Run given parser as many times as possible, discarding -- results. Here for the same reason as 'many'. skipMany :: m a -> m () skipMany p = (p >> skipMany p) <|> return () class Parsely m => ParselyTry m where -- | If argument fails consuming input, act as if it wasn't consumed. (I.e. put -- it back) try :: m a -> m a class ParselyTry m => MonadParsec m tok pos | m -> tok, m -> pos where token :: (tok -> String) -> (tok -> pos) -> (tok -> Maybe a) -> m a tokenPrim :: (tok -> String) -> (pos -> tok -> [tok] -> pos) -> (tok -> Maybe a) -> m a tokens :: Eq tok => ([tok] -> String) -> (pos -> [tok] -> pos) -> [tok] -> m [tok] lookAhead :: m a -> m a instance Parsely (P.GenParser tok st) where () = P.label unexpected = P.unexpected many = P.many skipMany = P.skipMany instance ParselyTry (P.GenParser tok st) where try = P.try instance MonadParsec (P.GenParser tok st) tok P.SourcePos where token = P.token tokenPrim = P.tokenPrim tokens = P.tokens lookAhead = P.lookAhead