--------------------------------------------------------------------------------
-- | Module containing the elements used in a template.  A template is generally
-- just a list of these elements.
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
module Hakyll.Web.Template.Internal.Element
    ( TemplateKey (..)
    , TemplateExpr (..)
    , TemplateElement (..)
    , templateElems
    , parseTemplateElemsFile
    ) where


--------------------------------------------------------------------------------
import           Control.Applicative     ((<|>), (<*))
import           Control.Monad           (void)
import           Control.Arrow           (left)
import           Data.Binary             (Binary, get, getWord8, put, putWord8)
import           Data.List               (intercalate)
import           Data.Maybe              (isJust)
import           Data.Typeable           (Typeable)
import           GHC.Exts                (IsString (..))
import qualified Text.Parsec             as P
import qualified Text.Parsec.String      as P


--------------------------------------------------------------------------------
import           Hakyll.Core.Util.Parser


--------------------------------------------------------------------------------
newtype TemplateKey = TemplateKey String
    deriving (Get TemplateKey
[TemplateKey] -> Put
TemplateKey -> Put
(TemplateKey -> Put)
-> Get TemplateKey -> ([TemplateKey] -> Put) -> Binary TemplateKey
forall t. (t -> Put) -> Get t -> ([t] -> Put) -> Binary t
putList :: [TemplateKey] -> Put
$cputList :: [TemplateKey] -> Put
get :: Get TemplateKey
$cget :: Get TemplateKey
put :: TemplateKey -> Put
$cput :: TemplateKey -> Put
Binary, Int -> TemplateKey -> ShowS
[TemplateKey] -> ShowS
TemplateKey -> String
(Int -> TemplateKey -> ShowS)
-> (TemplateKey -> String)
-> ([TemplateKey] -> ShowS)
-> Show TemplateKey
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [TemplateKey] -> ShowS
$cshowList :: [TemplateKey] -> ShowS
show :: TemplateKey -> String
$cshow :: TemplateKey -> String
showsPrec :: Int -> TemplateKey -> ShowS
$cshowsPrec :: Int -> TemplateKey -> ShowS
Show, TemplateKey -> TemplateKey -> Bool
(TemplateKey -> TemplateKey -> Bool)
-> (TemplateKey -> TemplateKey -> Bool) -> Eq TemplateKey
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: TemplateKey -> TemplateKey -> Bool
$c/= :: TemplateKey -> TemplateKey -> Bool
== :: TemplateKey -> TemplateKey -> Bool
$c== :: TemplateKey -> TemplateKey -> Bool
Eq, Typeable)


--------------------------------------------------------------------------------
instance IsString TemplateKey where
    fromString :: String -> TemplateKey
fromString = String -> TemplateKey
TemplateKey


--------------------------------------------------------------------------------
-- | Elements of a template.
data TemplateElement
    = Chunk String
    | Expr TemplateExpr
    | Escaped
      -- expr, then, else
    | If TemplateExpr [TemplateElement] (Maybe [TemplateElement])
      -- expr, body, separator
    | For TemplateExpr [TemplateElement] (Maybe [TemplateElement])
      -- filename
    | Partial TemplateExpr
    | TrimL
    | TrimR
    deriving (Int -> TemplateElement -> ShowS
[TemplateElement] -> ShowS
TemplateElement -> String
(Int -> TemplateElement -> ShowS)
-> (TemplateElement -> String)
-> ([TemplateElement] -> ShowS)
-> Show TemplateElement
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [TemplateElement] -> ShowS
$cshowList :: [TemplateElement] -> ShowS
show :: TemplateElement -> String
$cshow :: TemplateElement -> String
showsPrec :: Int -> TemplateElement -> ShowS
$cshowsPrec :: Int -> TemplateElement -> ShowS
Show, TemplateElement -> TemplateElement -> Bool
(TemplateElement -> TemplateElement -> Bool)
-> (TemplateElement -> TemplateElement -> Bool)
-> Eq TemplateElement
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: TemplateElement -> TemplateElement -> Bool
$c/= :: TemplateElement -> TemplateElement -> Bool
== :: TemplateElement -> TemplateElement -> Bool
$c== :: TemplateElement -> TemplateElement -> Bool
Eq, Typeable)


--------------------------------------------------------------------------------
instance Binary TemplateElement where
    put :: TemplateElement -> Put
put (Chunk String
string) = Word8 -> Put
putWord8 Word8
0 Put -> Put -> Put
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> String -> Put
forall t. Binary t => t -> Put
put String
string
    put (Expr TemplateExpr
e)       = Word8 -> Put
putWord8 Word8
1 Put -> Put -> Put
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> TemplateExpr -> Put
forall t. Binary t => t -> Put
put TemplateExpr
e
    put  TemplateElement
