module Zinza.Parser (parseTemplate) where

import Control.Applicative (many, optional, some, (<|>))
import Control.Monad       (void)
import Data.Char           (isAlphaNum, isLower)
import Data.List           (foldl')
import Text.Parsec
       (anyChar, eof, getPosition, lookAhead, notFollowedBy, parse, satisfy,
       try)
import Text.Parsec.Char    (char, space, spaces, string)
import Text.Parsec.Pos     (SourcePos, sourceColumn, sourceLine)
import Text.Parsec.String  (Parser)

import Zinza.Errors
import Zinza.Expr
import Zinza.Node
import Zinza.Pos
import Zinza.Var

-- | Parse template into nodes. No other than syntactic checks are performed.
parseTemplate
    :: FilePath  -- ^ name of the template
    -> String    -- ^ contents of the template
    -> Either ParseError (Nodes Var)
parseTemplate :: String -> String -> Either ParseError (Nodes String)
parseTemplate String
input String
contents
    = (ParseError -> Either ParseError (Nodes String))
-> (Nodes String -> Either ParseError (Nodes String))
-> Either ParseError (Nodes String)
-> Either ParseError (Nodes String)
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (ParseError -> Either ParseError (Nodes String)
forall a b. a -> Either a b
Left (ParseError -> Either ParseError (Nodes String))
-> (ParseError -> ParseError)
-> ParseError
-> Either ParseError (Nodes String)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ParseError
ParseError (String -> ParseError)
-> (ParseError -> String) -> ParseError -> ParseError
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ParseError -> String
forall a. Show a => a -> String
show) Nodes String -> Either ParseError (Nodes String)
forall a b. b -> Either a b
Right
    (Either ParseError (Nodes String)
 -> Either ParseError (Nodes String))
-> Either ParseError (Nodes String)
-> Either ParseError (Nodes String)
forall a b. (a -> b) -> a -> b
$ Parsec String () (Nodes String)
-> String -> String -> Either ParseError (Nodes String)
forall s t a.
Stream s Identity t =>
Parsec s () a -> String -> s -> Either ParseError a
parse (Parsec String () (Nodes String)
nodesP Parsec String () (Nodes String)
-> ParsecT String () Identity () -> Parsec String () (Nodes String)
forall a b.
ParsecT String () Identity a
-> ParsecT String () Identity b -> ParsecT String () Identity a
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 ()
eof) String
input String
contents

-------------------------------------------------------------------------------
-- Location
-------------------------------------------------------------------------------

toLoc :: SourcePos -> Loc
toLoc :: SourcePos -> Loc
toLoc SourcePos
p = Column -> Column -> Loc
Loc (SourcePos -> Column
sourceLine SourcePos
p) (SourcePos -> Column
sourceColumn SourcePos
p)

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

varP :: Parser Var
varP :: Parser String
varP = (:) (Char -> String -> String)
-> ParsecT String () Identity Char
-> ParsecT String () Identity (String -> String)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Char -> Bool) -> ParsecT String () Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
(Char -> Bool) -> ParsecT s u m Char
satisfy Char -> Bool
isLower ParsecT String () Identity (String -> String)
-> Parser String -> Parser String
forall a b.
ParsecT String () Identity (a -> b)
-> ParsecT String () Identity a -> ParsecT String () Identity b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> ParsecT String () Identity Char -> Parser String
forall a.
ParsecT String () Identity a -> ParsecT String () Identity [a]
forall (f :: * -> *) a. Alternative f => f a -> f [a]
many ((Char -> Bool) -> ParsecT String () Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
(Char -> Bool) -> ParsecT s u m Char
satisfy Char -> Bool
isVarChar)

locP :: Parser Loc
locP :: Parser Loc
locP = SourcePos -> Loc
toLoc (SourcePos -> Loc)
-> ParsecT String () Identity SourcePos -> Parser Loc
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ParsecT String () Identity SourcePos
forall (m :: * -> *) s u. Monad m => ParsecT s u m SourcePos
getPosition

located :: Parser a -> Parser (Located a)
located :: forall a. Parser a -> Parser (Located a)
located Parser a
p = do
    Loc
l <- Parser Loc
locP
    Loc -> a -> Located a
