{-# LANGUAGE OverloadedStrings #-}

-- |
-- Module      :  Text.Mustache.Parser
-- Copyright   :  © 2016–present Stack Builders
-- License     :  BSD 3 clause
--
-- Maintainer  :  Mark Karpov <markkarpov92@gmail.com>
-- Stability   :  experimental
-- Portability :  portable
--
-- Megaparsec parser for Mustache templates. You don't usually need to
-- import the module, because "Text.Mustache" re-exports everything you may
-- need, import that module instead.
module Text.Mustache.Parser
  ( parseMustache,
  )
where

import Control.Monad
import Control.Monad.State.Strict
import Data.Char (isSpace)
import Data.Maybe (catMaybes)
import Data.Text (Text, stripEnd)
import qualified Data.Text as T
import Data.Void
import Text.Megaparsec
import Text.Megaparsec.Char
import qualified Text.Megaparsec.Char.Lexer as L
import Text.Mustache.Type

----------------------------------------------------------------------------
-- Parser

-- | Parse a given Mustache template.
parseMustache ::
  -- | Location of the file to parse
  FilePath ->
  -- | File contents (Mustache template)
  Text ->
  -- | Parsed nodes or parse error
  Either (ParseErrorBundle Text Void) [Node]
parseMustache :: FilePath -> Text -> Either (ParseErrorBundle Text Void) [Node]
parseMustache =
  Parsec Void Text [Node]
-> FilePath -> Text -> Either (ParseErrorBundle Text Void) [Node]
forall e s a.
Parsec e s a -> FilePath -> s -> Either (ParseErrorBundle s e) a
parse (Parsec Void Text [Node]
 -> FilePath -> Text -> Either (ParseErrorBundle Text Void) [Node])
-> Parsec Void Text [Node]
-> FilePath
-> Text
-> Either (ParseErrorBundle Text Void) [Node]
forall a b. (a -> b) -> a -> b
$
    StateT St (Parsec Void Text) [Node]
-> St -> Parsec Void Text [Node]
forall (m :: * -> *) s a. Monad m => StateT s m a -> s -> m a
evalStateT (Parser () -> StateT St (Parsec Void Text) [Node]
pMustache Parser ()
forall e s (m :: * -> *). MonadParsec e s m => m ()
eof) (Text -> Text -> Int -> St
St Text
"{{" Text
"}}" Int
0)

pMustache :: Parser () -> Parser [Node]
pMustache :: Parser () -> StateT St (Parsec Void Text) [Node]
pMustache = ([Maybe Node] -> [Node])
-> StateT St (Parsec Void Text) [Maybe Node]
-> StateT St (Parsec Void Text) [Node]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap [Maybe Node] -> [Node]
forall a. [Maybe a] -> [a]
catMaybes (StateT St (Parsec Void Text) [Maybe Node]
 -> StateT St (Parsec Void Text) [Node])
-> (Parser () -> StateT St (Parsec Void Text) [Maybe Node])
-> Parser ()
-> StateT St (Parsec Void Text) [Node]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. StateT St (Parsec Void Text) (Maybe Node)
-> Parser () -> StateT St (Parsec Void Text) [Maybe Node]
forall (m :: * -> *) a end. MonadPlus m => m a -> m end -> m [a]
manyTill ([StateT St (Parsec Void Text) (Maybe Node)]
-> StateT St (Parsec Void Text) (Maybe Node)
forall (f :: * -> *) (m :: * -> *) a.
(Foldable f, Alternative m) =>
f (m a) -> m a
choice [StateT St (Parsec Void Text) (Maybe Node)]
alts)
  where
    alts :: [StateT St (Parsec Void Text) (Maybe Node)]
alts =
      [ Maybe Node
forall a. Maybe a
Nothing Maybe Node
-> Parser () -> StateT St (Parsec Void Text) (Maybe Node)
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ Parser () -> Parser ()
forall a. Parser a -> Parser a
withStandalone Parser ()
pComment,
        Node -> Maybe Node
forall a. a -> Maybe a
Just (Node -> Maybe Node)
-> StateT St (Parsec Void Text) Node
-> StateT St (Parsec Void Text) (Maybe Node)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Text
-> (Key -> [Node] -> Node) -> StateT St (Parsec Void Text) Node
pSection Text
"#" Key -> [Node] -> Node
Section,
        Node -> Maybe Node
forall a. a -> Maybe a
Just (Node -> Maybe Node)
-> StateT St (Parsec Void Text) Node
-> StateT St (Parsec Void Text) (Maybe Node)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Text
-> (Key -> [Node] -> Node) -> StateT St (Parsec Void Text) Node
pSection Text
"^" Key -> [Node] -> Node
InvertedSection,
        Node -> Maybe Node
forall a. a -> Maybe a
Just (Node -> Maybe Node)
-> StateT St (Parsec Void Text) Node
-> StateT St (Parsec Void Text) (Maybe Node)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> StateT St (Parsec Void Text) Node
-> StateT St (Parsec Void Text) Node
forall a. Parser a -> Parser a
pStandalone ((Pos -> Maybe Pos) -> StateT St (Parsec Void Text) Node
pPartial Pos -> Maybe Pos
forall a. a -> Maybe a
Just),
        Node -> Maybe Node
forall a. a -> Maybe a
Just (Node -> Maybe Node)
-> StateT St (Parsec Void Text) Node
-> StateT St (Parsec Void Text) (Maybe Node)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Pos -> Maybe Pos) -> StateT St (Parsec Void Text) Node
pPartial (Maybe Pos -> Pos -> Maybe Pos
forall a b. a -> b -> a
const Maybe Pos
forall a. Maybe a
Nothing),
        Maybe Node
forall a. Maybe a
Nothing Maybe Node
-> Parser () -> StateT St (Parsec Void Text) (Maybe Node)
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ Parser () -> Parser ()
forall a. Parser a -> Parser a
withStandalone Parser ()
pSetDelimiters,
        Node -> Maybe Node
forall a. a -> Maybe a
Just (Node -> Maybe Node)
-> StateT St (Parsec Void Text) Node
-> StateT St (Parsec Void Text) (Maybe Node)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> StateT St (Parsec Void Text) Node
pUnescapedVariable,
        Node -> Maybe Node
forall a. a -> Maybe a
Just (Node -> Maybe Node)
-> StateT St (Parsec Void Text) Node
-> StateT St (Parsec Void Text) (Maybe Node)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> StateT St (Parsec Void Text) Node
pUnescapedSpecial,
        Node -> Maybe Node
forall a. a -> Maybe a
Just (Node -> Maybe Node)
-> StateT St (Parsec Void Text) Node
-> StateT St (Parsec Void Text) (Maybe Node)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> StateT St (Parsec Void Text) Node
pEscapedVariable,
        Node -> Maybe Node
forall a. a -> Maybe a
Just (Node -> Maybe Node)
-> StateT St (Parsec Void Text) Node
-> StateT St (Parsec Void Text) (Maybe Node)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> StateT St (Parsec Void Text) Node
pTextBlock
      ]
{-# INLINE pMustache #-}

pTextBlock :: Parser Node
pTextBlock :: StateT St (Parsec Void Text) Node
pTextBlock = do
  Text
start <- (St -> Text) -> StateT St (Parsec Void Text) Text
forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
gets St -> Text
openingDel
  Text
txt <- ([Text] -> Text)
-> StateT St (Parsec Void Text) [Text]
-> StateT St (Parsec Void Text) Text
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap [Text] -> Text
T.concat (StateT St (Parsec Void Text) [Text]
 -> StateT St (Parsec Void Text) Text)
-> (StateT St (Parsec Void Text) Text
    -> StateT St (Parsec Void Text) [Text])
-> StateT St (Parsec Void Text) Text
-> StateT St (Parsec Void Text) Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. StateT St (Parsec Void Text) Text
-> StateT St (Parsec Void Text) [Text]
forall (m :: * -> *) a. MonadPlus m => m a -> m [a]
many (StateT St (Parsec Void Text) Text
 -> StateT St (Parsec Void Text) Text)
-> StateT St (Parsec Void Text) Text
-> StateT St (Parsec Void Text) Text
forall a b. (a -> b) -> a -> b
$ do
    (Parser () -> Parser ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (Parser () -> Parser ())
-> (Text -> Parser ()) -> Text -> Parser ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. StateT St (Parsec Void Text) Text -> Parser ()
forall e s (m :: * -> *) a. MonadParsec e s m => m a -> m ()
notFollowedBy (StateT St (Parsec Void Text) Text -> Parser ())
-> (Text -> StateT St (Parsec Void Text) Text) -> Text -> Parser ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> StateT St (Parsec Void Text) Text
forall e s (m :: * -> *).
MonadParsec e s m =>
Tokens s -> m (Tokens s)
string) Text
start
    let textChar :: Char -> Bool
textChar Char
x = Char
x Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
/= Text -> Char
T.head Text
start Bool -> Bool -> Bool
&& Char
x Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
/= Char
'\n'
    Tokens Text -> StateT St (Parsec Void Text) (Tokens Text)
forall e s (m :: * -> *).
MonadParsec e s m =>
Tokens s -> m (Tokens s)
string (Int -> Text -> Text
T.take Int
1 Text
start) StateT St (Parsec Void Text) Text
-> StateT St (Parsec Void Text) Text
-> StateT St (Parsec Void Text) Text
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Maybe FilePath
-> (Token Text -> Bool)
-> StateT St (Parsec Void Text) (Tokens Text)
forall e s (m :: * -> *).
MonadParsec e s m =>
Maybe FilePath -> (Token s -> Bool) -> m (Tokens s)
takeWhile1P (FilePath -> Maybe FilePath
forall a. a -> Maybe a
Just FilePath
"text char") Char -> Bool
Token Text -> Bool
textChar
  Maybe Text
meol <- StateT St (Parsec Void Text) Text
-> StateT St (Parsec Void Text) (Maybe Text)
forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional StateT St (Parsec Void Text) Text
eol'
  Node -> StateT St (Parsec Void Text) Node
forall (m :: * -> *) a. Monad m => a -> m a
return (Node -> StateT St (Parsec Void Text) Node)
-> Node -> StateT St (Parsec Void Text) Node
forall a b. (a -> b) -> a -> b
$ case Maybe Text
meol of
    Maybe Text
Nothing -> Text -> Node
TextBlock Text
txt
    Just Text
txt' -> Text -> Node
TextBlock (Text
txt Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
txt')
{-# INLINE pTextBlock #-}

pUnescapedVariable :: Parser Node
pUnescapedVariable :: StateT St (Parsec Void Text) Node
pUnescapedVariable = Key -> Node
UnescapedVar (Key -> Node)
-> StateT St (Parsec Void Text) Key
-> StateT St (Parsec Void Text) Node
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Text -> StateT St (Parsec Void Text) Key
pTag Text
"&"
{-# INLINE pUnescapedVariable #-}

pUnescapedSpecial :: Parser Node
pUnescapedSpecial :: StateT St (Parsec Void Text) Node
pUnescapedSpecial = do
  Text
start <- (St -> Text) -> StateT St (Parsec Void Text) Text
forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
gets St -> Text
openingDel
  Text
end <- (St -> Text) -> StateT St (Parsec Void Text) Text
forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
gets St -> Text
closingDel
  StateT St (Parsec Void Text) Text
-> StateT St (Parsec Void Text) Text
-> StateT St (Parsec Void Text) Node
-> StateT St (Parsec Void Text) Node
forall (m :: * -> *) open close a.
Applicative m =>
m open -> m close -> m a -> m a
between (Text -> StateT St (Parsec Void Text) Text
symbol (Text -> StateT St (Parsec Void Text) Text)
-> Text -> StateT St (Parsec Void Text) Text
forall a b. (a -> b) -> a -> b
$ Text
start Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"{") (Tokens Text -> StateT St (Parsec Void Text) (Tokens Text)
forall e s (m :: * -> *).
MonadParsec e s m =>
Tokens s -> m (Tokens s)
string (Tokens Text -> StateT St (Parsec Void Text) (Tokens Text))
-> Tokens Text -> StateT St (Parsec Void Text) (Tokens Text)
forall a b. (a -> b) -> a -> b
$ Text
"}" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
end) (StateT St (Parsec Void Text) Node
 -> StateT St (Parsec Void Text) Node)
-> StateT St (Parsec Void Text) Node
-> StateT St (Parsec Void Text) Node
forall a b. (a -> b) -> a -> b
$
    Key -> Node
UnescapedVar (Key -> Node)
-> StateT St (Parsec Void Text) Key
-> StateT St (Parsec Void Text) Node
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> StateT St (Parsec Void Text) Key
pKey
{-# INLINE pUnescapedSpecial #-}

pSection :: Text -> (Key -> [Node] -> Node) -> Parser Node
pSection :: Text
-> (Key -> [Node] -> Node) -> StateT St (Parsec Void Text) Node
pSection Text
suffix Key -> [Node] -> Node
f = do
  Key
key <- StateT St (Parsec Void Text) Key
-> StateT St (Parsec Void Text) Key
forall a. Parser a -> Parser a
withStandalone (Text -> StateT St (Parsec Void Text) Key
pTag Text
suffix)
  [Node]
nodes <- (Parser () -> StateT St (Parsec Void Text) [Node]
pMustache (Parser () -> StateT St (Parsec Void Text) [Node])
-> (Key -> Parser ()) -> Key -> StateT St (Parsec Void Text) [Node]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Parser () -> Parser ()
forall a. Parser a -> Parser a
withStandalone (Parser () -> Parser ()) -> (Key -> Parser ()) -> Key -> Parser ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Key -> Parser ()
pClosingTag) Key
key
  Node -> StateT St (Parsec Void Text) Node
forall (m :: * -> *) a. Monad m => a -> m a
return (Key -> [Node] -> Node
f Key
key [Node]
nodes)
{-# INLINE pSection #-}

pPartial :: (Pos -> Maybe Pos) -> Parser Node
pPartial :: (Pos -> Maybe Pos) -> StateT St (Parsec Void Text) Node
pPartial Pos -> Maybe Pos
f = do
  Maybe Pos
pos <- Pos -> Maybe Pos
f (Pos -> Maybe Pos)
-> StateT St (Parsec Void Text) Pos
-> StateT St (Parsec Void Text) (Maybe Pos)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> StateT St (Parsec Void Text) Pos
forall s e (m :: * -> *).
(TraversableStream s, MonadParsec e s m) =>
m Pos
L.indentLevel
  Key
key <- Text -> StateT St (Parsec Void Text) Key
pTag Text
">"
  let pname :: PName
pname = Text -> PName
PName (Text -> PName) -> Text -> PName
forall a b. (a -> b) -> a -> b
$ Text -> [Text] -> Text
T.intercalate (FilePath -> Text
T.pack FilePath
".") (Key -> [Text]
unKey Key
key)
  Node -> StateT St (Parsec Void Text) Node
forall (m :: * -> *) a. Monad m => a -> m a
return (PName -> Maybe Pos -> Node
Partial PName
pname Maybe Pos
pos)
{-# INLINE pPartial #-}

pComment :: Parser ()
pComment :: Parser ()
pComment = StateT St (Parsec Void Text) FilePath -> Parser ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (StateT St (Parsec Void Text) FilePath -> Parser ())
-> StateT St (Parsec Void Text) FilePath -> Parser ()
forall a b. (a -> b) -> a -> b
$ do
  Text
start <- (St -> Text) -> StateT St (Parsec Void Text) Text
forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
gets St -> Text
openingDel
  Text
end <- (St -> Text) -> StateT St (Parsec Void Text) Text
forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
gets St -> Text
closingDel
  (StateT St (Parsec Void Text) Text -> Parser ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (StateT St (Parsec Void Text) Text -> Parser ())
-> (Text -> StateT St (Parsec Void Text) Text) -> Text -> Parser ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> StateT St (Parsec Void Text) Text
symbol) (Text
start Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"!")
  StateT St (Parsec Void Text) Char
-> StateT St (Parsec Void Text) Text
-> StateT St (Parsec Void Text) FilePath
forall (m :: * -> *) a end. MonadPlus m => m a -> m end -> m [a]
manyTill (StateT St (Parsec Void Text) Char
forall e s (m :: * -> *). MonadParsec e s m => m (Token s)
anySingle StateT St (Parsec Void Text) Char
-> FilePath -> StateT St (Parsec Void Text) Char
forall e s (m :: * -> *) a.
MonadParsec e s m =>
m a -> FilePath -> m a
<?> FilePath
"character") (Tokens Text -> StateT St (Parsec Void Text) (Tokens Text)
forall e s (m :: * -> *).
MonadParsec e s m =>
Tokens s -> m (Tokens s)
string Text
Tokens Text
end)
{-# INLINE pComment #-}

pSetDelimiters :: Parser ()
pSetDelimiters :: Parser ()
pSetDelimiters = Parser () -> Parser ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (Parser () -> Parser ()) -> Parser () -> Parser ()
forall a b. (a -> b) -> a -> b
$ do
  Text
start <- (St -> Text) -> StateT St (Parsec Void Text) Text
forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
gets St -> Text
openingDel
  Text
end <- (St -> Text) -> StateT St (Parsec Void Text) Text
forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
gets St -> Text
closingDel
  (StateT St (Parsec Void Text) Text -> Parser ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (StateT St (Parsec Void Text) Text -> Parser ())
-> (Text -> StateT St (Parsec Void Text) Text) -> Text -> Parser ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> StateT St (Parsec Void Text) Text
symbol) (Text
start Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"=")
  Text
start' <- StateT St (Parsec Void Text) Text
pDelimiter StateT St (Parsec Void Text) Text
-> Parser () -> StateT St (Parsec Void Text) Text
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Parser ()
scn
  Text
end' <- StateT St (Parsec Void Text) Text
pDelimiter StateT St (Parsec Void Text) Text
-> Parser () -> StateT St (Parsec Void Text) Text
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Parser ()
scn
  (StateT St (Parsec Void Text) Text -> Parser ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (StateT St (Parsec Void Text) Text -> Parser ())
-> (Text -> StateT St (Parsec Void Text) Text) -> Text -> Parser ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> StateT St (Parsec Void Text) Text
forall e s (m :: * -> *).
MonadParsec e s m =>
Tokens s -> m (Tokens s)
string) (Text
"=" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
end)
  (St -> St) -> Parser ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modify' ((St -> St) -> Parser ()) -> (St -> St) -> Parser ()
forall a b. (a -> b) -> a -> b
$ \St
st ->
    St
st
      { openingDel :: Text
openingDel = Text
start',
        closingDel :: Text
closingDel = Text
end'
      }
{-# INLINE pSetDelimiters #-}

pEscapedVariable :: Parser Node
pEscapedVariable :: StateT St (Parsec Void Text) Node
pEscapedVariable = Key -> Node
EscapedVar (Key -> Node)
-> StateT St (Parsec Void Text) Key
-> StateT St (Parsec Void Text) Node
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Text -> StateT St (Parsec Void Text) Key
pTag Text
""
{-# INLINE pEscapedVariable #-}

withStandalone :: Parser a -> Parser a
withStandalone :: Parser a -> Parser a
withStandalone Parser a
p = Parser a -> Parser a
forall a. Parser a -> Parser a
pStandalone Parser a
p Parser a -> Parser a -> Parser a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser a
p
{-# INLINE withStandalone #-}

pStandalone :: Parser a -> Parser a
pStandalone :: Parser a -> Parser a
pStandalone Parser a
p = Parser ()
pBol Parser () -> Parser a -> Parser a
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Parser a -> Parser a
forall e s (m :: * -> *) a. MonadParsec e s m => m a -> m a
try (Parser () -> Parser () -> Parser a -> Parser a
forall (m :: * -> *) open close a.
Applicative m =>
m open -> m close -> m a -> m a
between Parser ()
sc (Parser ()
sc Parser () -> Parser () -> Parser ()
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* (StateT St (Parsec Void Text) Text -> Parser ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void StateT St (Parsec Void Text) Text
eol' Parser () -> Parser () -> Parser ()
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser ()
forall e s (m :: * -> *). MonadParsec e s m => m ()
eof)) Parser a
p)
{-# INLINE pStandalone #-}

pTag :: Text -> Parser Key
pTag :: Text -> StateT St (Parsec Void Text) Key
pTag Text
suffix = do
  Text
start <- (St -> Text) -> StateT St (Parsec Void Text) Text
forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
gets St -> Text
openingDel
  Text
end <- (St -> Text) -> StateT St (Parsec Void Text) Text
forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
gets St -> Text
closingDel
  StateT St (Parsec Void Text) Text
-> StateT St (Parsec Void Text) Text
-> StateT St (Parsec Void Text) Key
-> StateT St (Parsec Void Text) Key
forall (m :: * -> *) open close a.
Applicative m =>
m open -> m close -> m a -> m a
between (Text -> StateT St (Parsec Void Text) Text
symbol (Text -> StateT St (Parsec Void Text) Text)
-> Text -> StateT St (Parsec Void Text) Text
forall a b. (a -> b) -> a -> b
$ Text
start Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
suffix) (Tokens Text -> StateT St (Parsec Void Text) (Tokens Text)
forall e s (m :: * -> *).
MonadParsec e s m =>
Tokens s -> m (Tokens s)
string Text
Tokens Text
end) StateT St (Parsec Void Text) Key
pKey
{-# INLINE pTag #-}

pClosingTag :: Key -> Parser ()
pClosingTag :: Key -> Parser ()
pClosingTag Key
key = do
  Text
start <- (St -> Text) -> StateT St (Parsec Void Text) Text
forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
gets St -> Text
openingDel
  Text
end <- (St -> Text) -> StateT St (Parsec Void Text) Text
forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
gets St -> Text
closingDel
  let str :: Text
str = Key -> Text
keyToText Key
key
  StateT St (Parsec Void Text) Text -> Parser ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (StateT St (Parsec Void Text) Text -> Parser ())
-> StateT St (Parsec Void Text) Text -> Parser ()
forall a b. (a -> b) -> a -> b
$ StateT St (Parsec Void Text) Text
-> StateT St (Parsec Void Text) Text
-> StateT St (Parsec Void Text) Text
-> StateT St (Parsec Void Text) Text
forall (m :: * -> *) open close a.
Applicative m =>
m open -> m close -> m a -> m a
between (Text -> StateT St (Parsec Void Text) Text
symbol (Text -> StateT St (Parsec Void Text) Text)
-> Text -> StateT St (Parsec Void Text) Text
forall a b. (a -> b) -> a -> b
$ Text
start Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"/") (Tokens Text -> StateT St (Parsec Void Text) (Tokens Text)
forall e s (m :: * -> *).
MonadParsec e s m =>
Tokens s -> m (Tokens s)
string Text
Tokens Text
end) (Text -> StateT St (Parsec Void Text) Text
symbol Text
str)
{-# INLINE pClosingTag #-}

pKey :: Parser Key
pKey :: StateT St (Parsec Void Text) Key
pKey = (([Text] -> Key)
-> StateT St (Parsec Void Text) [Text]
-> StateT St (Parsec Void Text) Key
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap [Text] -> Key
Key (StateT St (Parsec Void Text) [Text]
 -> StateT St (Parsec Void Text) Key)
-> (StateT St (Parsec Void Text) [Text]
    -> StateT St (Parsec Void Text) [Text])
-> StateT St (Parsec Void Text) [Text]
-> StateT St (Parsec Void Text) Key
forall b c a. (b -> c) -> (a -> b) -> a -> c
. StateT St (Parsec Void Text) [Text]
-> StateT St (Parsec Void Text) [Text]
forall a. Parser a -> Parser a
lexeme (StateT St (Parsec Void Text) [Text]
 -> StateT St (Parsec Void Text) [Text])
-> (StateT St (Parsec Void Text) [Text]
    -> StateT St (Parsec Void Text) [Text])
-> StateT St (Parsec Void Text) [Text]
-> StateT St (Parsec Void Text) [Text]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath
-> StateT St (Parsec Void Text) [Text]
-> StateT St (Parsec Void Text) [Text]
forall e s (m :: * -> *) a.
MonadParsec e s m =>
FilePath -> m a -> m a
label FilePath
"key") (StateT St (Parsec Void Text) [Text]
forall a. StateT St (Parsec Void Text) [a]
implicit StateT St (Parsec Void Text) [Text]
-> StateT St (Parsec Void Text) [Text]
-> StateT St (Parsec Void Text) [Text]
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> StateT St (Parsec Void Text) [Text]
other)
  where
    implicit :: StateT St (Parsec Void Text) [a]
implicit = [] [a]
-> StateT St (Parsec Void Text) Char
-> StateT St (Parsec Void Text) [a]
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ Token Text -> StateT St (Parsec Void Text) (Token Text)
forall e s (m :: * -> *).
(MonadParsec e s m, Token s ~ Char) =>
Token s -> m (Token s)
char Char
Token Text
'.'
    other :: StateT St (Parsec Void Text) [Text]
other = do
      Text
end <- (St -> Text) -> StateT St (Parsec Void Text) Text
forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
gets St -> Text
closingDel
      let f :: Char -> Bool
f Char
x = Char
x Char -> FilePath -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`notElem` (Char
'.' Char -> FilePath -> FilePath
forall a. a -> [a] -> [a]
: Char
'}' Char -> FilePath -> FilePath
forall a. a -> [a] -> [a]
: Text -> FilePath
T.unpack Text
end)
          lbl :: FilePath
lbl = FilePath
"key-constituent characters"
      [Text] -> [Text]
stripLast ([Text] -> [Text])
-> StateT St (Parsec Void Text) [Text]
-> StateT St (Parsec Void Text) [Text]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> StateT St (Parsec Void Text) Text
-> StateT St (Parsec Void Text) Char
-> StateT St (Parsec Void Text) [Text]
forall (m :: * -> *) a end. MonadPlus m => m a -> m end -> m [a]
sepBy1 (Maybe FilePath
-> (Token Text -> Bool)
-> StateT St (Parsec Void Text) (Tokens Text)
forall e s (m :: * -> *).
MonadParsec e s m =>
Maybe FilePath -> (Token s -> Bool) -> m (Tokens s)
takeWhile1P (FilePath -> Maybe FilePath
forall a. a -> Maybe a
Just FilePath
lbl) Char -> Bool
Token Text -> Bool
f) (Token Text -> StateT St (Parsec Void Text) (Token Text)
forall e s (m :: * -> *).
(MonadParsec e s m, Token s ~ Char) =>
Token s -> m (Token s)
char Char
Token Text
'.')
    stripLast :: [Text] -> [Text]
stripLast [] = []
    stripLast [Text
x] = [Text -> Text
stripEnd Text
x]
    stripLast (Text
x0 : Text
x1 : [Text]
xs) = Text
x0 Text -> [Text] -> [Text]
forall a. a -> [a] -> [a]
: [Text] -> [Text]
stripLast (Text
x1 Text -> [Text] -> [Text]
forall a. a -> [a] -> [a]
: [Text]
xs)
{-# INLINE pKey #-}

pDelimiter :: Parser Text
pDelimiter :: StateT St (Parsec Void Text) Text
pDelimiter = Maybe FilePath
-> (Token Text -> Bool)
-> StateT St (Parsec Void Text) (Tokens Text)
forall e s (m :: * -> *).
MonadParsec e s m =>
Maybe FilePath -> (Token s -> Bool) -> m (Tokens s)
takeWhile1P (FilePath -> Maybe FilePath
forall a. a -> Maybe a
Just FilePath
"delimiter char") Char -> Bool
Token Text -> Bool
delChar StateT St (Parsec Void Text) Text
-> FilePath -> StateT St (Parsec Void Text) Text
forall e s (m :: * -> *) a.
MonadParsec e s m =>
m a -> FilePath -> m a
<?> FilePath
"delimiter"
  where
    delChar :: Char -> Bool
delChar Char
x = Bool -> Bool
not (Char -> Bool
isSpace Char
x) Bool -> Bool -> Bool
&& Char
x Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
/= Char
'='
{-# INLINE pDelimiter #-}

pBol :: Parser ()
pBol :: Parser ()
pBol = do
  Int
o <- StateT St (Parsec Void Text) Int
forall e s (m :: * -> *). MonadParsec e s m => m Int
getOffset
  Int
o' <- (St -> Int) -> StateT St (Parsec Void Text) Int
forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
gets St -> Int
newlineOffset
  Bool -> Parser () -> Parser ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (Int
o Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
o') Parser ()
forall (f :: * -> *) a. Alternative f => f a
empty
{-# INLINE pBol #-}

----------------------------------------------------------------------------
-- Auxiliary types

-- | Type of Mustache parser monad stack.
type Parser = StateT St (Parsec Void Text)

-- | State used in the parser.
data St = St
  { -- | Opening delimiter
    St -> Text
openingDel :: Text,
    -- | Closing delimiter
    St -> Text
closingDel :: Text,
    -- | The offset at which last newline character was parsed
    St -> Int
newlineOffset :: !Int
  }

----------------------------------------------------------------------------
-- Lexer helpers and other

scn :: Parser ()
scn :: Parser ()
scn = Parser () -> Parser () -> Parser () -> Parser ()
forall e s (m :: * -> *).
MonadParsec e s m =>
m () -> m () -> m () -> m ()
L.space Parser ()
forall e s (m :: * -> *).
(MonadParsec e s m, Token s ~ Char) =>
m ()
space1 Parser ()
forall (f :: * -> *) a. Alternative f => f a
empty Parser ()
forall (f :: * -> *) a. Alternative f => f a
empty
{-# INLINE scn #-}

sc :: Parser ()
sc :: Parser ()
sc = Parser () -> Parser () -> Parser () -> Parser ()
forall e s (m :: * -> *).
MonadParsec e s m =>
m () -> m () -> m () -> m ()
L.space (StateT St (Parsec Void Text) Text -> Parser ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (StateT St (Parsec Void Text) Text -> Parser ())
-> StateT St (Parsec Void Text) Text -> Parser ()
forall a b. (a -> b) -> a -> b
$ Maybe FilePath
-> (Token Text -> Bool)
-> StateT St (Parsec Void Text) (Tokens Text)
forall e s (m :: * -> *).
MonadParsec e s m =>
Maybe FilePath -> (Token s -> Bool) -> m (Tokens s)
takeWhile1P Maybe FilePath
forall a. Maybe a
Nothing Char -> Bool
Token Text -> Bool
f) Parser ()
forall (f :: * -> *) a. Alternative f => f a
empty Parser ()
forall (f :: * -> *) a. Alternative f => f a
empty
  where
    f :: Char -> Bool
f Char
x = Char
x Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
' ' Bool -> Bool -> Bool
|| Char
x Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'\t'
{-# INLINE sc #-}

lexeme :: Parser a -> Parser a
lexeme :: Parser a -> Parser a
lexeme = Parser () -> Parser a -> Parser a
forall e s (m :: * -> *) a. MonadParsec e s m => m () -> m a -> m a
L.lexeme Parser ()
scn
{-# INLINE lexeme #-}

symbol :: Text -> Parser Text
symbol :: Text -> StateT St (Parsec Void Text) Text
symbol = Parser ()
-> Tokens Text -> StateT St (Parsec Void Text) (Tokens Text)
forall e s (m :: * -> *).
MonadParsec e s m =>
m () -> Tokens s -> m (Tokens s)
L.symbol Parser ()
scn
{-# INLINE symbol #-}

keyToText :: Key -> Text
keyToText :: Key -> Text
keyToText (Key []) = Text
"."
keyToText (Key [Text]
ks) = Text -> [Text] -> Text
T.intercalate Text
"." [Text]
ks
{-# INLINE keyToText #-}

eol' :: Parser Text
eol' :: StateT St (Parsec Void Text) Text
eol' = do
  Text
x <- StateT St (Parsec Void Text) Text
forall e s (m :: * -> *).
(MonadParsec e s m, Token s ~ Char) =>
m (Tokens s)
eol
  Int
o <- StateT St (Parsec Void Text) Int
forall e s (m :: * -> *). MonadParsec e s m => m Int
getOffset
  (St -> St) -> Parser ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modify' (\St
st -> St
st {newlineOffset :: Int
newlineOffset = Int
o})
  Text -> StateT St (Parsec Void Text) Text
forall (m :: * -> *) a. Monad m => a -> m a
return Text
x
{-# INLINE eol' #-}