Escaped       = Word8 -> Put
putWord8 Word8
2
    put (If TemplateExpr
e [TemplateElement]
t Maybe [TemplateElement]
f)     = Word8 -> Put
putWord8 Word8
3 Put -> Put -> Put
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> TemplateExpr -> Put
forall t. Binary t => t -> Put
put TemplateExpr
e Put -> Put -> Put
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> [TemplateElement] -> Put
forall t. Binary t => t -> Put
put [TemplateElement]
t Put -> Put -> Put
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Maybe [TemplateElement] -> Put
forall t. Binary t => t -> Put
put Maybe [TemplateElement]
f
    put (For TemplateExpr
e [TemplateElement]
b Maybe [TemplateElement]
s)    = Word8 -> Put
putWord8 Word8
4 Put -> Put -> Put
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> TemplateExpr -> Put
forall t. Binary t => t -> Put
put TemplateExpr
e Put -> Put -> Put
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> [TemplateElement] -> Put
forall t. Binary t => t -> Put
put [TemplateElement]
b Put -> Put -> Put
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Maybe [TemplateElement] -> Put
forall t. Binary t => t -> Put
put Maybe [TemplateElement]
s
    put (Partial TemplateExpr
e)    = Word8 -> Put
putWord8 Word8
5 Put -> Put -> Put
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> TemplateExpr -> Put
forall t. Binary t => t -> Put
put TemplateExpr
e
    put  TemplateElement
TrimL         = Word8 -> Put
putWord8 Word8
6
    put  TemplateElement
TrimR         = Word8 -> Put
putWord8 Word8
7

    get :: Get TemplateElement
get = Get Word8
getWord8 Get Word8 -> (Word8 -> Get TemplateElement) -> Get TemplateElement
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \Word8
tag -> case Word8
tag of
        Word8
0 -> String -> TemplateElement
Chunk (String -> TemplateElement) -> Get String -> Get TemplateElement
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Get String
forall t. Binary t => Get t
get
        Word8
1 -> TemplateExpr -> TemplateElement
Expr (TemplateExpr -> TemplateElement)
-> Get TemplateExpr -> Get TemplateElement
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Get TemplateExpr
forall t. Binary t => Get t
get
        Word8
2 -> TemplateElement -> Get TemplateElement
forall (f :: * -> *) a. Applicative f => a -> f a
pure TemplateElement
Escaped
        Word8
3 -> TemplateExpr
-> [TemplateElement] -> Maybe [TemplateElement] -> TemplateElement
If (TemplateExpr
 -> [TemplateElement] -> Maybe [TemplateElement] -> TemplateElement)
-> Get TemplateExpr
-> Get
     ([TemplateElement] -> Maybe [TemplateElement] -> TemplateElement)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Get TemplateExpr
forall t. Binary t => Get t
get Get
  ([TemplateElement] -> Maybe [TemplateElement] -> TemplateElement)
-> Get [TemplateElement]
-> Get (Maybe [TemplateElement] -> TemplateElement)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Get [TemplateElement]
forall t. Binary t => Get t
get Get (Maybe [TemplateElement] -> TemplateElement)
-> Get (Maybe [TemplateElement]) -> Get TemplateElement
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Get (Maybe [TemplateElement])
forall t. Binary t => Get t
get
        Word8
4 -> TemplateExpr
-> [TemplateElement] -> Maybe [TemplateElement] -> TemplateElement
For (TemplateExpr
 -> [TemplateElement] -> Maybe [TemplateElement] -> TemplateElement)
-> Get TemplateExpr
-> Get
     ([TemplateElement] -> Maybe [TemplateElement] -> TemplateElement)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Get TemplateExpr
forall t. Binary t => Get t
get Get
  ([TemplateElement] -> Maybe [TemplateElement] -> TemplateElement)
-> Get [TemplateElement]
-> Get (Maybe [TemplateElement] -> TemplateElement)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Get [TemplateElement]
forall t. Binary t => Get t
get Get (Maybe [TemplateElement] -> TemplateElement)
-> Get (Maybe [TemplateElement]) -> Get TemplateElement
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Get (Maybe [TemplateElement])
forall t. Binary t => Get t
get
        Word8
5 -> TemplateExpr -> TemplateElement
Partial (TemplateExpr -> TemplateElement)
-> Get TemplateExpr -> Get TemplateElement
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Get TemplateExpr
forall t. Binary t => Get t
get
        Word8
6 -> TemplateElement -> Get TemplateElement
forall (f :: * -> *) a. Applicative f => a -> f a
pure TemplateElement
TrimL
        Word8
7 -> TemplateElement -> Get TemplateElement
forall (f :: * -> *) a. Applicative f => a -> f a
pure TemplateElement
TrimR
        Word8
_ -> String -> Get TemplateElement
forall a. HasCallStack => String -> a
error String
"Hakyll.Web.Template.Internal: Error reading cached template"


--------------------------------------------------------------------------------
-- | Expression in a template
data TemplateExpr
    = Ident TemplateKey
    | Call TemplateKey [TemplateExpr]
    | StringLiteral String
    deriving (TemplateExpr -> TemplateExpr -> Bool
(TemplateExpr -> TemplateExpr -> Bool)
-> (TemplateExpr -> TemplateExpr -> Bool) -> Eq TemplateExpr
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: TemplateExpr -> TemplateExpr -> Bool
$c/= :: TemplateExpr -> TemplateExpr -> Bool
== :: TemplateExpr -> TemplateExpr -> Bool
$c== :: TemplateExpr -> TemplateExpr -> Bool
Eq, Typeable)


--------------------------------------------------------------------------------
instance Show TemplateExpr where
    show :: TemplateExpr -> String
show (Ident (TemplateKey String
k))   = String
k
    show (Call (TemplateKey String
k) [TemplateExpr]
as) =
        String