forall a. Loc -> a -> Located a
L Loc
l (a -> Located a) -> Parser a -> Parser (Located a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser a
p

locVarP :: Parser (Located Var)
locVarP :: Parser (Located String)
locVarP = Parser String -> Parser (Located String)
forall a. Parser a -> Parser (Located a)
located Parser String
varP

isVarChar :: Char -> Bool
isVarChar :: Char -> Bool
isVarChar Char
c = Char -> Bool
isAlphaNum Char
c Bool -> Bool -> Bool
|| Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'_'

nodeP :: Parser (Node Var)
nodeP :: Parser (Node String)
nodeP = Parser (Node String)
forall var. Parser (Node var)
commentP Parser (Node String)
-> Parser (Node String) -> Parser (Node String)
forall a.
ParsecT String () Identity a
-> ParsecT String () Identity a -> ParsecT String () Identity a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser (Node String)
directiveP Parser (Node String)
-> Parser (Node String) -> Parser (Node String)
forall a.
ParsecT String () Identity a
-> ParsecT String () Identity a -> ParsecT String () Identity a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser (Node String)
exprNodeP Parser (Node String)
-> Parser (Node String) -> Parser (Node String)
forall a.
ParsecT String () Identity a
-> ParsecT String () Identity a -> ParsecT String () Identity a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser (Node String)
newlineN Parser (Node String)
-> Parser (Node String) -> Parser (Node String)
forall a.
ParsecT String () Identity a
-> ParsecT String () Identity a -> ParsecT String () Identity a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser (Node String)
rawP

nodesP :: Parser (Nodes Var)
nodesP :: Parsec String () (Nodes String)
nodesP = Parser (Node String) -> Parsec String () (Nodes String)
forall a.
ParsecT String () Identity a -> ParsecT String () Identity [a]
forall (f :: * -> *) a. Alternative f => f a -> f [a]
many Parser (Node String)
nodeP

newlineN :: Parser (Node Var)
newlineN :: Parser (Node String)
newlineN = String -> Node String
forall a. String -> Node a
NRaw (String -> Node String) -> (Char -> String) -> Char -> Node String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> String
forall a. a -> [a]
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Char -> Node String)
-> ParsecT String () Identity Char -> Parser (Node String)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Char -> ParsecT String () Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
'\n'

rawP :: Parser (Node Var)
rawP :: Parser (Node String)
rawP = String -> Maybe Char -> Node String
forall {a}. String -> Maybe Char -> Node a
mk (String -> Maybe Char -> Node String)
-> Parser String
-> ParsecT String () Identity (Maybe Char -> Node String)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ParsecT String () Identity Char -> Parser String
forall a.
ParsecT String () Identity a -> ParsecT String () Identity [a]
forall (f :: * -> *) a. Alternative f => f a -> f [a]
some ParsecT String () Identity Char
forall {u}. ParsecT String u Identity Char
rawCharP ParsecT String () Identity (Maybe Char -> Node String)
-> ParsecT String () Identity (Maybe Char) -> Parser (Node String)
forall a b.
ParsecT String () Identity (a -> b)
-> ParsecT String () Identity a -> ParsecT String () Identity b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> ParsecT String () Identity Char
-> ParsecT String () Identity (Maybe Char)
forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional (Char -> ParsecT String () Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
'\n') where
    rawCharP :: ParsecT String u Identity Char
rawCharP   = ParsecT String u Identity Char
forall {u}. ParsecT String u Identity Char
notBrace ParsecT String u Identity Char
-> ParsecT String u Identity Char -> ParsecT String u Identity Char
forall a.
ParsecT String u Identity a
-> ParsecT String u Identity a -> ParsecT String u Identity a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> ParsecT String u Identity Char -> ParsecT String u Identity Char
forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try (Char -> ParsecT String u Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
'{' ParsecT String u Identity Char
-> ParsecT String u Identity Char -> ParsecT String u Identity Char
forall a b.
ParsecT String u Identity a
-> ParsecT String u Identity b -> ParsecT String u Identity a
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* ParsecT String u Identity Char -> ParsecT String u Identity Char
forall s (m :: * -> *) t u a.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m a
lookAhead ParsecT String u Identity Char
forall {u}. ParsecT String u Identity Char
notSpecial)
    notBrace :: ParsecT String u Identity Char
notBrace   = (Char -> Bool) -> ParsecT String u Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
(Char -> Bool) -> ParsecT s u m Char
satisfy ((Char -> Bool) -> ParsecT String u Identity Char)
-> (Char -> Bool) -> ParsecT String u Identity Char
forall a b. (a -> b) -> a -> b
$ \Char
c -> Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
/= Char
'{' Bool -> Bool -> Bool
&& Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
/= Char
'\n'
    notSpecial :: ParsecT String u Identity Char
