{-|
Module      : $Header$
Description : Basic functions for dealing with mustache templates.
Copyright   : (c) Justus Adam, 2015
License     : BSD3
Maintainer  : dev@justus.science
Stability   : experimental
Portability : POSIX
-}
{-# LANGUAGE FlexibleContexts      #-}
{-# LANGUAGE LambdaCase            #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE NamedFieldPuns        #-}
{-# LANGUAGE OverloadedStrings     #-}
{-# LANGUAGE TupleSections         #-}
module Text.Mustache.Parser
  (
  -- * Generic parsing functions

    parse, parseWithConf

  -- * Configurations

  , MustacheConf(..), defaultConf

  -- * Parser

  , Parser, MustacheState

  -- * Mustache Constants

  , sectionBegin, sectionEnd, invertedSectionBegin, unescape2, unescape1
  , delimiterChange, nestingSeparator

  ) where


import           Control.Monad
import           Data.Char           (isAlphaNum, isSpace)
import           Data.List           (nub)
import           Data.Monoid         ((<>))
import           Data.Text           as T (Text, null, pack)
import           Prelude             as Prel
import           Text.Mustache.Types
import           Text.Parsec         as P hiding (endOfLine, parse)


-- | Initial configuration for the parser
data MustacheConf = MustacheConf
  { MustacheConf -> (String, String)
delimiters :: (String, String)
  }


-- | User state for the parser
data MustacheState = MustacheState
  { MustacheState -> (String, String)
sDelimiters        :: (String, String)
  , MustacheState -> Text
textStack          :: Text
  , MustacheState -> Bool
isBeginngingOfLine :: Bool
  , MustacheState -> Maybe DataIdentifier
currentSectionName :: Maybe DataIdentifier
  }


data ParseTagRes
  = SectionBegin Bool DataIdentifier
  | SectionEnd DataIdentifier
  | Tag (Node Text)
  | HandledTag


-- | @#@
sectionBegin :: Char
sectionBegin :: Char
sectionBegin = Char
'#'
-- | @/@
sectionEnd :: Char
sectionEnd :: Char
sectionEnd = Char
'/'
-- | @>@
partialBegin :: Char
partialBegin :: Char
partialBegin = Char
'>'
-- | @^@
invertedSectionBegin :: Char
invertedSectionBegin :: Char
invertedSectionBegin = Char
'^'
-- | @{@ and @}@
unescape2 :: (Char, Char)
unescape2 :: (Char, Char)
unescape2 = (Char
'{', Char
'}')
-- | @&@
unescape1 :: Char
unescape1 :: Char
unescape1 = Char
'&'
-- | @=@
delimiterChange :: Char
delimiterChange :: Char
delimiterChange = Char
'='
-- | @.@
nestingSeparator :: Char
nestingSeparator :: Char
nestingSeparator = Char
'.'
-- | @!@
comment :: Char
comment :: Char
comment = Char
'!'
-- | @.@
implicitIterator :: Char
implicitIterator :: Char
implicitIterator = Char
'.'
-- | Cannot be a letter, number or the nesting separation Character @.@
isAllowedDelimiterCharacter :: Char -> Bool
isAllowedDelimiterCharacter :: Char -> Bool
isAllowedDelimiterCharacter =
  Bool -> Bool
not (Bool -> Bool) -> (Char -> Bool) -> Char -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Bool] -> Bool
forall (t :: * -> *). Foldable t => t Bool -> Bool
Prel.or ([Bool] -> Bool) -> (Char -> [Bool]) -> Char -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char -> Bool] -> Char -> [Bool]
forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
sequence
    [ Char -> Bool
isSpace, Char -> Bool
isAlphaNum, (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
nestingSeparator) ]
allowedDelimiterCharacter :: Parser Char
allowedDelimiterCharacter :: Parser Char
allowedDelimiterCharacter =
  (Char -> Bool) -> Parser Char
forall s (m :: * -> *) u.
Stream s m Char =>
(Char -> Bool) -> ParsecT s u m Char
satisfy Char -> Bool
isAllowedDelimiterCharacter


-- | Empty configuration
emptyState :: MustacheState
emptyState :: MustacheState
emptyState = (String, String)
-> Text -> Bool -> Maybe DataIdentifier -> MustacheState
MustacheState (String
"", String
"") Text
forall a. Monoid a => a
mempty Bool
True Maybe DataIdentifier
forall a. Maybe a
Nothing


-- | Default configuration (delimiters = ("{{", "}}"))
defaultConf :: MustacheConf
defaultConf :: MustacheConf
defaultConf = (String, String) -> MustacheConf
MustacheConf (String
"{{", String
"}}")


initState :: MustacheConf -> MustacheState
initState :: MustacheConf -> MustacheState
initState (MustacheConf { (String, String)
delimiters :: (String, String)
delimiters :: MustacheConf -> (String, String)
delimiters }) = MustacheState
emptyState { sDelimiters :: (String, String)
sDelimiters = (String, String)
delimiters }


setIsBeginning :: Bool -> Parser ()
setIsBeginning :: Bool -> Parser ()
setIsBeginning Bool
b = (MustacheState -> MustacheState) -> Parser ()
forall (m :: * -> *) u s. Monad m => (u -> u) -> ParsecT s u m ()
modifyState (\MustacheState
s -> MustacheState
s { isBeginngingOfLine :: Bool
isBeginngingOfLine = Bool
b })


-- | The parser monad in use
type Parser = Parsec Text MustacheState


(<<) :: Monad m => m b -> m a -> m b
<< :: m b -> m a -> m b
(<<) = (m a -> m b -> m b) -> m b -> m a -> m b
forall a b c. (a -> b -> c) -> b -> a -> c
flip m a -> m b -> m b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
(>>)


endOfLine :: Parser String
endOfLine :: Parser String
endOfLine = do
  Maybe Char
r <- Parser Char -> ParsecT Text MustacheState Identity (Maybe Char)
forall s (m :: * -> *) t u a.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m (Maybe a)
optionMaybe (Parser Char -> ParsecT Text MustacheState Identity (Maybe Char))
-> Parser Char -> ParsecT Text MustacheState Identity (Maybe Char)
forall a b. (a -> b) -> a -> b
$ Char -> Parser Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
'\r'
  Char
n <- Char -> Parser Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
'\n'
  String -> Parser String
forall (m :: * -> *) a. Monad m => a -> m a
return (String -> Parser String) -> String -> Parser String
forall a b. (a -> b) -> a -> b
$ (String -> String)
-> (Char -> String -> String) -> Maybe Char -> String -> String
forall b a. b -> (a -> b) -> Maybe a -> b
maybe String -> String
forall a. a -> a
id (:) Maybe Char
r [Char
n]


{-|
  Runs the parser for a mustache template, returning the syntax tree.
-}
parse :: FilePath -> Text -> Either ParseError STree
parse :: String -> Text -> Either ParseError STree
parse = MustacheConf -> String -> Text -> Either ParseError STree
parseWithConf MustacheConf
defaultConf


-- | Parse using a custom initial configuration
parseWithConf :: MustacheConf -> FilePath -> Text -> Either ParseError STree
parseWithConf :: MustacheConf -> String -> Text -> Either ParseError STree
parseWithConf = Parsec Text MustacheState STree
-> MustacheState -> String -> Text -> Either ParseError STree
forall s t u a.
Stream s Identity t =>
Parsec s u a -> u -> String -> s -> Either ParseError a
P.runParser Parsec Text MustacheState STree
parseText (MustacheState -> String -> Text -> Either ParseError STree)
-> (MustacheConf -> MustacheState)
-> MustacheConf
-> String
-> Text
-> Either ParseError STree
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MustacheConf -> MustacheState
initState


parseText :: Parser STree
parseText :: Parsec Text MustacheState STree
parseText = do
  (MustacheState { Bool
isBeginngingOfLine :: Bool
isBeginngingOfLine :: MustacheState -> Bool
isBeginngingOfLine }) <- ParsecT Text MustacheState Identity MustacheState
forall (m :: * -> *) s u. Monad m => ParsecT s u m u
getState
  if Bool
isBeginngingOfLine
    then Parsec Text MustacheState STree
parseLine
    else Parsec Text MustacheState STree
continueLine


appendStringStack :: String -> Parser ()
appendStringStack :: String -> Parser ()
appendStringStack String
t = (MustacheState -> MustacheState) -> Parser ()
forall (m :: * -> *) u s. Monad m => (u -> u) -> ParsecT s u m ()
modifyState (\MustacheState
s -> MustacheState
s { textStack :: Text
textStack = MustacheState -> Text
textStack MustacheState
s Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
pack String
t})


continueLine :: Parser STree
continueLine :: Parsec Text MustacheState STree
continueLine = do
  (MustacheState { sDelimiters :: MustacheState -> (String, String)
sDelimiters = ( start :: String
start@(Char
x:String
_), String
_ )}) <- ParsecT Text MustacheState Identity MustacheState
forall (m :: * -> *) s u. Monad m => ParsecT s u m u
getState
  let forbidden :: String
forbidden = Char
x Char -> String -> String
forall a. a -> [a] -> [a]
: String
"\n\r"

  Parser Char -> Parser String
forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m [a]
many (String -> Parser Char
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m Char
noneOf String
forbidden) Parser String -> (String -> Parser ()) -> Parser ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= String -> Parser ()
appendStringStack

  (Parser String -> Parser String
forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try Parser String
endOfLine Parser String -> (String -> Parser ()) -> Parser ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= String -> Parser ()
appendStringStack Parser () -> Parser () -> Parser ()
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Bool -> Parser ()
setIsBeginning Bool
True Parser ()
-> Parsec Text MustacheState STree
-> Parsec Text MustacheState STree
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Parsec Text MustacheState STree
parseLine)
    Parsec Text MustacheState STree
-> Parsec Text MustacheState STree
-> Parsec Text MustacheState STree
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> (Parser String -> Parser String
forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try (String -> Parser String
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m String
string String
start) Parser String
-> ParsecT Text MustacheState Identity ParseTagRes
-> ParsecT Text MustacheState Identity ParseTagRes
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> ParsecT Text MustacheState Identity ParseTagRes
switchOnTag ParsecT Text MustacheState Identity ParseTagRes
-> (ParseTagRes -> Parsec Text MustacheState STree)
-> Parsec Text MustacheState STree
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= ParseTagRes -> Parsec Text MustacheState STree
continueFromTag)
    Parsec Text MustacheState STree
-> Parsec Text MustacheState STree
-> Parsec Text MustacheState STree
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> (Parser () -> Parser ()
forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try Parser ()
forall s (m :: * -> *) t u.
(Stream s m t, Show t) =>
ParsecT s u m ()
eof Parser ()
-> Parsec Text MustacheState STree
-> Parsec Text MustacheState STree
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Parsec Text MustacheState STree
finishFile)
    Parsec Text MustacheState STree
-> Parsec Text MustacheState STree
-> Parsec Text MustacheState STree
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> (Parser Char
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m Char
anyChar Parser Char -> (Char -> Parser ()) -> Parser ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= String -> Parser ()
appendStringStack (String -> Parser ()) -> (Char -> String) -> Char -> Parser ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Char -> String -> String
forall a. a -> [a] -> [a]
:[]) Parser ()
-> Parsec Text MustacheState STree
-> Parsec Text MustacheState STree
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Parsec Text MustacheState STree
continueLine)


flushText :: Parser STree
flushText :: Parsec Text MustacheState STree
flushText = do
  s :: MustacheState
s@(MustacheState { textStack :: MustacheState -> Text
textStack = Text
text }) <- ParsecT Text MustacheState Identity MustacheState
forall (m :: * -> *) s u. Monad m => ParsecT s u m u
getState
  MustacheState -> Parser ()
forall (m :: * -> *) u s. Monad m => u -> ParsecT s u m ()
putState (MustacheState -> Parser ()) -> MustacheState -> Parser ()
forall a b. (a -> b) -> a -> b
$ MustacheState
s { textStack :: Text
textStack = Text
forall a. Monoid a => a
mempty }
  STree -> Parsec Text MustacheState STree
forall (m :: * -> *) a. Monad m => a -> m a
return (STree -> Parsec Text MustacheState STree)
-> STree -> Parsec Text MustacheState STree
forall a b. (a -> b) -> a -> b
$ if Text -> Bool
T.null Text
text
              then []
              else [Text -> Node Text
forall α. α -> Node α
TextBlock Text
text]


finishFile :: Parser STree
finishFile :: Parsec Text MustacheState STree
finishFile =
  ParsecT Text MustacheState Identity MustacheState
forall (m :: * -> *) s u. Monad m => ParsecT s u m u
getState ParsecT Text MustacheState Identity MustacheState
-> (MustacheState -> Parsec Text MustacheState STree)
-> Parsec Text MustacheState STree
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
    (MustacheState {currentSectionName :: MustacheState -> Maybe DataIdentifier
currentSectionName = Maybe DataIdentifier
Nothing}) -> Parsec Text MustacheState STree
flushText
    (MustacheState {currentSectionName :: MustacheState -> Maybe DataIdentifier
currentSectionName = Just DataIdentifier
name}) ->
      String -> Parsec Text MustacheState STree
forall s u (m :: * -> *) a. String -> ParsecT s u m a
parserFail (String -> Parsec Text MustacheState STree)
-> String -> Parsec Text MustacheState STree
forall a b. (a -> b) -> a -> b
$ String
"Unclosed section " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> DataIdentifier -> String
forall a. Show a => a -> String
show DataIdentifier
name


parseLine :: Parser STree
parseLine :: Parsec Text MustacheState STree
parseLine = do
  (MustacheState { sDelimiters :: MustacheState -> (String, String)
sDelimiters = ( String
start, String
_ ) }) <- ParsecT Text MustacheState Identity MustacheState
forall (m :: * -> *) s u. Monad m => ParsecT s u m u
getState
  String
initialWhitespace <- Parser Char -> Parser String
forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m [a]
many (String -> Parser Char
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m Char
oneOf String
" \t")
  let handleStandalone :: Parsec Text MustacheState STree
handleStandalone = do
        ParseTagRes
tag <- ParsecT Text MustacheState Identity ParseTagRes
switchOnTag
        let continueNoStandalone :: Parsec Text MustacheState STree
continueNoStandalone = do
              String -> Parser ()
appendStringStack String
initialWhitespace
              Bool -> Parser ()
setIsBeginning Bool
False
              ParseTagRes -> Parsec Text MustacheState STree
continueFromTag ParseTagRes
tag
            standaloneEnding :: Parser ()
standaloneEnding = do
              Parser () -> Parser ()
forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try (Parser Char -> Parser ()
forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m ()
skipMany (String -> Parser Char
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m Char
oneOf String
" \t") Parser () -> Parser () -> Parser ()
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> (Parser ()
forall s (m :: * -> *) t u.
(Stream s m t, Show t) =>
ParsecT s u m ()
eof Parser () -> Parser () -> Parser ()
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> Parser String -> Parser ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void Parser String
endOfLine))
              Bool -> Parser ()
setIsBeginning Bool
True
        case ParseTagRes
tag of
          Tag (Partial Maybe Text
_ String
name) ->
            ( Parser ()
standaloneEnding Parser ()
-> Parsec Text MustacheState STree
-> Parsec Text MustacheState STree
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>>
              ParseTagRes -> Parsec Text MustacheState STree
continueFromTag (Node Text -> ParseTagRes
Tag (Maybe Text -> String -> Node Text
forall α. Maybe α -> String -> Node α
Partial (Text -> Maybe Text
forall a. a -> Maybe a
Just (String -> Text
pack String
initialWhitespace)) String
name))
            ) Parsec Text MustacheState STree
-> Parsec Text MustacheState STree
-> Parsec Text MustacheState STree
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> Parsec Text MustacheState STree
continueNoStandalone
          Tag Node Text
_ -> Parsec Text MustacheState STree
continueNoStandalone
          ParseTagRes
_     ->
            ( Parser ()
standaloneEnding Parser ()
-> Parsec Text MustacheState STree
-> Parsec Text MustacheState STree
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>>
              ParseTagRes -> Parsec Text MustacheState STree
continueFromTag ParseTagRes
tag
            ) Parsec Text MustacheState STree
-> Parsec Text MustacheState STree
-> Parsec Text MustacheState STree
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> Parsec Text MustacheState STree
continueNoStandalone
  (Parser String -> Parser String
forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try (String -> Parser String
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m String
string String
start) Parser String
-> Parsec Text MustacheState STree
-> Parsec Text MustacheState STree
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Parsec Text MustacheState STree
handleStandalone)
    Parsec Text MustacheState STree
-> Parsec Text MustacheState STree
-> Parsec Text MustacheState STree
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> (Parser () -> Parser ()
forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try Parser ()
forall s (m :: * -> *) t u.
(Stream s m t, Show t) =>
ParsecT s u m ()
eof Parser () -> Parser () -> Parser ()
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> String -> Parser ()
appendStringStack String
initialWhitespace Parser ()
-> Parsec Text MustacheState STree
-> Parsec Text MustacheState STree
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Parsec Text MustacheState STree
finishFile)
    Parsec Text MustacheState STree
-> Parsec Text MustacheState STree
-> Parsec Text MustacheState STree
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> (String -> Parser ()
appendStringStack String
initialWhitespace Parser () -> Parser () -> Parser ()
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Bool -> Parser ()
setIsBeginning Bool
False Parser ()
-> Parsec Text MustacheState STree
-> Parsec Text MustacheState STree
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Parsec Text MustacheState STree
continueLine)


continueFromTag :: ParseTagRes -> Parser STree
continueFromTag :: ParseTagRes -> Parsec Text MustacheState STree
continueFromTag (SectionBegin Bool
inverted DataIdentifier
name) = do
  STree
textNodes <- Parsec Text MustacheState STree
flushText
  state :: MustacheState
state@(MustacheState
    { currentSectionName :: MustacheState -> Maybe DataIdentifier
currentSectionName = Maybe DataIdentifier
previousSection }) <- ParsecT Text MustacheState Identity MustacheState
forall (m :: * -> *) s u. Monad m => ParsecT s u m u
getState
  MustacheState -> Parser ()
forall (m :: * -> *) u s. Monad m => u -> ParsecT s u m ()
putState (MustacheState -> Parser ()) -> MustacheState -> Parser ()
forall a b. (a -> b) -> a -> b
$ MustacheState
state { currentSectionName :: Maybe DataIdentifier
currentSectionName = DataIdentifier -> Maybe DataIdentifier
forall (m :: * -> *) a. Monad m => a -> m a
return DataIdentifier
name }
  STree
innerSectionContent <- Parsec Text MustacheState STree
parseText
  let sectionTag :: DataIdentifier -> ASTree α -> Node α
sectionTag =
        if Bool
inverted
          then DataIdentifier -> ASTree α -> Node α
forall α. DataIdentifier -> ASTree α -> Node α
InvertedSection
          else DataIdentifier -> ASTree α -> Node α
forall α. DataIdentifier -> ASTree α -> Node α
Section
  (MustacheState -> MustacheState) -> Parser ()
forall (m :: * -> *) u s. Monad m => (u -> u) -> ParsecT s u m ()
modifyState ((MustacheState -> MustacheState) -> Parser ())
-> (MustacheState -> MustacheState) -> Parser ()
forall a b. (a -> b) -> a -> b
$ \MustacheState
s -> MustacheState
s { currentSectionName :: Maybe DataIdentifier
currentSectionName = Maybe DataIdentifier
previousSection }
  STree
outerSectionContent <- Parsec Text MustacheState STree
parseText
  STree -> Parsec Text MustacheState STree
forall (m :: * -> *) a. Monad m => a -> m a
return (STree
textNodes STree -> STree -> STree
forall a. Semigroup a => a -> a -> a
<> [DataIdentifier -> STree -> Node Text
forall α. DataIdentifier -> ASTree α -> Node α
sectionTag DataIdentifier
name STree
innerSectionContent] STree -> STree -> STree
forall a. Semigroup a => a -> a -> a
<> STree
outerSectionContent)
continueFromTag (SectionEnd DataIdentifier
name) = do
  (MustacheState
    { Maybe DataIdentifier
currentSectionName :: Maybe DataIdentifier
currentSectionName :: MustacheState -> Maybe DataIdentifier
currentSectionName }) <- ParsecT Text MustacheState Identity MustacheState
forall (m :: * -> *) s u. Monad m => ParsecT s u m u
getState
  case Maybe DataIdentifier
currentSectionName of
    Just DataIdentifier
name' | DataIdentifier
name' DataIdentifier -> DataIdentifier -> Bool
forall a. Eq a => a -> a -> Bool
== DataIdentifier
name -> Parsec Text MustacheState STree
flushText
    Just DataIdentifier
name' -> String -> Parsec Text MustacheState STree
forall s u (m :: * -> *) a. String -> ParsecT s u m a
parserFail (String -> Parsec Text MustacheState STree)
-> String -> Parsec Text MustacheState STree
forall a b. (a -> b) -> a -> b
$ String
"Expected closing sequence for \"" String -> String -> String
forall a. Semigroup a => a -> a -> a
<> DataIdentifier -> String
forall a. Show a => a -> String
show DataIdentifier
name String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
"\" got \"" String -> String -> String
forall a. Semigroup a => a -> a -> a
<> DataIdentifier -> String
forall a. Show a => a -> String
show DataIdentifier
name' String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
"\"."
    Maybe DataIdentifier
Nothing -> String -> Parsec Text MustacheState STree
forall s u (m :: * -> *) a. String -> ParsecT s u m a
parserFail (String -> Parsec Text MustacheState STree)
-> String -> Parsec Text MustacheState STree
forall a b. (a -> b) -> a -> b
$ String
"Encountered closing sequence for \"" String -> String -> String
forall a. Semigroup a => a -> a -> a
<> DataIdentifier -> String
forall a. Show a => a -> String
show DataIdentifier
name String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
"\" which has never been opened."
continueFromTag (Tag Node Text
tag) = do
  STree
textNodes    <- Parsec Text MustacheState STree
flushText
  STree
furtherNodes <- Parsec Text MustacheState STree
parseText
  STree -> Parsec Text MustacheState STree
forall (m :: * -> *) a. Monad m => a -> m a
return (STree -> Parsec Text MustacheState STree)
-> STree -> Parsec Text MustacheState STree
forall a b. (a -> b) -> a -> b
$ STree
textNodes STree -> STree -> STree
forall a. Semigroup a => a -> a -> a
<> Node Text -> STree
forall (m :: * -> *) a. Monad m => a -> m a
return Node Text
tag STree -> STree -> STree
forall a. Semigroup a => a -> a -> a
<> STree
furtherNodes
continueFromTag ParseTagRes
HandledTag = Parsec Text MustacheState STree
parseText


switchOnTag :: Parser ParseTagRes
switchOnTag :: ParsecT Text MustacheState Identity ParseTagRes
switchOnTag = do
  (MustacheState { sDelimiters :: MustacheState -> (String, String)
sDelimiters = ( String
_, String
end )}) <- ParsecT Text MustacheState Identity MustacheState
forall (m :: * -> *) s u. Monad m => ParsecT s u m u
getState

  [ParsecT Text MustacheState Identity ParseTagRes]
-> ParsecT Text MustacheState Identity ParseTagRes
forall s (m :: * -> *) t u a.
Stream s m t =>
[ParsecT s u m a] -> ParsecT s u m a
choice
    [ Bool -> DataIdentifier -> ParseTagRes
SectionBegin Bool
False (DataIdentifier -> ParseTagRes)
-> ParsecT Text MustacheState Identity DataIdentifier
-> ParsecT Text MustacheState Identity ParseTagRes
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Parser Char -> Parser Char
forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try (Char -> Parser Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
sectionBegin) Parser Char
-> ParsecT Text MustacheState Identity DataIdentifier
-> ParsecT Text MustacheState Identity DataIdentifier
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> String -> ParsecT Text MustacheState Identity DataIdentifier
genParseTagEnd String
forall a. Monoid a => a
mempty)
    , DataIdentifier -> ParseTagRes
SectionEnd
        (DataIdentifier -> ParseTagRes)
-> ParsecT Text MustacheState Identity DataIdentifier
-> ParsecT Text MustacheState Identity ParseTagRes
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Parser Char -> Parser Char
forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try (Char -> Parser Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
sectionEnd) Parser Char
-> ParsecT Text MustacheState Identity DataIdentifier
-> ParsecT Text MustacheState Identity DataIdentifier
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> String -> ParsecT Text MustacheState Identity DataIdentifier
genParseTagEnd String
forall a. Monoid a => a
mempty)
    , Node Text -> ParseTagRes
