config-value-0.7.0.0: src/Config/NumberParser.y
{
{-# LANGUAGE Trustworthy #-}
module Config.NumberParser where
import Data.List (foldl')
import Config.Number
}
%tokentype
{ Char}
%token
'+' { '+' }
'-' { '-' }
'.' { '.' }
'0' { '0' }
'1' { '1' }
'2' { '2' }
'3' { '3' }
'4' { '4' }
'5' { '5' }
'6' { '6' }
'7' { '7' }
'8' { '8' }
'9' { '9' }
'A' { 'A' }
'B' { 'B' }
'C' { 'C' }
'D' { 'D' }
'E' { 'E' }
'F' { 'F' }
'O' { 'O' }
'P' { 'P' }
'X' { 'X' }
%name number
%%
number :: { Number }
: '-' unsigned_number { negNum $2 }
| unsigned_number { $1 }
unsigned_number
: '0' 'X' hexadecimal fracpart(hexadecimal) exppart('P')
{ mkNum (Radix16 $5) $3 $4 }
| decimal fracpart(decimal ) exppart('E')
{ mkNum (Radix10 $3) $1 $2 }
| '0' 'O' octal fracpart(octal )
{ mkNum Radix8 $3 $4 }
| '0' 'B' binary fracpart(binary )
{ mkNum Radix2 $3 $4 }
fracpart(p) :: { [Int] }
: { [] }
| '.' { [] }
| '.' p { $2 }
exppart(p) :: { Integer }
: { 0 }
| p expnum { $2 }
expnum :: { Integer }
: '+' decimal { toInt 10 $2 }
| '-' decimal { - toInt 10 $2 }
| decimal { toInt 10 $1 }
hexadecimal :: { [Int] }
: hexdigit { [$1] }
| hexadecimal hexdigit { $2 : $1 }
decimal :: { [Int] }
: decdigit { [$1] }
| decimal decdigit { $2 : $1 }
octal :: { [Int] }
: octdigit { [$1] }
| octal octdigit { $2 : $1 }
binary :: { [Int] }
: bindigit { [$1] }
| binary bindigit { $2 : $1 }
hexdigit :: { Int }
: '0' { 0} | '1' { 1} | '2' { 2} | '3' { 3}
| '4' { 4} | '5' { 5} | '6' { 6} | '7' { 7}
| '8' { 8} | '9' { 9} | 'A' {10} | 'B' {11}
| 'C' {12} | 'D' {13} | 'E' {14} | 'F' {15}
decdigit
: '0' { 0} | '1' { 1} | '2' { 2} | '3' { 3}
| '4' { 4} | '5' { 5} | '6' { 6} | '7' { 7}
| '8' { 8} | '9' { 9}
octdigit :: { Int }
: '0' { 0} | '1' { 1} | '2' { 2} | '3' { 3}
| '4' { 4} | '5' { 5} | '6' { 6} | '7' { 7}
bindigit :: { Int }
: '0' { 0} | '1' { 1}
{
mkNum :: Radix -> [Int] -> [Int] -> Number
mkNum radix coef frac =
MkNumber radix (fromInteger (toInt base coef) + toFrac base frac)
where
base = radixToInt radix
negNum :: Number -> Number
negNum n = n { numberCoefficient = - numberCoefficient n }
toInt :: Int -> [Int] -> Integer
toInt base = foldl' (\acc i -> acc*base' + fromIntegral i) 0 . reverse
where base' = fromIntegral base
toFrac :: Int -> [Int] -> Rational
toFrac base = foldl' (\acc i -> (fromIntegral i+acc)/base') 0
where base' = fromIntegral base
happyError [] = error "Unexpected EOF"
happyError (c:_) = error ("Unexpected: "++[c])
}