----------------------------------------------------------------------------- -- | -- Module : Hasmin.Parser.Numeric -- Copyright : (c) 2017 Cristian Adrián Ontivero -- License : BSD3 -- Stability : experimental -- Portability : unknown -- ----------------------------------------------------------------------------- module Hasmin.Parser.Numeric ( alphavalue , rational , int , percentage , number ) where import Control.Applicative ((<|>)) import Numeric (readSigned, readFloat) import Data.Attoparsec.Text (Parser) import qualified Data.Attoparsec.Text as A import Hasmin.Types.Numeric import Hasmin.Parser.Utils import Hasmin.Parser.Primitives -- | Parser for >. number :: Parser Number number = Number <$> rational -- | Parser for >. percentage :: Parser Percentage percentage = Percentage <$> rational <* A.char '%' alphavalue :: Parser Alphavalue alphavalue = mkAlphavalue <$> rational -- Note that many properties that allow an integer or real number as a value -- actually restrict the value to some range, often to a non-negative value. -- -- | Real number parser. \: <'int' integer> | [0-9]*.[0-9]+ rational :: Parser Rational rational = do sign <- A.option [] (wrapMinus <$> (A.char '-' <|> A.char '+')) dgts <- ((++) <$> digits <*> A.option "" fractionalPart) <|> ("0"++) <$> fractionalPart -- append a zero for read not to fail e <- A.option [] expo pure . fst . head $ readSigned readFloat (sign ++ dgts ++ e) where fractionalPart = (:) <$> A.char '.' <*> digits expo = (:) <$> A.satisfy (\c -> c == 'e' || c == 'E') <*> int' wrapMinus x = [x | x == '-'] -- we use this since read fails with leading '+'