Tag (Node Text -> ParseTagRes)
-> (DataIdentifier -> Node Text) -> DataIdentifier -> ParseTagRes
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Bool -> DataIdentifier -> Node Text
forall α. Bool -> DataIdentifier -> Node α
Variable Bool
False
        (DataIdentifier -> ParseTagRes)
-> ParsecT Text MustacheState Identity DataIdentifier
-> ParsecT Text MustacheState Identity ParseTagRes
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Parser Char -> Parser Char
forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try (Char -> Parser Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
unescape1) Parser Char
-> ParsecT Text MustacheState Identity DataIdentifier
-> ParsecT Text MustacheState Identity DataIdentifier
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> String -> ParsecT Text MustacheState Identity DataIdentifier
genParseTagEnd String
forall a. Monoid a => a
mempty)
    , Node Text -> ParseTagRes
Tag (Node Text -> ParseTagRes)
-> (DataIdentifier -> Node Text) -> DataIdentifier -> ParseTagRes
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Bool -> DataIdentifier -> Node Text
forall α. Bool -> DataIdentifier -> Node α
Variable Bool
False
        (DataIdentifier -> ParseTagRes)
-> ParsecT Text MustacheState Identity DataIdentifier
-> ParsecT Text MustacheState Identity ParseTagRes
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Parser Char -> Parser Char
forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try (Char -> Parser Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char ((Char, Char) -> Char
forall a b. (a, b) -> a
fst (Char, Char)
unescape2)) Parser Char
-> ParsecT Text MustacheState Identity DataIdentifier
-> ParsecT Text MustacheState Identity DataIdentifier
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> String -> ParsecT Text MustacheState Identity DataIdentifier
genParseTagEnd (Char -> String
forall (m :: * -> *) a. Monad m => a -> m a
return (Char -> String) -> Char -> String
forall a b. (a -> b) -> a -> b
$ (Char, Char) -> Char
forall a b. (a, b) -> b
snd (Char, Char)
unescape2))
    , Node Text -> ParseTagRes
