sexp-grammar-1.0.0: src/Language/SexpGrammar/Combinators.hs
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeOperators #-}
module Language.SexpGrammar.Combinators
( list
, vect
, el
, rest
, props
, (.:)
, (.:?)
, bool
, integer
, int
, real
, double
, string
, symbol
, keyword
, string'
, symbol'
, sym
, kw
, coproduct
, pair
, unpair
, swap
) where
import Prelude hiding ((.), id)
import Control.Category
import Data.Semigroup (sconcat)
import qualified Data.List.NonEmpty as NE
import Data.Scientific
import Data.StackPrism
import Data.Text (Text, pack, unpack)
import Data.InvertibleGrammar
import Data.InvertibleGrammar.TH
import Language.Sexp.Types
import Language.SexpGrammar.Base
----------------------------------------------------------------------
-- Sequence combinators
list :: Grammar SeqGrammar t t' -> Grammar SexpGrammar (Sexp :- t) t'
list = Inject . GList
vect :: Grammar SeqGrammar t t' -> Grammar SexpGrammar (Sexp :- t) t'
vect = Inject . GVect
el :: Grammar SexpGrammar (Sexp :- a) b -> Grammar SeqGrammar a b
el = Inject . GElem
rest :: Grammar SexpGrammar (Sexp :- a) (b :- a) -> Grammar SeqGrammar a ([b] :- a)
rest = Inject . GRest
props :: Grammar PropGrammar a b -> Grammar SeqGrammar a b
props = Inject . GProps
(.:) :: Kw -> Grammar SexpGrammar (Sexp :- t) (a :- t) -> Grammar PropGrammar t (a :- t)
(.:) name = Inject . GProp name
(.:?) :: Kw -> Grammar SexpGrammar (Sexp :- t) (a :- t) -> Grammar PropGrammar t (Maybe a :- t)
(.:?) name g = coproduct
[ $(grammarFor 'Just) . (name .: g)
, $(grammarFor 'Nothing)
]
----------------------------------------------------------------------
-- Atom combinators
bool :: SexpG Bool
bool = Inject . GAtom . Inject $ GBool
integer :: SexpG Integer
integer = Inject . GAtom . Inject $ GInt
int :: SexpG Int
int = iso fromIntegral fromIntegral . integer
real :: SexpG Scientific
real = Inject . GAtom . Inject $ GReal
double :: SexpG Double
double = iso toRealFloat fromFloatDigits . real
string :: SexpG Text
string = Inject . GAtom . Inject $ GString
string' :: SexpG String
string' = iso unpack pack . string
symbol :: SexpG Text
symbol = Inject . GAtom . Inject $ GSymbol
symbol' :: SexpG String
symbol' = iso unpack pack . symbol
keyword :: SexpG Kw
keyword = Inject . GAtom . Inject $ GKeyword
sym :: Text -> SexpG_
sym = Inject . GAtom . Inject . GSym
kw :: Kw -> SexpG_
kw = Inject . GAtom . Inject . GKw
----------------------------------------------------------------------
-- Special combinators
coproduct :: [Grammar g a b] -> Grammar g a b
coproduct = sconcat . NE.fromList
pair :: Grammar g (b :- a :- t) ((a, b) :- t)
unpair :: Grammar g ((a, b) :- t) (b :- a :- t)
(pair, unpair) = (Iso f g, Iso g f)
where
f = (\(b :- a :- t) -> (a, b) :- t)
g = (\((a, b) :- t) -> (b :- a :- t))
swap :: Grammar g (b :- a :- t) (a :- b :- t)
swap = Iso (\(b :- a :- t) -> a :- b :- t)
(\(a :- b :- t) -> b :- a :- t)