{-| Module : Data.JustParse.Numeric Description : Numeric parsing Copyright : Copyright Waived License : PublicDomain Maintainer : grantslatton@gmail.com Stability : experimental Portability : portable Parsers for dealing with signed and unsigned 'Int's and 'Float's. -} module Data.JustParse.Numeric ( decFloat, decFloat_, decInt, decInt_, hexInt, hexInt_ ) where --{-# LANGUAGE Safe #-} import Data.JustParse.Combinator import Data.JustParse.Internal import Data.JustParse.Char import Control.Monad ( liftM, liftM2 ) import Data.Char ( ord, digitToInt, toUpper, isDigit, isHexDigit ) -- | Reads many decimal digits and returns them as an @Int@. decInt :: Stream s Char => Parser s Int decInt = do sign <- optional (oneOf "-+") num <- liftM read (many1 digit) case sign of Just '-' -> return (-num) _ -> return num -- | Branching version of decInt. decInt_ :: Stream s Char => Parser s Int decInt_ = do sign <- optional (oneOf "-+") num <- liftM read (many1_ digit) case sign of Just '-' -> return (-num) _ -> return num -- | Parse a float. If a decimal point is present, it must have at -- least one digit before and after the decimal point. decFloat :: Stream s Char => Parser s Float decFloat = do sign <- optional (oneOf "-+") whole <- many1 digit fractional <- option ".0" (liftM2 (:) (char '.') (many1 digit)) case sign of Just '-' -> return (-(read (whole ++ fractional))) _ -> return (read (whole ++ fractional)) -- | Branching version of decFloat. decFloat_ :: Stream s Char => Parser s Float decFloat_ = do sign <- optional (oneOf "-+") whole <- many1_ digit fractional <- option_ ".0" (liftM2 (:) (char '.') (many1_ digit)) case sign of Just '-' -> return (-(read (whole ++ fractional))) _ -> return (read (whole ++ fractional)) -- | Reads many hexidecimal digits and returns them as an @Int@. hexInt :: Stream s Char => Parser s Int hexInt = do sign <- optional (oneOf "-+") num <- liftM (f . reverse) (many1 hexDigit) case sign of Just '-' -> return (-num) _ -> return num where f [] = 0 f (x:xs) | isDigit x = digitToInt x + 16 * f xs | otherwise = ord (toUpper x) - ord 'A' + 16 * f xs -- | Branching versino of 'hexInt'. hexInt_ :: Stream s Char => Parser s Int hexInt_ = do sign <- optional (oneOf "-+") num <- liftM (f . reverse) (many1_ hexDigit) case sign of Just '-' -> return (-num) _ -> return num where f [] = 0 f (x:xs) | isDigit x = digitToInt x + 16 * f xs | otherwise = ord (toUpper x) - ord 'A' + 16 * f xs