Tag (Node Text -> ParseTagRes)
-> (String -> Node Text) -> String -> ParseTagRes
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Maybe Text -> String -> Node Text
forall α. Maybe α -> String -> Node α
Partial Maybe Text
forall a. Maybe a
Nothing
        (String -> ParseTagRes)
-> Parser String -> ParsecT Text MustacheState Identity ParseTagRes
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Parser Char -> Parser Char
forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try (Char -> Parser Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
partialBegin) Parser Char -> Parser () -> Parser ()
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Parser ()
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m ()
spaces Parser () -> Parser String -> Parser String
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> (String -> Parser Char
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m Char
noneOf (String -> String
forall a. Eq a => [a] -> [a]
nub String
end) Parser Char -> Parser String -> Parser String
forall s (m :: * -> *) t u a end.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m end -> ParsecT s u m [a]
`manyTill` Parser String -> Parser String
forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try (Parser ()
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m ()
spaces Parser () -> Parser String -> Parser String
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> String -> Parser String
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m String
string String
end)))
    , ParseTagRes -> ParsecT Text MustacheState Identity ParseTagRes
forall (m :: * -> *) a. Monad m => a -> m a
return ParseTagRes
HandledTag
        ParsecT Text MustacheState Identity ParseTagRes
-> Parser () -> ParsecT Text MustacheState Identity ParseTagRes
forall (m :: * -> *) b a. Monad m => m b -> m a -> m b
<< (Parser Char -> Parser Char
forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try (Char -> Parser Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
delimiterChange) Parser Char -> Parser () -> Parser ()
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Parser ()
parseDelimChange)
    , Bool -> DataIdentifier -> ParseTagRes
