{- | this module provides a QuasiQuoter that supports the HSX syntax.

-- Module      :  Language.Haskell.HSX.Tranform
-- Copyright   :  (c) Niklas Broberg 2004-2012
-- License     :  BSD-style (see the file LICENSE.txt)
-- Maintainer  :  Niklas Broberg, niklas.broberg@gmail.com
-- Stability   :  experimental
-- Portability :  portable

You will need to enable the QuasiQuotes extension for it to work, which you can do by adding this to the top of your file:

    {-\# LANGUAGE QuasiQuotes \#-}

Here is a simple example that generates an HTML fragment:

> import Data.Char        (toUpper)
> import HSX.QQ           (hsx)
> import HSX.XMLGenerator
> html :: (XMLGenerator m) => XMLGenT m (XMLType m)
> html = [hsx| <p><% map toUpper "hello, world!"  %></p> |]

The syntax used by the hsx QuasiQuoter is the same as what is used by
@trhsx@. It is mostly normal XML syntax which a few key differences:

 1. strings inside tags and attributes are automatically escaped -- you do not need to do &lt;, etc.

 2. The <% %> syntax is used to embed the result of evaluating a Haskell expression into the XML

Values are embedde using the 'EmbedAsChild' and 'EmbedAsAttr'
classes. Additional instances can be added to support application
specific types.

module Language.Haskell.HSX.QQ
    ( hsx

import qualified Language.Haskell.Exts.Syntax           as Hs
import           Language.Haskell.Exts                  hiding (Exp, parse, parseExp)
import           Language.Haskell.HSX.Transform         (transformExp)
import           Language.Haskell.Meta.Parse            hiding (parseHsExp, parseExp)
import           Language.Haskell.Meta.Syntax.Translate (toExp)
import           Language.Haskell.TH                    (Exp, ExpQ)
import           Language.Haskell.TH.Quote              (QuasiQuoter(..))

-- | QuasiQuoter which can be used to parse HSX syntax
hsx :: QuasiQuoter
hsx = QuasiQuoter { quoteExp  = parseHsxExp
                  , quotePat  = error "the hsx QuasiQuoter can only be used on expressions."
                  , quoteType = error "the hsx QuasiQuoter can only be used on expressions."
                  , quoteDec  = error "the hsx QuasiQuoter can only be used on expressions."

parseHsxExp :: String -> ExpQ
parseHsxExp = either (error . show) (return . toExp . transformExp) . parseHsExp

parseExp :: String -> Either String Exp
parseExp = either Left (Right . toExp . transformExp) . parseHsExp

parseHsExp :: String -> Either String Hs.Exp
parseHsExp = either Left (Right . transformExp) . parseResultToEither . parseExpWithMode parseMode

parseMode :: ParseMode
parseMode = ParseMode "" allExtensions False True (Just baseFixities)

allExtensions :: [Extension]
allExtensions =