k String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"(" String -> ShowS
forall a. [a] -> [a] -> [a]
++ String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
intercalate String
", " ((TemplateExpr -> String) -> [TemplateExpr] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map TemplateExpr -> String
forall a. Show a => a -> String
show [TemplateExpr]
as) String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
")"
    show (StringLiteral String
s)         = ShowS
forall a. Show a => a -> String
show String
s


--------------------------------------------------------------------------------
instance Binary TemplateExpr where
    put :: TemplateExpr -> Put
put (Ident TemplateKey
k)         = Word8 -> Put
putWord8 Word8
0 Put -> Put -> Put
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> TemplateKey -> Put
forall t. Binary t => t -> Put
put TemplateKey
k
    put (Call TemplateKey
k [TemplateExpr]
as)       = Word8 -> Put
putWord8 Word8
1 Put -> Put -> Put
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> TemplateKey -> Put
forall t. Binary t => t -> Put
put TemplateKey
k Put -> Put -> Put
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> [TemplateExpr] -> Put
forall t. Binary t => t -> Put
put [TemplateExpr]
as
    put (StringLiteral String
s) = Word8 -> Put
putWord8 Word8
2 Put -> Put -> Put
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> String -> Put
forall t. Binary t => t -> Put
put String
s

    get :: Get TemplateExpr
get = Get Word8
getWord8 Get Word8 -> (Word8 -> Get TemplateExpr) -> Get TemplateExpr
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \Word8
tag -> case Word8
tag of
        Word8
0 -> TemplateKey -> TemplateExpr
Ident         (TemplateKey -> TemplateExpr)
-> Get TemplateKey -> Get TemplateExpr
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Get TemplateKey
forall t. Binary t => Get t
get
        Word8
1 -> TemplateKey -> [TemplateExpr] -> TemplateExpr
Call          (TemplateKey -> [TemplateExpr] -> TemplateExpr)
-> Get TemplateKey -> Get ([TemplateExpr] -> TemplateExpr)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Get TemplateKey
forall t. Binary t => Get t
get Get ([TemplateExpr] -> TemplateExpr)
-> Get [TemplateExpr] -> Get TemplateExpr
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Get [TemplateExpr]
forall t. Binary t => Get t
get
        Word8
2 -> String -> TemplateExpr
StringLiteral (String -> TemplateExpr) -> Get String -> Get TemplateExpr
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Get String
forall t. Binary t => Get t
get
        Word8
_ -> String -> Get TemplateExpr
forall a. HasCallStack => String -> a
error String
"Hakyll.Web.Template.Internal: Error reading cached template"

--------------------------------------------------------------------------------
parseTemplateElemsFile :: FilePath -> String -> Either String [TemplateElement]
parseTemplateElemsFile :: String -> String -> Either String [TemplateElement]
parseTemplateElemsFile String
file = (ParseError -> String)
-> Either ParseError [TemplateElement]
-> Either String [TemplateElement]
forall (a :: * -> * -> *) b c d.
ArrowChoice a =>
a b c -> a (Either b d) (Either c d)
left (\ParseError
e -> String
"Cannot parse template " String -> ShowS
forall a. [a] -> [a] -> [a]
++ ParseError -> String
forall a. Show a => a -> String
show ParseError
e)
                            (Either ParseError [TemplateElement]
 -> Either String [TemplateElement])
-> (String -> Either ParseError [TemplateElement])
-> String
-> Either String [TemplateElement]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Parsec String () [TemplateElement]
-> String -> String -> Either ParseError [TemplateElement]
forall s t a.
Stream s Identity t =>
Parsec s () a -> String -> s -> Either ParseError a
P.parse (Parsec String () [TemplateElement]
templateElems Parsec String () [TemplateElement]
-> ParsecT String () Identity ()
-> Parsec String () [TemplateElement]
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* ParsecT String () Identity ()
forall s (m :: * -> *) t u.
(Stream s m t, Show t) =>
ParsecT s u m ()
P.eof) String
file


--------------------------------------------------------------------------------
templateElems :: P.Parser [TemplateElement]
templateElems :: Parsec String () [TemplateElement]
templateElems = [[TemplateElement]] -> [TemplateElement]
forall a. Monoid a => [a] -> a
mconcat ([[TemplateElement]] -> [TemplateElement])
-> ParsecT String () Identity [[TemplateElement]]
-> Parsec String () [TemplateElement]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parsec String () [TemplateElement]
-> ParsecT String () Identity [[TemplateElement]]
forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m [a]
P.many ([Parsec String () [TemplateElement]]
-> Parsec String () [TemplateElement]
forall s (m :: * -> *) t u a.
Stream s m t =>
[ParsecT s u m a] -> ParsecT s u m a
P.choice [ ParsecT String () Identity TemplateElement
-> Parsec String () [TemplateElement]
forall a.
ParsecT String () Identity a -> ParsecT String () Identity [a]
lift ParsecT String () Identity TemplateElement
chunk
                                             , ParsecT String () Identity TemplateElement
-> Parsec String () [TemplateElement]
forall a.
ParsecT String () Identity a -> ParsecT String () Identity [a]
lift ParsecT String () Identity TemplateElement
escaped
                                             , Parsec String () [TemplateElement]
conditional
                                             , Parsec String () [TemplateElement]
for
                                             , Parsec String () [TemplateElement]
partial
                                             , Parsec String () [TemplateElement]
expr
                                             ])
    where lift :: ParsecT String () Identity a -> ParsecT String () Identity [a]