SectionBegin Bool
True
        (DataIdentifier -> ParseTagRes)
-> ParsecT Text MustacheState Identity DataIdentifier
-> ParsecT Text MustacheState Identity ParseTagRes
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Parser Char -> Parser Char
forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try (Char -> Parser Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
invertedSectionBegin) Parser Char
-> ParsecT Text MustacheState Identity DataIdentifier
-> ParsecT Text MustacheState Identity DataIdentifier
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> String -> ParsecT Text MustacheState Identity DataIdentifier
genParseTagEnd String
forall a. Monoid a => a
mempty ParsecT Text MustacheState Identity DataIdentifier
-> (DataIdentifier
    -> ParsecT Text MustacheState Identity DataIdentifier)
-> ParsecT Text MustacheState Identity DataIdentifier
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
              n :: DataIdentifier
n@(NamedData [Text]
_) -> DataIdentifier
-> ParsecT Text MustacheState Identity DataIdentifier
forall (m :: * -> *) a. Monad m => a -> m a
return DataIdentifier
n
              DataIdentifier
_ -> String -> ParsecT Text MustacheState Identity DataIdentifier
forall s u (m :: * -> *) a. String -> ParsecT s u m a
parserFail String
"Inverted Sections can not be implicit."
            )
    , ParseTagRes -> ParsecT Text MustacheState Identity ParseTagRes
