{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE DefaultSignatures #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE FunctionalDependencies #-} {- | Module : Data.Syntax Description : Abstract syntax description. Copyright : (c) Paweł Nowak License : MIT Maintainer : Paweł Nowak Stability : experimental Abstract syntax descriptions based on semi-isomorphisms. -} module Data.Syntax ( -- * Syntax. Syntax(..), -- * Common isomorphisms. packed ) where import Prelude hiding (take, takeWhile) import Control.Lens.Iso import Control.Lens.SemiIso import Data.MonoTraversable import Data.SemiIsoFunctor import Data.Sequences hiding (take, takeWhile) -- | An isomorphism between a sequence and a list of its elements. packed :: IsSequence seq => Iso' seq [Element seq] packed = iso otoList fromList -- | An abstract syntax description based on semi-isomorphisms. -- -- This class can be implemented by both parsers and printers (and maybe more?). -- -- The usual use is to write a polymorphic syntax description and instantiate it -- both as a parser and a printer. An example is available in the 'syntax-example' -- package. -- -- Methods of this class try to mimic "Data.Attoparsec.Text" interface. class ( SemiIsoAlternative syn , SemiIsoMonad syn , IsSequence seq , Eq seq , Eq (Element seq)) => Syntax syn seq | syn -> seq where -- | Any character. anyChar :: syn (Element seq) -- | A specific character. char :: Element seq -> syn () char c = exact c /$/ anyChar -- | Any character except the given one. notChar :: Element seq -> syn (Element seq) notChar c = bifiltered (/= c) /$/ anyChar -- | Any character satisfying a predicate. satisfy :: (Element seq -> Bool) -> syn (Element seq) satisfy p = bifiltered p /$/ anyChar -- | Transforms a character using a SemiIso and filters out values -- not satisfying the predicate. satisfyWith :: ASemiIso' a (Element seq) -> (a -> Bool) -> syn a satisfyWith ai p = bifiltered p . ai /$/ anyChar -- | A specific string. string :: seq -> syn () string s = exact s /$/ take (olength s) -- | A string of length @n@. take :: Int -> syn seq take n = packed /$/ sireplicate n anyChar -- | Maximal string which elements satisfy a predicate. takeWhile :: (Element seq -> Bool) -> syn seq takeWhile p = packed /$/ simany (satisfy p) -- | Maximal non-empty string which elements satisfy a predicate. takeWhile1 :: (Element seq -> Bool) -> syn seq takeWhile1 p = packed /$/ sisome (satisfy p) -- | Maximal string which elements do not satisfy a predicate. takeTill :: (Element seq -> Bool) -> syn seq takeTill p = takeWhile (not . p) -- | Maximal non-empty string which elements do not satisfy a predicate. takeTill1 :: (Element seq -> Bool) -> syn seq takeTill1 p = takeWhile1 (not . p) {-# MINIMAL anyChar #-}