ddc-core-salt-0.3.1.1: DDC/Core/Salt/Name/Lit.hs
-- | 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