lift = (a -> [a])
-> ParsecT String () Identity a -> ParsecT String () Identity [a]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (a -> [a] -> [a]
forall a. a -> [a] -> [a]
:[])


--------------------------------------------------------------------------------
chunk :: P.Parser TemplateElement
chunk :: ParsecT String () Identity TemplateElement
chunk = String -> TemplateElement
Chunk (String -> TemplateElement)
-> ParsecT String () Identity String
-> ParsecT String () Identity TemplateElement
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ParsecT String () Identity Char
-> ParsecT String () Identity String
forall s (m :: * -> *) t u a.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m [a]
P.many1 (String -> ParsecT String () Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m Char
P.noneOf String
"$")


--------------------------------------------------------------------------------
expr :: P.Parser [TemplateElement]
expr :: Parsec String () [TemplateElement]
expr = Parsec String () [TemplateElement]
-> Parsec String () [TemplateElement]
forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
P.try (Parsec String () [TemplateElement]
 -> Parsec String () [TemplateElement])
-> Parsec String () [TemplateElement]
-> Parsec String () [TemplateElement]
forall a b. (a -> b) -> a -> b
$ do
    Bool
trimLExpr <- Parser Bool
trimOpen
    TemplateExpr
e <- Parser TemplateExpr
expr'
    Bool
trimRExpr <- Parser Bool
trimClose
    [TemplateElement] -> Parsec String () [TemplateElement]
forall (m :: * -> *) a. Monad m => a -> m a
return ([TemplateElement] -> Parsec String () [TemplateElement])
-> [TemplateElement] -> Parsec String () [TemplateElement]
forall a b. (a -> b) -> a -> b
$ [TemplateElement
TrimL | Bool
trimLExpr] [TemplateElement] -> [TemplateElement] -> [TemplateElement]
forall a. [a] -> [a] -> [a]
++ [TemplateExpr -> TemplateElement
Expr TemplateExpr
e] [TemplateElement] -> [TemplateElement] -> [TemplateElement]
forall a. [a] -> [a] -> [a]
++ [TemplateElement
TrimR | Bool
trimRExpr]


--------------------------------------------------------------------------------
expr' :: P.Parser TemplateExpr
expr' :: Parser TemplateExpr
expr' = Parser TemplateExpr
stringLiteral Parser TemplateExpr -> Parser TemplateExpr -> Parser TemplateExpr
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser TemplateExpr
call Parser TemplateExpr -> Parser TemplateExpr -> Parser TemplateExpr
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser TemplateExpr
ident


--------------------------------------------------------------------------------
escaped :: P.Parser TemplateElement
escaped :: ParsecT String () Identity TemplateElement
escaped = TemplateElement
Escaped TemplateElement
-> ParsecT String () Identity String
-> ParsecT String () Identity TemplateElement
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ ParsecT String () Identity String
-> ParsecT String () Identity String
forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
P.try (String -> ParsecT String () Identity String
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m String
P.string String
"$$")


--------------------------------------------------------------------------------
trimOpen :: P.Parser Bool
trimOpen :: Parser Bool
trimOpen = do
    ParsecT String () Identity Char -> ParsecT String () Identity ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (ParsecT String () Identity Char -> ParsecT String () Identity ())
-> ParsecT String () Identity Char -> ParsecT String () Identity ()
forall a b. (a -> b) -> a -> b
$ Char -> ParsecT String () Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
P.char Char
'$'
    Maybe Char
trimLIf <- ParsecT String () Identity Char
-> ParsecT String () Identity (Maybe Char)
forall s (m :: * -> *) t u a.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m (Maybe a)
P.optionMaybe (ParsecT String () Identity Char
 -> ParsecT String () Identity (Maybe Char))
-> ParsecT String () Identity Char
-> ParsecT String () Identity (Maybe Char)
forall a b. (a -> b) -> a -> b
$ ParsecT String () Identity Char -> ParsecT String () Identity Char
forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
P.try (Char -> ParsecT String () Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
P.char Char
'-')
    Bool -> Parser Bool
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Bool -> Parser Bool) -> Bool -> Parser Bool
forall a b. (a -> b) -> a -> b
$ Maybe Char -> Bool
forall a. Maybe a -> Bool
isJust Maybe Char
trimLIf


--------------------------------------------------------------------------------
trimClose :: P.Parser Bool
trimClose :: Parser Bool
trimClose = do
    Maybe Char
trimIfR <- ParsecT String () Identity Char
-> ParsecT String () Identity (Maybe Char)
forall s (m :: * -> *) t u a.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m (Maybe a)
P.optionMaybe (ParsecT String () Identity Char
 -> ParsecT String () Identity (Maybe Char))
-> ParsecT String () Identity Char
-> ParsecT String () Identity (Maybe Char)
forall a b. (a -> b) -> a -> b
$ (Char -> ParsecT String () Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
P.char Char
'-')
    ParsecT String () Identity Char -> ParsecT String () Identity ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (ParsecT String () Identity Char -> ParsecT String () Identity ())
