packages feed

LslPlus-0.1.2: src/Language/Lsl/Internal/NumberParsing.hs

module Language.Lsl.Internal.NumberParsing(readHexFloat,readInt) where

import Data.Char(digitToInt)
import Text.ParserCombinators.Parsec(GenParser(..),(<|>),char,digit,hexDigit,many,many1,oneOf,option,parse,satisfy)

hexFloat =
    do char '0'
       oneOf "xX"
       wholeDigits <- many1 hexDigit
       let w = foldl (\ x y -> x * 16.0 + y) 0.0 $ map (fromIntegral . digitToInt) wholeDigits
       frac <- option 0.0 fractionalPart
       p <- expPart
       return $ (w + frac) * p
       
fractionalPart =
    do char '.'
       digits <- many1 hexDigit
       return $ foldr (\ x y -> (x + y) / 16.0) 0.0 $ map (fromIntegral . digitToInt) digits
       
expPart =
    do oneOf "pP"
       f <- option (2^) ((char '+' >> return (2^)) <|> (char '-' >> return ((1/).(2^)))) 
       digits <- many1 digit
       let exp = foldl (\ x y -> 10 * x + y) 0 $ map digitToInt digits
       return $ f exp

hexFloatAndTail :: Fractional a => GenParser Char b [(a,String)]
hexFloatAndTail =
    do v <- hexFloat
       rest <- many (satisfy (const True))
       return [(realToFrac v,rest)]

readHexFloat s = 
    case parse hexFloatAndTail "" s of
        Left _ -> []
        Right v -> v
        
hexInt =
    do oneOf "xX"
       digits <- many1 hexDigit
       return $ foldl (\ x y -> x * 16 + y) 0 $ map digitToInt digits
       
decimalInt =
    do digits <- many1 digit
       return $ foldl (\ x y -> x * 10 + y) 0 $ map digitToInt digits

int = do char '0'
         (hexInt <|> decimalInt <|> return 0)
   <|> decimalInt
   
intAndTail =
    do i <- int
       rest <- many (satisfy (const True))
       return (i,rest)
       
readInt s =
    case parse intAndTail "" s of
        Left _ -> []
        Right v -> [v]