notSpecial = (Char -> Bool) -> ParsecT String u Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
(Char -> Bool) -> ParsecT s u m Char
satisfy ((Char -> Bool) -> ParsecT String u Identity Char)
-> (Char -> Bool) -> ParsecT String u Identity Char
forall a b. (a -> b) -> a -> b
$ \Char
c -> Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
/= Char
'{' Bool -> Bool -> Bool
&& Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
/= Char
'%' Bool -> Bool -> Bool
&& Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
/= Char
'#'

    mk :: String -> Maybe Char -> Node a
mk String
s Maybe Char
Nothing  = String -> Node a
forall a. String -> Node a
NRaw String
s
    mk String
s (Just Char
c) = String -> Node a
forall a. String -> Node a
NRaw (String
s String -> String -> String
forall a. [a] -> [a] -> [a]
++ [Char
c])

exprNodeP :: Parser (Node Var)
exprNodeP :: Parser (Node String)
exprNodeP = do
    String
_ <- 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
"{{")
    ParsecT String () Identity ()
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m ()
spaces
    LExpr String
expr <- Parser (LExpr String)
exprP
    ParsecT String () Identity ()
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m ()
spaces
    String
_ <- String -> Parser String
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m String
string String
"}}"
    Node String -> Parser (Node String)
forall a. a -> ParsecT String () Identity a
forall (m :: * -> *) a. Monad m => a -> m a
return (LExpr String -> Node String
forall a. LExpr a -> Node a
NExpr LExpr String
expr)

exprP :: Parser (LExpr Var)
exprP :: Parser (LExpr String)
exprP = do
    LExpr String
expr <- Parser (LExpr String)
primitiveExprP
    [LExpr String]
exprs <- Parser (LExpr String) -> ParsecT String () Identity [LExpr String]
forall a.
ParsecT String () Identity a -> ParsecT String () Identity [a]
forall (f :: * -> *) a. Alternative f => f a -> f [a]
many Parser (LExpr String)
primitiveExprP
    LExpr String -> Parser (LExpr String)
forall a. a -> ParsecT String () Identity a
forall (m :: * -> *) a. Monad m => a -> m a
return (LExpr String -> Parser (LExpr String))
-> LExpr String -> Parser (LExpr String)
forall a b. (a -> b) -> a -> b
$ (LExpr String -> LExpr String -> LExpr String)
-> LExpr String -> [LExpr String] -> LExpr String
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' (\f :: LExpr String
f@(L Loc
l Expr String
_) LExpr String
x -> Loc -> Expr String -> LExpr String
forall a. Loc -> a -> Located a
L Loc
l (LExpr String -> LExpr String -> Expr String
forall a. LExpr a -> LExpr a -> Expr a
EApp LExpr String
f LExpr String
x)) LExpr String
expr [LExpr String]
exprs

primitiveExprP :: Parser (LExpr Var)
primitiveExprP :: Parser (LExpr String)
primitiveExprP = Parser (LExpr String) -> Parser (LExpr String)
forall a. Parser a -> Parser a
parens Parser (LExpr String)
exprP Parser (LExpr String)
-> Parser (LExpr String) -> Parser (LExpr String)
forall a.
ParsecT String () Identity a
-> ParsecT String () Identity a -> ParsecT String () Identity a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser (Expr String) -> Parser (LExpr String)
forall a. Parser a -> Parser (Located a)
located Parser (Expr String)
primitiveExprP'

parens :: Parser a -> Parser a
parens :: forall a. Parser a -> Parser a
parens Parser a
p = do
    Char
_ <- Char -> ParsecT String () Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
'('
    ParsecT String () Identity ()
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m ()
spaces
    a
x <- Parser a
p
    Char
_ <- Char -> ParsecT String () Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
')'
    ParsecT String () Identity ()
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m ()
spaces
    a -> Parser a
forall a. a -> ParsecT String () Identity a
forall (m :: * -> *) a. Monad m => a -> m a
return a
x

primitiveExprP' :: Parser (Expr Var)
primitiveExprP' :: Parser (Expr String)
primitiveExprP' = do
    v :: Located String
v@(L Loc
l String
_) <- Parser (Located String)
locVarP
    [Located String]
