{-# OPTIONS #-}
module Language.Python.Common.StringEscape (
unescapeString,
unescapeRawString,
octalDigits,
hexDigits) where
import Numeric (readHex, readOct)
unescapeString :: String -> String
unescapeString :: String -> String
unescapeString (Char
'\\':Char
'\\':String
cs) = Char
'\\' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
unescapeString String
cs
unescapeString (Char
'\\':Char
'\'':String
cs) = Char
'\'' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
unescapeString String
cs
unescapeString (Char
'\\':Char
'"':String
cs) = Char
'"' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
unescapeString String
cs
unescapeString (Char
'\\':Char
'a':String
cs) = Char
'\a' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
unescapeString String
cs
unescapeString (Char
'\\':Char
'b':String
cs) = Char
'\b' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
unescapeString String
cs
unescapeString (Char
'\\':Char
'f':String
cs) = Char
'\f' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
unescapeString String
cs
unescapeString (Char
'\\':Char
'n':String
cs) = Char
'\n' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
unescapeString String
cs
unescapeString (Char
'\\':Char
'r':String
cs) = Char
'\r' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
unescapeString String
cs
unescapeString (Char
'\\':Char
't':String
cs) = Char
'\t' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
unescapeString String
cs
unescapeString (Char
'\\':Char
'v':String
cs) = Char
'\v' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
unescapeString String
cs
unescapeString (Char
'\\':Char
'\n':String
cs) = String -> String
unescapeString String
cs
unescapeString (Char
'\\':rest :: String
rest@(Char
o:String
_))
| 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 Int
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 (Char
'\\':Char
'x':rest :: String
rest@(Char
h:String
_))
| 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 Int
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 (Char
c: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 Int
n String
numericDigits String -> Int
readNumeric 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 t
_ String
acc [] = [String -> Char
numericToChar String
acc]
loop t
0 String
acc String
rest
= String -> Char
numericToChar String
acc Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
unescapeString String
rest
loop t
n String
acc (Char
c: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
-t
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 = String
"01234567"
hexDigits :: String
hexDigits = String
"0123456789abcdef"