-> ParsecT String () Identity Char -> ParsecT String () Identity ()
forall a b. (a -> b) -> a -> b
$ Char -> ParsecT String () Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
P.char Char
'$'
    Bool -> Parser Bool
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Bool -> Parser Bool) -> Bool -> Parser Bool
forall a b. (a -> b) -> a -> b
$ Maybe Char -> Bool
forall a. Maybe a -> Bool
isJust Maybe Char
trimIfR


--------------------------------------------------------------------------------
conditional :: P.Parser [TemplateElement]
conditional :: Parsec String () [TemplateElement]
conditional = Parsec String () [TemplateElement]
-> Parsec String () [TemplateElement]
forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
P.try (Parsec String () [TemplateElement]
 -> Parsec String () [TemplateElement])
-> Parsec String () [TemplateElement]
-> Parsec String () [TemplateElement]
forall a b. (a -> b) -> a -> b
$ do
    -- if
    Bool
trimLIf <- Parser Bool
trimOpen
    ParsecT String () Identity String -> ParsecT String () Identity ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (ParsecT String () Identity String
 -> ParsecT String () Identity ())
-> ParsecT String () Identity String
-> ParsecT String () Identity ()
forall a b. (a -> b) -> a -> b
$ String -> ParsecT String () Identity String
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m String
P.string String
"if("
    TemplateExpr
e <- Parser TemplateExpr
expr'
    ParsecT String () Identity Char -> ParsecT String () Identity ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (ParsecT String () Identity Char -> ParsecT String () Identity ())
-> ParsecT String () Identity Char -> ParsecT String () Identity ()
forall a b. (a -> b) -> a -> b
$ Char -> ParsecT String () Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
P.char Char
')'
    Bool
trimRIf <- Parser Bool
trimClose
    -- then
    [TemplateElement]
thenBranch <- Parsec String () [TemplateElement]
templateElems
    -- else
    Maybe (Bool, [TemplateElement], Bool)
elseParse <- String -> Parser (Maybe (Bool, [TemplateElement], Bool))
opt String
"else"
    -- endif
    Bool
trimLEnd <- Parser Bool
trimOpen
    ParsecT String () Identity String -> ParsecT String () Identity ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (ParsecT String () Identity String
 -> ParsecT String () Identity ())
-> ParsecT String () Identity String
-> ParsecT String () Identity ()
forall a b. (a -> b) -> a -> b
$ String -> ParsecT String () Identity String
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m String
P.string String
"endif"
    Bool
trimREnd <- Parser Bool
trimClose

    -- As else is optional we need to sort out where any Trim_s need to go.
    let ([TemplateElement]
thenBody, Maybe [TemplateElement]
elseBody) = ([TemplateElement], Maybe [TemplateElement])
-> ((Bool, [TemplateElement], Bool)
    -> ([TemplateElement], Maybe [TemplateElement]))
-> Maybe (Bool, [TemplateElement], Bool)
-> ([TemplateElement], Maybe [TemplateElement])
forall b a. b -> (a -> b) -> Maybe a -> b
maybe ([TemplateElement]
thenNoElse, Maybe [TemplateElement]
forall a. Maybe a
Nothing) (Bool, [TemplateElement], Bool)
-> ([TemplateElement], Maybe [TemplateElement])
thenElse Maybe (Bool, [TemplateElement], Bool)
elseParse
            where thenNoElse :: [TemplateElement]
thenNoElse =
                      [TemplateElement
TrimR | Bool
trimRIf] [TemplateElement] -> [TemplateElement] -> [TemplateElement]
forall a. [a] -> [a] -> [a]
++ [TemplateElement]
thenBranch [TemplateElement] -> [TemplateElement] -> [TemplateElement]
forall a. [a] -> [a] -> [a]
++ [TemplateElement
TrimL | Bool
trimLEnd]

                  thenElse :: (Bool, [TemplateElement], Bool)
-> ([TemplateElement], Maybe [TemplateElement])
thenElse (Bool
trimLElse, [TemplateElement]
elseBranch, Bool
trimRElse) = ([TemplateElement]
thenB, Maybe [TemplateElement]
elseB)
                      where thenB :: [TemplateElement]
thenB = [TemplateElement
TrimR | Bool
trimRIf]
                                 [TemplateElement] -> [TemplateElement] -> [TemplateElement]
forall a. [a] -> [a] -> [a]
++ [TemplateElement]
thenBranch
                                 [TemplateElement] -> [TemplateElement] -> [TemplateElement]
forall a. [a] -> [a] -> [a]
++ [TemplateElement
TrimL | Bool
trimLElse]

                            elseB :: Maybe [TemplateElement]
elseB = [TemplateElement] -> Maybe [TemplateElement]
forall a. a -> Maybe a
Just ([TemplateElement] -> Maybe [TemplateElement])
-> [TemplateElement] -> Maybe [TemplateElement]
forall a b. (a -> b) -> a -> b
$ [TemplateElement
TrimR | Bool
trimRElse]
                                        [TemplateElement] -> [TemplateElement] -> [TemplateElement]
forall a. [a] -> [a] -> [a]
++ [TemplateElement]
elseBranch
                                        [TemplateElement] -> [TemplateElement] -> [TemplateElement]
