-- | Reading literal values. module DDC.Core.Salt.Name.Lit ( readLitInteger , readLitPrimNat , readLitPrimInt , readLitPrimWordOfBits) where import Data.List import Data.Char -- | Read a signed integer. readLitInteger :: String -> Maybe Integer readLitInteger [] = Nothing readLitInteger str@(c:cs) | '-' <- c , all isDigit cs = Just $ read str | all isDigit str = Just $ read str | otherwise = Nothing -- | Read an integer with an explicit format specifier like @1234i#@. readLitPrimNat :: String -> Maybe Integer readLitPrimNat str1 | (ds, str2) <- span isDigit str1 , not $ null ds , Just "" <- stripPrefix "#" str2 = Just $ read ds | otherwise = Nothing -- | Read an integer with an explicit format specifier like @1234i#@. readLitPrimInt :: String -> Maybe Integer readLitPrimInt str1 | '-' : str2 <- str1 , (ds, "i#") <- span isDigit str2 , not $ null ds = Just $ read ds | (ds, "i#") <- span isDigit str1 , not $ null ds = Just $ read ds | otherwise = Nothing -- | Read a word with an explicit format speficier. readLitPrimWordOfBits :: String -> Maybe (Integer, Int) readLitPrimWordOfBits str1 -- binary like 0b01001w32# | Just str2 <- stripPrefix "0b" str1 , (ds, str3) <- span (\c -> c == '0' || c == '1') str2 , not $ null ds , Just str4 <- stripPrefix "w" str3 , (bs, "#") <- span isDigit str4 , not $ null bs , bits <- read bs , length ds <= bits = Just (readBinary ds, bits) -- decimal like 1234w32# | (ds, str2) <- span isDigit str1 , not $ null ds , Just str3 <- stripPrefix "w" str2 , (bs, "#") <- span isDigit str3 , not $ null bs = Just (read ds, read bs) | otherwise = Nothing -- | Read a binary string as a number. readBinary :: (Num a, Read a) => String -> a readBinary digits = foldl' (\ acc b -> if b then 2 * acc + 1 else 2 * acc) 0 $ map (/= '0') digits