vs <- Parser (Located String)
-> ParsecT String () Identity [Located String]
forall a.
ParsecT String () Identity a -> ParsecT String () Identity [a]
forall (f :: * -> *) a. Alternative f => f a -> f [a]
many (Char -> ParsecT String () Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
'.' ParsecT String () Identity Char
-> Parser (Located String) -> Parser (Located String)
forall a b.
ParsecT String () Identity a
-> ParsecT String () Identity b -> ParsecT String () Identity b
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Parser (Located String)
locVarP)
    ParsecT String () Identity ()
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m ()
spaces
    let expr :: Expr String
expr = (Expr String -> Located String -> Expr String)
-> Expr String -> [Located String] -> Expr String
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl (\Expr String
e Located String
f -> LExpr String -> Located String -> Expr String
forall a. LExpr a -> Located String -> Expr a
EField (Loc -> Expr String -> LExpr String
forall a. Loc -> a -> Located a
L Loc
l Expr String
e) Located String
f) (Located String -> Expr String
forall a. Located a -> Expr a
EVar Located String
v) [Located String]
vs
    Expr String -> Parser (Expr String)
forall a. a -> ParsecT String () Identity a
forall (m :: * -> *) a. Monad m => a -> m a
return Expr String
expr

commentP :: Parser (Node var)
commentP :: forall var. Parser (Node var)
commentP = do
    SourcePos
pos <- ParsecT String () Identity SourcePos
forall (m :: * -> *) s u. Monad m => ParsecT s u m SourcePos
getPosition
    String
_ <- 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
"{#")
    SourcePos -> Parser (Node var)
forall {a}. SourcePos -> ParsecT String () Identity (Node a)
go SourcePos
pos
  where
    go :: SourcePos -> ParsecT String () Identity (Node a)
go SourcePos
pos = do
        Char
c <- ParsecT String () Identity Char
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m Char
anyChar
        case Char
c of
            Char
'#' -> do
                Char
c' <- ParsecT String () Identity Char
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m Char
anyChar
                case Char
c' of
                    Char
'}' -> Node a
forall a. Node a
NComment Node a
-> ParsecT String () Identity ()
-> ParsecT String () Identity (Node a)
forall a b.
a -> ParsecT String () Identity b -> ParsecT String () Identity a
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ Bool -> ParsecT String () Identity ()
eatNewlineWhen (SourcePos -> Column
sourceColumn SourcePos
pos Column -> Column -> Bool
forall a. Eq a => a -> a -> Bool
== Column
1)
                    Char
_   -> SourcePos -> ParsecT String () Identity (Node a)
go SourcePos
pos
            Char
_   -> SourcePos -> ParsecT String () Identity (Node a)
go SourcePos
pos

eatNewlineWhen :: Bool -> Parser ()
eatNewlineWhen :: Bool -> ParsecT String () Identity ()
eatNewlineWhen Bool
False = () -> ParsecT String () Identity ()
forall a. a -> ParsecT String () Identity a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
eatNewlineWhen Bool
True  = ParsecT String () Identity (Maybe Char)
-> ParsecT String () Identity ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (ParsecT String () Identity Char
-> ParsecT String () Identity (Maybe Char)
forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional (Char -> ParsecT String () Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
'\n'))

directiveP :: Parser (Node Var)
directiveP :: Parser (Node String)
directiveP = Parser (Node String)
forP Parser (Node String)
-> Parser (Node String) -> Parser (Node String)
forall a.
ParsecT String () Identity a
-> ParsecT String () Identity a -> ParsecT String () Identity a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser (Node String)
ifP Parser (Node String)
-> Parser (Node String) -> Parser (Node String)
forall a.
ParsecT String () Identity a
-> ParsecT String () Identity a -> ParsecT String () Identity a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser (Node String)
defBlockP Parser (Node String)
-> Parser (Node String) -> Parser (Node String)
forall a.
ParsecT String () Identity a
-> ParsecT String () Identity a -> ParsecT String () Identity a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser (Node String)
useBlockP

spaces1 :: Parser ()
spaces1 :: ParsecT String () Identity ()
spaces1 = ParsecT String () Identity Char
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m Char
space ParsecT String () Identity Char
-> ParsecT String () Identity () -> ParsecT String () Identity ()
forall a b.
ParsecT String () Identity a
-> ParsecT String () Identity b -> ParsecT String () Identity b
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> ParsecT String () Identity ()
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m ()
spaces

open :: String -> Parser Bool
open :: String -> Parser Bool
open String
n = do
    SourcePos
pos <- ParsecT String () Identity SourcePos
forall (m :: * -> *) s u. Monad m => ParsecT s u m SourcePos
getPosition
    ()
