module RlangQQ.Antiquote (extractAntiquotes) where

import Language.Haskell.Meta
import Language.Haskell.TH
import Text.Trifecta
import Control.Applicative

extractAntiquotes :: Parser [Either Exp String]
extractAntiquotes = do
    a <- Right <$> many (noneOf "$")
    bc <- do
        string "$"
        b <- try (Left <$> antiquote) <|> pure (Right "$")
        c <- extractAntiquotes
        return (b:c)
      <|> ([] <$ eof)
    return (a:bc)

antiquote = do
    string "("
    firstExp ""

-- | repeatedly try 'parseExp' on input ending (not including) @)@, until the first success.
firstExp prev = do
    c <- many (noneOf ")")
    string ")"
    let cs = prev ++ c -- appending is the least of efficiency concerns here
                       -- chances are that you only have a couple ')' characters
                       -- inside the $(  ) at most.
    case parseExp cs of
        Right x -> return x
        _ -> firstExp (cs ++ ")")