packages feed

morloc-0.33.0: library/Morloc/Quasi.hs

{-# LANGUAGE TemplateHaskell, QuasiQuotes #-}

module Morloc.Quasi
  ( idoc
  ) where

import Language.Haskell.TH
import Language.Haskell.TH.Quote
import qualified Morloc.Data.Doc as G

import qualified Language.Haskell.Meta.Parse as MP

import Text.Parsec

type Parser = Parsec String ()

data I
  = S String
  | V String

pIs :: Parser [I]
pIs = many1 (try pV <|> try pS <|> try pE) <* eof

pV :: Parser I
pV = fmap V $ between (string "#{") (char '}') (many1 (noneOf "}"))

pS :: Parser I
pS = fmap S $ many1 (noneOf "#")

-- | match a literal '#' sign
pE :: Parser I
pE = fmap (S . return) $ char '#' <* notFollowedBy (char '}')

-- | __i__nterpolated __doc__ument
idoc :: QuasiQuoter
idoc =
  QuasiQuoter
    { quoteExp = compile
    , quotePat = error "Can't handle patterns"
    , quoteType = error "Can't handle types"
    , quoteDec = error "Can't handle declarations"
    }
  where
    compile :: String -> Q Exp
    compile txt =
      case parse pIs "" txt of
        Left err -> error $ show err
        Right xs -> return $ AppE (VarE 'G.hcat) (ListE (map qI xs))
          where qI :: I -> Exp
                qI (S x) = (LitE (StringL x))
                qI (V x) =
                  case MP.parseExp x of
                    (Right hask) -> hask -- a Haskell expression
                    (Left err) -> error err