_ <- ParsecT String () Identity () -> ParsecT String () Identity ()
forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try (ParsecT String () Identity () -> ParsecT String () Identity ())
-> ParsecT String () Identity () -> ParsecT String () Identity ()
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
"{%" Parser String
-> ParsecT String () Identity () -> ParsecT String () Identity ()
forall a b.
ParsecT String () Identity a
-> ParsecT String () Identity b -> ParsecT String () Identity b
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> ParsecT String () Identity ()
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m ()
spaces ParsecT String () Identity () -> Parser String -> Parser String
forall a b.
ParsecT String () Identity a
-> ParsecT String () Identity b -> ParsecT String () Identity b
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> String -> Parser String
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m String
string String
n Parser String
-> ParsecT String () Identity () -> ParsecT String () Identity ()
forall a b.
ParsecT String () Identity a
-> ParsecT String () Identity b -> ParsecT String () Identity b
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> ParsecT String () Identity ()
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m ()
spaces
    Bool -> Parser Bool
forall a. a -> ParsecT String () Identity a
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool -> Parser Bool) -> Bool -> Parser Bool
forall a b. (a -> b) -> a -> b
$ SourcePos -> Column
sourceColumn SourcePos
pos Column -> Column -> Bool
forall a. Eq a => a -> a -> Bool
== Column
1  -- parsec counts pos from 1, not zero.

close :: String -> Parser ()
close :: String -> ParsecT String () Identity ()
close String
n = do
    Bool
on0 <- String -> Parser Bool
open (String
"end" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
n)
    Bool -> ParsecT String () Identity ()
close' Bool
on0

close' :: Bool -> Parser ()
close' :: Bool -> ParsecT String () Identity ()
close' Bool
on0 = do
    String
_ <- String -> Parser String
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m String
string String
"%}"
    Bool -> ParsecT String () Identity ()
eatNewlineWhen Bool
on0

forP :: Parser (Node Var)
forP :: Parser (Node String)
forP = do
    Bool
on0 <- String -> Parser Bool
open String
"for"
    String
var <- Parser String
varP
    ParsecT String () Identity ()
spaces1
    String
_ <- String -> Parser String
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m String
string String
"in"
    ParsecT String () Identity Char -> ParsecT String () Identity ()
forall s (m :: * -> *) t a u.
(Stream s m t, Show a) =>
ParsecT s u m a -> ParsecT s u m ()
notFollowedBy (ParsecT String () Identity Char -> ParsecT String () Identity ())
-> ParsecT String () Identity Char -> ParsecT String () Identity ()
forall a b. (a -> b) -> a -> b
$ (Char -> Bool) -> ParsecT String () Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
(Char -> Bool) -> ParsecT s u m Char
satisfy Char -> Bool
isAlphaNum
    ParsecT String () Identity ()
spaces1
    LExpr String
expr <- Parser (LExpr String)
exprP
    Bool -> ParsecT String () Identity ()
close' Bool
on0
    Nodes String
ns <- Parsec String () (Nodes String)
nodesP
    String -> ParsecT String () Identity ()
close String
"for"
    Node String -> Parser (Node String)
forall a. a -> ParsecT String () Identity a
forall (m :: * -> *) a. Monad m => a -> m a
return (Node String -> Parser (Node String))
-> Node String -> Parser (Node String)
forall a b. (a -> b) -> a -> b
$ String -> LExpr String -> Nodes (Maybe String) -> Node String
forall a. String -> LExpr a -> Nodes (Maybe a) -> Node a
NFor String
var LExpr String
expr (String -> Node String -> Node (Maybe String)
forall (f :: * -> *) a.
(Functor f, Eq a) =>
a -> f a -> f (Maybe a)
abstract1 String
var (Node String -> Node (Maybe String))
-> Nodes String -> Nodes (Maybe String)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Nodes String
ns)

ifP :: Parser (Node Var)
ifP :: Parser (Node String)
ifP = do
    Bool
on0 <- String -> Parser Bool
open String
"if"
    LExpr String
expr <- Parser (LExpr String)
exprP
    Bool -> ParsecT String () Identity ()
close' Bool
on0
    Nodes String
ns <- Parsec String () (Nodes String)
nodesP
    (Nodes String -> Node String) -> Parser (Node String)