forall (m :: * -> *) a. Monad m => a -> m a
return ParseTagRes
HandledTag ParsecT Text MustacheState Identity ParseTagRes
-> Parser String -> ParsecT Text MustacheState Identity ParseTagRes
forall (m :: * -> *) b a. Monad m => m b -> m a -> m b
<< (Parser Char -> Parser Char
forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try (Char -> Parser Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
comment) Parser Char -> Parser String -> Parser String
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Parser Char -> Parser String -> Parser String
forall s (m :: * -> *) t u a end.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m end -> ParsecT s u m [a]
manyTill Parser Char
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m Char
anyChar (Parser String -> Parser String
forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try (Parser String -> Parser String) -> Parser String -> Parser String
forall a b. (a -> b) -> a -> b
$ String -> Parser String
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m String
string String
end))
    , Node Text -> ParseTagRes
Tag (Node Text -> ParseTagRes)
-> (DataIdentifier -> Node Text) -> DataIdentifier -> ParseTagRes
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Bool -> DataIdentifier -> Node Text
forall α. Bool -> DataIdentifier -> Node α
Variable Bool
True
        (DataIdentifier -> ParseTagRes)
-> ParsecT Text MustacheState Identity DataIdentifier
-> ParsecT Text MustacheState Identity ParseTagRes
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> ParsecT Text MustacheState Identity DataIdentifier
genParseTagEnd String
forall a. Monoid a => a
mempty
    ]
  where
    parseDelimChange :: Parser ()