forall a. [a] -> [a] -> [a]
++ [TemplateElement
TrimL | Bool
trimLEnd]

    [TemplateElement] -> Parsec String () [TemplateElement]
forall (f :: * -> *) a. Applicative f => a -> f a
pure ([TemplateElement] -> Parsec String () [TemplateElement])
-> [TemplateElement] -> Parsec String () [TemplateElement]
forall a b. (a -> b) -> a -> b
$ [TemplateElement
TrimL | Bool
trimLIf] [TemplateElement] -> [TemplateElement] -> [TemplateElement]
forall a. [a] -> [a] -> [a]
++ [TemplateExpr
-> [TemplateElement] -> Maybe [TemplateElement] -> TemplateElement
If TemplateExpr
e [TemplateElement]
thenBody Maybe [TemplateElement]
elseBody] [TemplateElement] -> [TemplateElement] -> [TemplateElement]
forall a. [a] -> [a] -> [a]
++ [TemplateElement
TrimR | Bool
trimREnd]


--------------------------------------------------------------------------------
for :: P.Parser [TemplateElement]
for :: Parsec String () [TemplateElement]
for = Parsec String () [TemplateElement]
-> Parsec String () [TemplateElement]
forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
P.try (Parsec String () [TemplateElement]
 -> Parsec String () [TemplateElement])
-> Parsec String () [TemplateElement]
-> Parsec String () [TemplateElement]
forall a b. (a -> b) -> a -> b
$ do
    -- for
    Bool
trimLFor <- Parser Bool
trimOpen
    ParsecT String () Identity String -> ParsecT String () Identity ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (ParsecT String () Identity String
 -> ParsecT String () Identity ())
-> ParsecT String () Identity String
-> ParsecT String () Identity ()
forall a b. (a -> b) -> a -> b
$ String -> ParsecT String () Identity String
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m String
P.string String
"for("
    TemplateExpr
e <- Parser TemplateExpr
expr'
    ParsecT String () Identity Char -> ParsecT String () Identity ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (ParsecT String () Identity Char -> ParsecT String () Identity ())
-> ParsecT String () Identity Char -> ParsecT String () Identity ()
forall a b. (a -> b) -> a -> b
$ Char -> ParsecT String () Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
P.char Char
')'
    Bool
trimRFor <- Parser Bool
trimClose
    -- body
    [TemplateElement]
bodyBranch <- Parsec String () [TemplateElement]
templateElems
    -- sep
    Maybe (Bool, [TemplateElement], Bool)
sepParse <- String -> Parser (Maybe (Bool, [TemplateElement], Bool))
opt String
"sep"
    -- endfor
    Bool
trimLEnd <- Parser Bool
trimOpen
    ParsecT String () Identity String -> ParsecT String () Identity ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (ParsecT String () Identity String
 -> ParsecT String () Identity ())
-> ParsecT String () Identity String
-> ParsecT String () Identity ()
forall a b. (a -> b) -> a -> b
$ String -> ParsecT String () Identity String
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m String
P.string String
"endfor"
    Bool
trimREnd <- Parser Bool
trimClose

    -- As sep is optional we need to sort out where any Trim_s need to go.
    let ([TemplateElement]
forBody, Maybe [TemplateElement]
sepBody) = ([TemplateElement], Maybe [TemplateElement])
-> ((Bool, [TemplateElement], Bool)
    -> ([TemplateElement], Maybe [TemplateElement]))
-> Maybe (Bool, [TemplateElement], Bool)
-> ([TemplateElement], Maybe [TemplateElement])
forall b a. b -> (a -> b) -> Maybe a -> b
maybe ([TemplateElement]
forNoSep, Maybe [TemplateElement]
forall a. Maybe a
Nothing) (Bool, [TemplateElement], Bool)
-> ([TemplateElement], Maybe [TemplateElement])
forSep Maybe (Bool, [TemplateElement], Bool)
sepParse
            where forNoSep :: [TemplateElement]
forNoSep =
                      [TemplateElement
TrimR | Bool
trimRFor] [TemplateElement] -> [TemplateElement] -> [TemplateElement]
forall a. [a] -> [a] -> [a]
++ [TemplateElement]
bodyBranch [TemplateElement] -> [TemplateElement] -> [TemplateElement]
forall a. [a] -> [a] -> [a]
++ [TemplateElement
TrimL | Bool
trimLEnd]

                  forSep :: (Bool, [TemplateElement], Bool)
-> ([TemplateElement], Maybe [TemplateElement])
forSep (Bool
trimLSep, [TemplateElement]
sepBranch, Bool
trimRSep) = ([TemplateElement]
forB, Maybe [TemplateElement]
sepB)
                      where forB :: [TemplateElement]
forB = [TemplateElement
TrimR | Bool
trimRFor]
                                [TemplateElement] -> [TemplateElement] -> [TemplateElement]
forall a. [a] -> [a] -> [a]
++ [TemplateElement]
bodyBranch
                                [TemplateElement] -> [TemplateElement] -> [TemplateElement]
forall a. [a] -> [a] -> [a]
++ [TemplateElement
TrimL | Bool
trimLSep]

                            sepB :: Maybe [TemplateElement]
