{-# OPTIONS #-}
module Language.Python.Common.StringEscape (
unescapeString,
unescapeRawString,
octalDigits,
hexDigits) where
import Numeric (readHex, readOct)
unescapeString :: String -> String
unescapeString :: String -> String
unescapeString ('\\':'\\':cs :: String
cs) = '\\' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
unescapeString String
cs
unescapeString ('\\':'\'':cs :: String
cs) = '\'' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
unescapeString String
cs
unescapeString ('\\':'"':cs :: String
cs) = '"' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
unescapeString String
cs
unescapeString ('\\':'a':cs :: String
cs) = '\a' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
unescapeString String
cs
unescapeString ('\\':'b':cs :: String
cs) = '\b' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
unescapeString String
cs
unescapeString ('\\':'f':cs :: String
cs) = '\f' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
unescapeString String
cs
unescapeString ('\\':'n':cs :: String
cs) = '\n' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
unescapeString String
cs
unescapeString ('\\':'r':cs :: String
cs) = '\r' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
unescapeString String
cs
unescapeString ('\\':'t':cs :: String
cs) = '\t' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
unescapeString String
cs
unescapeString ('\\':'v':cs :: String
cs) = '\v' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
unescapeString String
cs
unescapeString ('\\':'\n':cs :: String
cs) = String -> String
unescapeString String
cs
unescapeString ('\\':rest :: String
rest@(o :: Char
o:_))
| Char
o Char -> String -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` String
octalDigits = Int -> String -> (String -> Int) -> String -> String
unescapeNumeric 3 String
octalDigits ((Int, String) -> Int
forall a b. (a, b) -> a
fst ((Int, String) -> Int)
-> (String -> (Int, String)) -> String -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [(Int, String)] -> (Int, String)
forall a. [a] -> a
head ([(Int, String)] -> (Int, String))
-> (String -> [(Int, String)]) -> String -> (Int, String)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> [(Int, String)]
forall a. (Eq a, Num a) => ReadS a
readOct) String
rest
unescapeString ('\\':'x':rest :: String
rest@(h :: Char
h:_))
| Char
h Char -> String -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` String
hexDigits = Int -> String -> (String -> Int) -> String -> String
unescapeNumeric 2 String
hexDigits ((Int, String) -> Int
forall a b. (a, b) -> a
fst ((Int, String) -> Int)
-> (String -> (Int, String)) -> String -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [(Int, String)] -> (Int, String)
forall a. [a] -> a
head ([(Int, String)] -> (Int, String))
-> (String -> [(Int, String)]) -> String -> (Int, String)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> [(Int, String)]
forall a. (Eq a, Num a) => ReadS a
readHex) String
rest
unescapeString (c :: Char
c:cs :: String
cs) = Char
c Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
unescapeString String
cs
unescapeString [] = []
unescapeRawString :: String -> String
unescapeRawString :: String -> String
unescapeRawString = String -> String
forall a. a -> a
id
unescapeNumeric :: Int -> String -> (String -> Int) -> String -> String
unescapeNumeric :: Int -> String -> (String -> Int) -> String -> String
unescapeNumeric n :: Int
n numericDigits :: String
numericDigits readNumeric :: String -> Int
readNumeric str :: String
str
= Int -> String -> String -> String
forall t. (Eq t, Num t) => t -> String -> String -> String
loop Int
n [] String
str
where
loop :: t -> String -> String -> String
loop _ acc :: String
acc [] = [String -> Char
numericToChar String
acc]
loop 0 acc :: String
acc rest :: String
rest
= String -> Char
numericToChar String
acc Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
unescapeString String
rest
loop n :: t
n acc :: String
acc (c :: Char
c:cs :: String
cs)
| Char
c Char -> String -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` String
numericDigits = t -> String -> String -> String
loop (t
nt -> t -> t
forall a. Num a => a -> a -> a
-1) (Char
cChar -> String -> String
forall a. a -> [a] -> [a]
:String
acc) String
cs
| Bool
otherwise = String -> Char
numericToChar String
acc Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
unescapeString (Char
cChar -> String -> String
forall a. a -> [a] -> [a]
:String
cs)
numericToChar :: String -> Char
numericToChar :: String -> Char
numericToChar = Int -> Char
forall a. Enum a => Int -> a
toEnum (Int -> Char) -> (String -> Int) -> String -> Char
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Int
readNumeric (String -> Int) -> (String -> String) -> String -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> String
forall a. [a] -> [a]
reverse
octalDigits, hexDigits :: String
octalDigits :: String
octalDigits = "01234567"
hexDigits :: String
hexDigits = "0123456789abcdef"