forall {a}. (Nodes String -> a) -> ParsecT String () Identity a
closing (LExpr String -> Nodes String -> Nodes String -> Node String
forall a. LExpr a -> Nodes a -> Nodes a -> Node a
NIf LExpr String
expr Nodes String
ns)
  where
    closing :: (Nodes String -> a) -> ParsecT String () Identity a
closing Nodes String -> a
mk = (Nodes String -> a) -> ParsecT String () Identity a
forall {a} {b}. ([a] -> b) -> ParsecT String () Identity b
closeIf Nodes String -> a
mk ParsecT String () Identity a
-> ParsecT String () Identity a -> ParsecT String () Identity a
forall a.
ParsecT String () Identity a
-> ParsecT String () Identity a -> ParsecT String () Identity a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> (Nodes String -> a) -> ParsecT String () Identity a
elifP Nodes String -> a
mk ParsecT String () Identity a
-> ParsecT String () Identity a -> ParsecT String () Identity a
forall a.
ParsecT String () Identity a
-> ParsecT String () Identity a -> ParsecT String () Identity a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> (Nodes String -> a) -> ParsecT String () Identity a
forall {a}. (Nodes String -> a) -> ParsecT String () Identity a
elseP Nodes String -> a
mk

    closeIf :: ([a] -> b) -> ParsecT String () Identity b
closeIf [a] -> b
mk = do
        String -> ParsecT String () Identity ()
close String
"if"
        b -> ParsecT String () Identity b
forall a. a -> ParsecT String () Identity a
forall (m :: * -> *) a. Monad m => a -> m a
return ([a] -> b
mk [])

    elseP :: (Nodes String -> b) -> ParsecT String () Identity b
elseP Nodes String -> b
mk = do
        Bool
on0 <- String -> Parser Bool
open String
"else"
        Bool -> ParsecT String () Identity ()
close' Bool
on0
        Nodes String
ns <- Parsec String () (Nodes String)
nodesP
        String -> ParsecT String () Identity ()
close String
"if"
        b -> ParsecT String () Identity b
forall a. a -> ParsecT String () Identity a
forall (m :: * -> *) a. Monad m => a -> m a
return (Nodes String -> b
mk Nodes String
ns)

    elifP :: (Nodes String -> a) -> ParsecT String () Identity a
elifP Nodes String -> a
mk = do
        Bool
on0 <- String -> Parser Bool
open String
"elif"
        LExpr String
expr <- Parser (LExpr String)
exprP
        Bool -> ParsecT String () Identity ()
close' Bool
on0
        Nodes String
ns <- Parsec String () (Nodes String)
nodesP
        (Nodes String -> a) -> ParsecT String () Identity a
closing (Nodes String -> a
mk (Nodes String -> a)
-> (Nodes String -> Nodes String) -> Nodes String -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Node String -> Nodes String
forall a. a -> [a]
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Node String -> Nodes String)
-> (Nodes String -> Node String) -> Nodes String -> Nodes String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. LExpr String -> Nodes String -> Nodes String -> Node String
forall a. LExpr a -> Nodes a -> Nodes a -> Node a
NIf LExpr String
expr Nodes String
ns)

defBlockP :: Parser (Node Var)
defBlockP :: Parser (Node String)
defBlockP = do
    Loc
l <- Parser Loc
locP
    Bool
on0 <- String -> Parser Bool
open String
"defblock"
    String
var <- Parser String
varP
    ParsecT String () Identity ()
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m ()
spaces
    Bool -> ParsecT String () Identity ()
close' Bool
on0
    Nodes String
ns <- Parsec String () (Nodes String)
nodesP
    String -> ParsecT String () Identity ()
close String
"block"
    Node String -> Parser (Node String)
forall a. a -> ParsecT String () Identity a
forall (m :: * -> *) a. Monad m => a -> m a
return (Loc -> String -> Nodes String -> Node String
forall a. Loc -> String -> Nodes a -> Node a
NDefBlock Loc
l String
var Nodes String
ns)

useBlockP :: Parser (Node Var)
useBlockP :: Parser (Node String)
useBlockP = do
    Loc
l <- Parser Loc
locP
    Bool
on0 <- String -> Parser Bool
open String
"useblock"
    String
var <- Parser String
varP
    ParsecT String () Identity ()
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m ()
spaces
    Bool -> ParsecT String () Identity ()
close' Bool
on0
    Node String -> Parser (Node String)
forall a. a -> ParsecT String () Identity a
forall (m :: * -> *) a. Monad m => a -> m a
return (Loc -> String -> Node String
forall a. Loc -> String -> Node a
NUseBlock Loc
l String
var)