    -- | Raw string literals, implemented using Template Haskell's quasiquotation
    -- feature.
    module Text.RawString.QQ (r, rQ)
           where

    import Language.Haskell.TH
    import Language.Haskell.TH.Quote

    {-|

    A quasiquoter for raw string literals - that is, string literals that don't
    recognise the standard escape sequences (such as @\'\\n\'@). Basically, they
    make your code more readable by freeing you from the responsibility to escape
    backslashes. They are useful when working with regular expressions, DOS/Windows
    paths and markup languages (such as XML).

    Don't forget the @LANGUAGE QuasiQuotes@ pragma if you're using this
    module in your code.

    Usage:

    @
        ghci> :set -XQuasiQuotes
        ghci> import Text.RawString.QQ
        ghci> let s = [r|\\w+\@[a-zA-Z_]+?\\.[a-zA-Z]{2,3}|]
        ghci> s
        \"\\\\w+\@[a-zA-Z_]+?\\\\.[a-zA-Z]{2,3}\"
        ghci> [r|C:\\Windows\\SYSTEM|] ++ [r|\\user32.dll|]
        \"C:\\\\Windows\\\\SYSTEM\\\\user32.dll\"
    @

    Multiline raw string literals are also supported:

    @
        multiline :: String
        multiline = [r|\<HTML\>
        \<HEAD\>
        \<TITLE\>Auto-generated html formated source\</TITLE\>
        \<META HTTP-EQUIV=\"Content-Type\" CONTENT=\"text/html; charset=windows-1252\"\>
        \</HEAD\>
        \<BODY LINK=\"#0000ff\" VLINK=\"#800080\" BGCOLOR=\"#ffffff\"\>
        \<P\> \</P\>
        \<PRE\>|]
    @

    Caveat: since the @\"|]\"@ character sequence is used to terminate the
    quasiquotation, you can't use it inside the raw string literal. Use 'rQ' if you
    want to embed that character sequence inside the raw string.

    For more on raw strings, see e.g.
    <http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2053.html>

    For more on quasiquotation, see
    <http://www.haskell.org/haskellwiki/Quasiquotation>

    -}
    r :: QuasiQuoter
    r :: QuasiQuoter
    r = QuasiQuoter {
        -- Extracted from dead-simple-json.
        quoteExp :: String -> Q Exp
    quoteExp  = Exp -> Q Exp
    forall a. a -> Q a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Exp -> Q Exp) -> (String -> Exp) -> String -> Q Exp
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Lit -> Exp
    LitE (Lit -> Exp) -> (String -> Lit) -> String -> Exp
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . String -> Lit
    StringL (String -> Lit) -> (String -> String) -> String -> Lit
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . String -> String
    normaliseNewlines,

        quotePat :: String -> Q Pat
    quotePat  = \String
    _ -> String -> Q Pat
    forall a. String -> Q a
    forall (m :: * -> *) a. MonadFail m => String -> m a
    fail String
    "illegal raw string QuasiQuote \
                               \(allowed as expression only, used as a pattern)",
        quoteType :: String -> Q Type
    quoteType = \String
    _ -> String -> Q Type
    forall a. String -> Q a
    forall (m :: * -> *) a. MonadFail m => String -> m a
    fail String
    "illegal raw string QuasiQuote \
                               \(allowed as expression only, used as a type)",
        quoteDec :: String -> Q [Dec]
    quoteDec  = \String
    _ -> String -> Q [Dec]
    forall a. String -> Q a
    forall (m :: * -> *) a. MonadFail m => String -> m a
    fail String
    "illegal raw string QuasiQuote \
                               \(allowed as expression only, used as a declaration)"
    }

    {-| A variant of 'r' that interprets the @\"|~]\"@ sequence as @\"|]\"@,
    @\"|~~]\"@ as @\"|~]\"@ and, in general, @\"|~^n]\"@ as @\"|~^(n-1)]\"@
    for n >= 1.

    Usage:

    @
        ghci> [rQ||~]|~]|]
        \"|]|]\"
        ghci> [rQ||~~]|]
        \"|~]\"
        ghci> [rQ||~~~~]|]
        \"|~~~]\"
    @
    -}
    rQ :: QuasiQuoter
    rQ :: QuasiQuoter
    rQ = QuasiQuoter {
        quoteExp :: String -> Q Exp
    quoteExp  = Exp -> Q Exp
    forall a. a -> Q a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Exp -> Q Exp) -> (String -> Exp) -> String -> Q Exp
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Lit -> Exp
    LitE (Lit -> Exp) -> (String -> Lit) -> String -> Exp
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . String -> Lit
    StringL (String -> Lit) -> (String -> String) -> String -> Lit
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . String -> String
    escape_rQ (String -> String) -> (String -> String) -> String -> String
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . String -> String
    normaliseNewlines,

        quotePat :: String -> Q Pat
    quotePat  = \String
    _ -> String -> Q Pat
    forall a. String -> Q a
    forall (m :: * -> *) a. MonadFail m => String -> m a
    fail String
    "illegal raw string QuasiQuote \
                               \(allowed as expression only, used as a pattern)",
        quoteType :: String -> Q Type
    quoteType = \String
    _ -> String -> Q Type
    forall a. String -> Q a
    forall (m :: * -> *) a. MonadFail m => String -> m a
    fail String
    "illegal raw string QuasiQuote \
                               \(allowed as expression only, used as a type)",
        quoteDec :: String -> Q [Dec]
    quoteDec  = \String
    _ -> String -> Q [Dec]
    forall a. String -> Q a
    forall (m :: * -> *) a. MonadFail m => String -> m a
    fail String
    "illegal raw string QuasiQuote \
                               \(allowed as expression only, used as a declaration)"
    }

    escape_rQ :: String -> String
    escape_rQ :: String -> String
    escape_rQ [] = []
    escape_rQ (Char
    '|':Char
    '~':String
    xs) =
      let (String
    tildas, String
    rest) = (Char -> Bool) -> String -> (String, String)
    forall a. (a -> Bool) -> [a] -> ([a], [a])
    span (Char -> Char -> Bool
    forall a. Eq a => a -> a -> Bool
    == Char
    '~') String
    xs
      in case String
    rest of
        []       -> Char
    '|'Char -> String -> String
    forall a. a -> [a] -> [a]
    :Char
    '~'Char -> String -> String
    forall a. a -> [a] -> [a]
    :String
    tildas
        (Char
    ']':String
    rs) -> Char
    '|'Char -> String -> String
    forall a. a -> [a] -> [a]
    :String
    tildas String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ Char
    ']'Char -> String -> String
    forall a. a -> [a] -> [a]
    :String -> String
    escape_rQ String
    rs
        String
    rs       -> Char
    '|'Char -> String -> String
    forall a. a -> [a] -> [a]
    :Char
    '~'Char -> String -> String
    forall a. a -> [a] -> [a]
    :String
    tildas String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ String -> String
    escape_rQ String
    rs
    escape_rQ (Char
    x:String
    xs) = Char
    x Char -> String -> String
    forall a. a -> [a] -> [a]
    : String -> String
    escape_rQ String
    xs

    -- See https://github.com/23Skidoo/raw-strings-qq/issues/1 and
    -- https://ghc.haskell.org/trac/ghc/ticket/11215.
    normaliseNewlines :: String -> String
    normaliseNewlines :: String -> String
    normaliseNewlines []             = []
    normaliseNewlines (Char
    '\r':Char
    '\n':String
    cs) = Char
    '\n'Char -> String -> String
    forall a. a -> [a] -> [a]
    :String -> String
    normaliseNewlines String
    cs
    normaliseNewlines (Char
    c:String
    cs)         = Char
    cChar -> String -> String
    forall a. a -> [a] -> [a]
    :String -> String
    normaliseNewlines String
    cs