sepB = [TemplateElement] -> Maybe [TemplateElement]
forall a. a -> Maybe a
Just ([TemplateElement] -> Maybe [TemplateElement])
-> [TemplateElement] -> Maybe [TemplateElement]
forall a b. (a -> b) -> a -> b
$ [TemplateElement
TrimR | Bool
trimRSep]
                                       [TemplateElement] -> [TemplateElement] -> [TemplateElement]
forall a. [a] -> [a] -> [a]
++ [TemplateElement]
sepBranch
                                       [TemplateElement] -> [TemplateElement] -> [TemplateElement]
forall a. [a] -> [a] -> [a]
++ [TemplateElement
TrimL | Bool
trimLEnd]

    [TemplateElement] -> Parsec String () [TemplateElement]
forall (f :: * -> *) a. Applicative f => a -> f a
pure ([TemplateElement] -> Parsec String () [TemplateElement])
-> [TemplateElement] -> Parsec String () [TemplateElement]
forall a b. (a -> b) -> a -> b
$ [TemplateElement
TrimL | Bool
trimLFor] [TemplateElement] -> [TemplateElement] -> [TemplateElement]
forall a. [a] -> [a] -> [a]
++ [TemplateExpr
-> [TemplateElement] -> Maybe [TemplateElement] -> TemplateElement
For TemplateExpr
e [TemplateElement]
forBody Maybe [TemplateElement]
sepBody] [TemplateElement] -> [TemplateElement] -> [TemplateElement]
forall a. [a] -> [a] -> [a]
++ [TemplateElement
TrimR | Bool
trimREnd]


--------------------------------------------------------------------------------
partial :: P.Parser [TemplateElement]
partial :: Parsec String () [TemplateElement]
partial = Parsec String () [TemplateElement]
-> Parsec String () [TemplateElement]
forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
P.try (Parsec String () [TemplateElement]
 -> Parsec String () [TemplateElement])
-> Parsec String () [TemplateElement]
-> Parsec String () [TemplateElement]
forall a b. (a -> b) -> a -> b
$ do
    Bool
trimLPart <- Parser Bool
trimOpen
    ParsecT String () Identity String -> ParsecT String () Identity ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (ParsecT String () Identity String
 -> ParsecT String () Identity ())
-> ParsecT String () Identity String
-> ParsecT String () Identity ()
forall a b. (a -> b) -> a -> b
$ String -> ParsecT String () Identity String
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m String
P.string String
"partial("
    TemplateExpr
e <- Parser TemplateExpr
expr'
    ParsecT String () Identity Char -> ParsecT String () Identity ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (ParsecT String () Identity Char -> ParsecT String () Identity ())
-> ParsecT String () Identity Char -> ParsecT String () Identity ()
forall a b. (a -> b) -> a -> b
$ Char -> ParsecT String () Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
P.char Char
')'
    Bool
trimRPart <- Parser Bool
trimClose

    [TemplateElement] -> Parsec String () [TemplateElement]
forall (f :: * -> *) a. Applicative f => a -> f a
pure ([TemplateElement] -> Parsec String () [TemplateElement])
-> [TemplateElement] -> Parsec String () [TemplateElement]
forall a b. (a -> b) -> a -> b
$ [TemplateElement
TrimL | Bool
trimLPart] [TemplateElement] -> [TemplateElement] -> [TemplateElement]
forall a. [a] -> [a] -> [a]
++ [TemplateExpr -> TemplateElement
Partial TemplateExpr
e] [TemplateElement] -> [TemplateElement] -> [TemplateElement]
forall a. [a] -> [a] -> [a]
++ [TemplateElement
TrimR | Bool
trimRPart]


--------------------------------------------------------------------------------
ident :: P.Parser TemplateExpr
ident :: Parser TemplateExpr
ident = Parser TemplateExpr -> Parser TemplateExpr
forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
P.try (Parser TemplateExpr -> Parser TemplateExpr)
-> Parser TemplateExpr -> Parser TemplateExpr
forall a b. (a -> b) -> a -> b
$ TemplateKey -> TemplateExpr
Ident (TemplateKey -> TemplateExpr)
-> ParsecT String () Identity TemplateKey -> Parser TemplateExpr
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ParsecT String () Identity TemplateKey
key


--------------------------------------------------------------------------------
call :: P.Parser TemplateExpr
call :: Parser TemplateExpr
call = Parser TemplateExpr -> Parser TemplateExpr
forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
P.try (Parser TemplateExpr -> Parser TemplateExpr)
-> Parser TemplateExpr -> Parser TemplateExpr
forall a b. (a -> b) -> a -> b
$ do
    TemplateKey
f <- ParsecT String () Identity TemplateKey
key
    ParsecT String () Identity Char -> ParsecT String () Identity ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (ParsecT String () Identity Char -> ParsecT String () Identity ())
-> ParsecT String () Identity Char -> ParsecT String () Identity ()
forall a b. (a -> b) -> a -> b
$ Char -> ParsecT String () Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
P.char Char
'('
    ParsecT String () Identity ()
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m ()
P.spaces
    [TemplateExpr]
