import Text.ParserCombinators.Parsec import Control.Monad data Bencoding = BString String | BInteger Integer | BList [Bencoding] | BDict [(String,Bencoding)] deriving Show bencoding = choice [liftM BString byteString, liftM BInteger integer, liftM BList list, liftM BDict dict] byteString = do n <- numeral guard (n >= 0) char ':' count n anyToken integer = between (char 'i') (char 'e') numeral list = between (char 'l') (char 'e') (many bencoding) dict = between (char 'd') (char 'e') $ many $ liftM2 (,) byteString bencoding numeral :: Num a => Parser a numeral = do sign <- option "" (string "-") digits <- many1 digit guard (digits == "0" || head digits /= '0') return $ fromInteger $ read $ sign ++ digits