parseDelimChange = do
      (MustacheState { sDelimiters :: MustacheState -> (String, String)
sDelimiters = ( String
_, String
end )}) <- ParsecT Text MustacheState Identity MustacheState
forall (m :: * -> *) s u. Monad m => ParsecT s u m u
getState
      Parser ()
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m ()
spaces
      String
delim1 <- Parser Char
allowedDelimiterCharacter Parser Char -> Parser Char -> Parser String
forall s (m :: * -> *) t u a end.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m end -> ParsecT s u m [a]
`manyTill` Parser Char
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m Char
space
      Parser ()
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m ()
spaces
      String
delim2 <- Parser Char
allowedDelimiterCharacter Parser Char -> Parser String -> Parser String
forall s (m :: * -> *) t u a end.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m end -> ParsecT s u m [a]
`manyTill` Parser String -> Parser String
forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try (Parser ()
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m ()
spaces Parser () -> Parser String -> Parser String
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> String -> Parser String
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m String
string (Char
delimiterChange Char -> String -> String
forall a. a -> [a] -> [a]
: String
end))
      Bool -> Parser () -> Parser ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (String
delim1 String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== String
forall a. Monoid a => a
mempty Bool -> Bool -> Bool
|| String
delim2 String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== String
forall a. Monoid a => a
mempty)
        (Parser () -> Parser ()) -> Parser () -> Parser ()
forall a b. (a -> b) -> a -> b
$ String -> Parser ()
forall s u (m :: * -> *) a. String -> ParsecT s u m a
parserFail String
"Tags must contain more than 0 characters"
      MustacheState
oldState <- ParsecT Text MustacheState Identity MustacheState
forall (m :: * -> *) s u. Monad m => ParsecT s u m u
getState
      MustacheState -> Parser ()
forall (m :: * -> *) u s. Monad m => u -> ParsecT s u m ()
putState (MustacheState -> Parser ()) -> MustacheState -> Parser ()
forall a b. (a -> b) -> a -> b
$ MustacheState
oldState { sDelimiters :: (String, String)
sDelimiters = (String
delim1, String
delim2) }


genParseTagEnd :: String -> Parser DataIdentifier
genParseTagEnd :: String -> ParsecT Text MustacheState Identity DataIdentifier
genParseTagEnd String
emod = do
  (MustacheState { sDelimiters :: MustacheState -> (String, String)
sDelimiters = ( String
start, String
end ) }) <- ParsecT Text MustacheState Identity MustacheState
forall (m :: * -> *) s u. Monad m => ParsecT s u m u
getState

  let nEnd :: String
nEnd = String
emod String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
end
      disallowed :: String
disallowed = String -> String
forall a. Eq a => [a] -> [a]
nub (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ Char
nestingSeparator Char -> String -> String
forall a. a -> [a] -> [a]
: String
start String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
end

      parseOne :: Parser [Text]
      parseOne :: Parser [Text]
parseOne = do

        String
one <- String -> Parser Char
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m Char
noneOf String
disallowed
          Parser Char -> Parser () -> Parser String
forall s (m :: * -> *) t u a end.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m end -> ParsecT s u m [a]
`manyTill` Parser () -> Parser ()
forall s (m :: * -> *) t u a.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m a
lookAhead
            (Parser () -> Parser ()
forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try (Parser ()
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m ()
spaces Parser () -> Parser () -> Parser ()
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Parser String -> Parser ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (String -> Parser String
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m String
string String
nEnd))
            Parser () -> Parser () -> Parser ()
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> Parser () -> Parser ()
forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try (Parser Char -> Parser ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (Parser Char -> Parser ()) -> Parser Char -> Parser ()
forall a b. (a -> b) -> a -> b
$ Char -> Parser Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
nestingSeparator))

        [Text]
others <- (Char -> Parser Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
nestingSeparator Parser Char -> Parser [Text] -> Parser [Text]
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Parser [Text]
parseOne)
                  Parser [Text] -> Parser [Text] -> Parser [Text]
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> ([Text] -> String -> [Text]
forall a b. a -> b -> a
const [Text]
forall a. Monoid a => a
mempty (String -> [Text]) -> Parser String -> Parser [Text]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Parser ()
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m ()
spaces Parser () -> Parser String -> Parser String
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> String -> Parser String
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m String
string String
nEnd))
        [Text] -> Parser [Text]
forall (m :: * -> *) a. Monad m => a -> m a
return ([Text] -> Parser [Text]) -> [Text] -> Parser [Text]
forall a b. (a -> b) -> a -> b
$ String -> Text
pack String
one Text -> [Text] -> [Text]
forall a. a -> [a] -> [a]
: [Text]
others
  Parser ()
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m ()
spaces
  (Parser Char -> Parser Char
forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try (Char -> Parser Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
implicitIterator) Parser Char -> Parser () -> Parser ()
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Parser ()
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m ()
spaces Parser () -> Parser String -> Parser String
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> String -> Parser String
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m String
string String
nEnd Parser String
-> ParsecT Text MustacheState Identity DataIdentifier
-> ParsecT Text MustacheState Identity DataIdentifier
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> DataIdentifier
-> ParsecT Text MustacheState Identity DataIdentifier
forall (m :: * -> *) a. Monad m => a -> m a
return DataIdentifier
Implicit)
    ParsecT Text MustacheState Identity DataIdentifier
-> ParsecT Text MustacheState Identity DataIdentifier
-> ParsecT Text MustacheState Identity DataIdentifier
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> ([Text] -> DataIdentifier
NamedData ([Text] -> DataIdentifier)
-> Parser [Text]
-> ParsecT Text MustacheState Identity DataIdentifier
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser [Text]
parseOne)