module Language.Python.Common.StringEscape (
unescapeString,
unescapeRawString,
octalDigits,
hexDigits) where
import Numeric (readHex, readOct)
unescapeString :: String -> String
unescapeString ('\\':'\\':cs) = '\\' : unescapeString cs
unescapeString ('\\':'\'':cs) = '\'' : unescapeString cs
unescapeString ('\\':'"':cs) = '"' : unescapeString cs
unescapeString ('\\':'a':cs) = '\a' : unescapeString cs
unescapeString ('\\':'b':cs) = '\b' : unescapeString cs
unescapeString ('\\':'f':cs) = '\f' : unescapeString cs
unescapeString ('\\':'n':cs) = '\n' : unescapeString cs
unescapeString ('\\':'r':cs) = '\r' : unescapeString cs
unescapeString ('\\':'t':cs) = '\t' : unescapeString cs
unescapeString ('\\':'v':cs) = '\v' : unescapeString cs
unescapeString ('\\':'\n':cs) = unescapeString cs
unescapeString ('\\':rest@(o:_))
| o `elem` octalDigits = unescapeNumeric 3 octalDigits (fst . head . readOct) rest
unescapeString ('\\':'x':rest@(h:_))
| h `elem` hexDigits = unescapeNumeric 2 hexDigits (fst . head . readHex) rest
unescapeString (c:cs) = c : unescapeString cs
unescapeString [] = []
unescapeRawString :: String -> String
unescapeRawString ('\\':'\'':cs) = '\'' : unescapeRawString cs
unescapeRawString ('\\':'"':cs) = '"' : unescapeRawString cs
unescapeRawString ('\\':'\n':cs) = unescapeRawString cs
unescapeRawString (c:cs) = c : unescapeRawString cs
unescapeRawString [] = []
unescapeNumeric :: Int -> String -> (String -> Int) -> String -> String
unescapeNumeric n numericDigits readNumeric str
= loop n [] str
where
loop _ acc [] = [numericToChar acc]
loop 0 acc rest
= numericToChar acc : unescapeString rest
loop n acc (c:cs)
| c `elem` numericDigits = loop (n1) (c:acc) cs
| otherwise = numericToChar acc : unescapeString (c:cs)
numericToChar :: String -> Char
numericToChar = toEnum . readNumeric . reverse
octalDigits, hexDigits :: String
octalDigits = "01234567"
hexDigits = "0123456789abcdef"