parsePrologExp :: (Data a, Lift a) => ParsecT [Char] () Identity a -> String -> String -> Q Exp
parsePrologExp parser name str = do
   case parse (whitespace >> parser <* eof) ("(Prolog " ++ name ++ " expression)") str of
      Right x -> const (fail $ "Quasi-quoted expressions of type " ++ show (typeOf x) ++ " are not implemented.")
          `extQ` unquote                     -- Term
          `extQ` (listE . map unquote)       -- [Term]
          `extQ` unquoteClause               -- Clause
          `extQ` (listE . map unquoteClause) -- [Clause]
           $ x
      Left e -> fail (show e)
  where
   unquote (Struct "$" [Struct var []]) =
                             [e| Struct (show $(varE (mkName var))) [] |]
   unquote (Struct "$" _)  = fail "Found '$' with non-unquotable arguments"
   unquote (Struct a   ts) = [e| Struct a $(listE $ map unquote ts) |]
   unquote t               = lift t

   unquoteClause (Clause lhs rhs) =
      [e| Clause $(unquote lhs) $(listE $ map unquote rhs) |]
   unquoteClause (ClauseFn _ _) =
      fail "Clauses using Haskell functions are not quasi-quotable."
parsePrologExp :: (Data a, Lift a) => ParsecT [Char] () Identity a -> String -> String -> Q Exp
parsePrologExp parser name str = do
   case parse (whitespace >> parser <* eof) ("(Prolog " ++ name ++ " expression)") str of
      Right x -> const (fail $ "Quasi-quoted expressions of type " ++ show (typeOf x) ++ " are not implemented.")
          `extQ` unquote                     -- Term
          `extQ` (listE . map unquote)       -- [Term]
          `extQ` unquoteClause               -- Clause
          `extQ` (listE . map unquoteClause) -- [Clause]
           $ x
      Left e -> fail (show e)
  where
   unquote (Struct "$" [Struct var []]) =
                             [e| Struct (show $(varE (mkName var))) [] |]
   unquote (Struct "$" _)  = fail "Found '$' with non-unquotable arguments"
   unquote (Struct a   ts) = [e| Struct a $(listE $ map unquote ts) |]
   unquote t               = lift t

   unquoteClause (Clause lhs rhs) =
      [e| Clause $(unquote lhs) $(listE $ map unquote rhs) |]
   unquoteClause (ClauseFn _ _) =
      fail "Clauses using Haskell functions are not quasi-quotable."
parsePrologExp parser name str = do
   case parse (whitespace >> parser <* eof) ("(Prolog " ++ name ++ " expression)") str of
      Right x -> const (fail $ "Quasi-quoted expressions of type " ++ show (typeOf x) ++ " are not implemented.")
          `extQ` unquote                     -- Term
          `extQ` (listE . map unquote)       -- [Term]
          `extQ` unquoteClause               -- Clause
          `extQ` (listE . map unquoteClause) -- [Clause]
           $ x
      Left e -> fail (show e)
  where
   unquote (Struct "$" [Struct var []]) =
                             [e| Struct (show $(varE (mkName var))) [] |]
   unquote (Struct "$" _)  = fail "Found '$' with non-unquotable arguments"
   unquote (Struct a   ts) = [e| Struct a $(listE $ map unquote ts) |]
   unquote t               = lift t

   unquoteClause (Clause lhs rhs) =
      [e| Clause $(unquote lhs) $(listE $ map unquote rhs) |]
   unquoteClause (ClauseFn _ _) =
      fail "Clauses using Haskell functions are not quasi-quotable."