{-# LANGUAGE CPP #-} -------------------------------------------------------------------- -- | -- Copyright : © Edward Kmett 2010-2014, Johan Kiviniemi 2013 -- License : BSD3 -- Maintainer: Edward Kmett -- Stability : experimental -- Portability: non-portable -- -- A trivial, inefficient parser with no support for error reporting. -------------------------------------------------------------------- module Ersatz.Internal.Parser ( Parser , runParser , sepBy, sepBy1 , token, string , integer, natural , eof , satisfy ) where import Control.Applicative import Control.Monad.State import Data.Char (isDigit) #if __GLASGOW_HASKELL__ < 710 import Data.Traversable (traverse) #endif type Parser t a = StateT [t] [] a runParser :: Parser t a -> [t] -> [a] runParser = evalStateT sepBy :: Parser t a -> Parser t sep -> Parser t [a] sepBy p sep = sepBy1 p sep <|> pure [] sepBy1 :: Parser t a -> Parser t sep -> Parser t [a] sepBy1 p sep = (:) <$> p <*> many (sep *> p) token :: Eq t => t -> Parser t t token t = satisfy (== t) string :: Eq t => [t] -> Parser t [t] string = traverse token integer :: (Num i, Read i) => Parser Char i integer = negation <*> natural negation :: Num n => Parser Char (n -> n) negation = negate <$ token '-' <|> pure id natural :: Read i => Parser Char i natural = read <$> some (satisfy isDigit) eof :: Parser t () eof = do [] <- get return () satisfy :: (t -> Bool) -> Parser t t satisfy f = do (t:ts) <- get guard (f t) t <$ put ts