as <- Parser TemplateExpr
-> ParsecT String () Identity ()
-> ParsecT String () Identity [TemplateExpr]
forall s (m :: * -> *) t u a sep.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m sep -> ParsecT s u m [a]
P.sepBy Parser TemplateExpr
expr' (ParsecT String () Identity ()
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m ()
P.spaces ParsecT String () Identity ()
-> ParsecT String () Identity Char
-> ParsecT String () Identity Char
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Char -> ParsecT String () Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
P.char Char
',' ParsecT String () Identity Char
-> ParsecT String () Identity () -> ParsecT String () Identity ()
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> ParsecT String () Identity ()
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m ()
P.spaces)
    ParsecT String () Identity ()
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m ()
P.spaces
    ParsecT String () Identity Char -> ParsecT String () Identity ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (ParsecT String () Identity Char -> ParsecT String () Identity ())
-> ParsecT String () Identity Char -> ParsecT String () Identity ()
forall a b. (a -> b) -> a -> b
$ Char -> ParsecT String () Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
P.char Char
')'
    TemplateExpr -> Parser TemplateExpr
forall (m :: * -> *) a. Monad m => a -> m a
return (TemplateExpr -> Parser TemplateExpr)
-> TemplateExpr -> Parser TemplateExpr
forall a b. (a -> b) -> a -> b
$ TemplateKey -> [TemplateExpr] -> TemplateExpr
Call TemplateKey
f [TemplateExpr]
as


--------------------------------------------------------------------------------
stringLiteral :: P.Parser TemplateExpr
stringLiteral :: Parser TemplateExpr
stringLiteral = do
    ParsecT String () Identity Char -> ParsecT String () Identity ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (ParsecT String () Identity Char -> ParsecT String () Identity ())
-> ParsecT String () Identity Char -> ParsecT String () Identity ()
forall a b. (a -> b) -> a -> b
$ Char -> ParsecT String () Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
P.char Char
'\"'
    String
str <- ParsecT String () Identity Char
-> ParsecT String () Identity String
forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m [a]
P.many (ParsecT String () Identity Char
 -> ParsecT String () Identity String)
-> ParsecT String () Identity Char
-> ParsecT String () Identity String
forall a b. (a -> b) -> a -> b
$ do
        Char
x <- String -> ParsecT String () Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m Char
P.noneOf String
"\""
        if Char
x Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'\\' then ParsecT String () Identity Char
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m Char
P.anyChar else Char -> ParsecT String () Identity Char
forall (m :: * -> *) a. Monad m => a -> m a
return Char
x
    ParsecT String () Identity Char -> ParsecT String () Identity ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (ParsecT String () Identity Char -> ParsecT String () Identity ())
-> ParsecT String () Identity Char -> ParsecT String () Identity ()
forall a b. (a -> b) -> a -> b
$ Char -> ParsecT String () Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
P.char Char
'\"'
    TemplateExpr -> Parser TemplateExpr
forall (m :: * -> *) a. Monad m => a -> m a
return (TemplateExpr -> Parser TemplateExpr)
-> TemplateExpr -> Parser TemplateExpr
forall a b. (a -> b) -> a -> b
$ String -> TemplateExpr
StringLiteral String
str


--------------------------------------------------------------------------------
key :: P.Parser TemplateKey
key :: ParsecT String () Identity TemplateKey
key = String -> TemplateKey
TemplateKey (String -> TemplateKey)
-> ParsecT String () Identity String
-> ParsecT String () Identity TemplateKey
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ParsecT String () Identity String
metadataKey


--------------------------------------------------------------------------------
opt :: String -> P.Parser (Maybe (Bool, [TemplateElement], Bool))
opt :: String -> Parser (Maybe (Bool, [TemplateElement], Bool))
opt String
clause = ParsecT String () Identity (Bool, [TemplateElement], Bool)
-> Parser (Maybe (Bool, [TemplateElement], Bool))
forall s (m :: * -> *) t u a.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m (Maybe a)
P.optionMaybe (ParsecT String () Identity (Bool, [TemplateElement], Bool)
 -> Parser (Maybe (Bool, [TemplateElement], Bool)))
-> ParsecT String () Identity (Bool, [TemplateElement], Bool)
-> Parser (Maybe (Bool, [TemplateElement], Bool))
forall a b. (a -> b) -> a -> b
$ ParsecT String () Identity (Bool, [TemplateElement], Bool)
-> ParsecT String () Identity (Bool, [TemplateElement], Bool)
forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
P.try (ParsecT String () Identity (Bool, [TemplateElement], Bool)
 -> ParsecT String () Identity (Bool, [TemplateElement], Bool))
-> ParsecT String () Identity (Bool, [TemplateElement], Bool)
-> ParsecT String () Identity (Bool, [TemplateElement], Bool)
forall a b. (a -> b) -> a -> b
$ do
    Bool
trimL <- Parser Bool
trimOpen
    ParsecT String () Identity String -> ParsecT String () Identity ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (ParsecT String () Identity String
 -> ParsecT String () Identity ())
-> ParsecT String () Identity String
-> ParsecT String () Identity ()
forall a b. (a -> b) -> a -> b
$ String -> ParsecT String () Identity String
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m String
P.string String
clause
    Bool
trimR <- Parser Bool
trimClose
    [TemplateElement]
branch <- Parsec String () [TemplateElement]
templateElems
    (Bool, [TemplateElement], Bool)
-> ParsecT String () Identity (Bool, [TemplateElement], Bool)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Bool
trimL, [TemplateElement]
branch, Bool
trimR)