Skip to content

Instantly share code, notes, and snippets.

@kagamilove0707
Last active December 18, 2015 13:19
Show Gist options
  • Save kagamilove0707/5788805 to your computer and use it in GitHub Desktop.
Save kagamilove0707/5788805 to your computer and use it in GitHub Desktop.
Parsec入門したかったので書いてみましたですー>ω< 数値リテラルのパーサーです(`・ω・´)
import Control.Applicative ((<$>),(<*>),(*>),(<*))
import Data.Char (ord)
import Text.Parsec (try, char, eof, oneOf, many, many1, parse, (<|>))
import Text.Parsec.String (Parser)
{-
number ::= binary | octal | decimal | hexadecimal | zero
binary ::= '0' ('b'|'B') ('0'|'1')+
octal ::= '0' ('o'|'O') ('0'..'7')+
decimal ::= ('1'..'9') ('0'..'9')*
hexadecimal ::= '0' ('x'|'X') ('0'..'9'|'a'..'f'|'A'..'F')+
zero ::= '0'
-}
number, binary, octal, decimal, hexadecimal, zero :: Parser Integer
number = try binary <|> try octal <|> try decimal <|> try hexadecimal <|> zero <* eof
binary = binaryToInteger <$> (char '0' *> (char 'b' <|> char 'B') *> many1 (char '0' <|> char '1'))
octal = octalToInteger <$> (char '0' *> (char 'o' <|> char 'O') *> many1 (oneOf ['0'..'7']))
decimal = (.) decimalToInteger . (:) <$> (oneOf ['1'..'9']) <*> many (oneOf ['0'..'9'])
hexadecimal = hexadecimalToInteger <$> (char '0' *> (char 'x' <|> char 'X') *> many1 (oneOf $ ['0'..'9'] ++ ['a'..'f'] ++ ['A'..'F']))
zero = const 0 <$> char '0'
binaryToInteger, octalToInteger, decimalToInteger, hexadecimalToInteger :: String -> Integer
binaryToInteger = foldl (\x y->x * 2 + fromIntegral (ord y) - fromIntegral (ord '0')) 0
octalToInteger = foldl (\x y->x * 8 + fromIntegral (ord y) - fromIntegral (ord '0')) 0
decimalToInteger = foldl (\x y->x * 10 + fromIntegral (ord y) - fromIntegral (ord '0')) 0
hexadecimalToInteger = foldl (\x y->x * 16 + charToInteger y) 0
where
charToInteger x
|x `elem` ['0'..'9'] = x' - fromIntegral (ord '0')
|x `elem` ['a'..'f'] = x' - fromIntegral (ord 'a') + 10
|x `elem` ['A'..'F'] = x' - fromIntegral (ord 'A') + 10
where
x' = fromIntegral (ord x)
read' :: (Num a) => String -> Maybe a
read' s = case parse number "read'" s of
Right x -> Just (fromIntegral x)
Left _ -> Nothing
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment