How can I parse integers with unlimited length, no delimiters with attoparsec?
I am trying to parse two 3 character integers using attoparsec. An example input might look something like this:
341
... which I would like to analyze:
Constructor 34 1
I have two solutions that work, but which are somewhat clunky:
stdK :: P.Parser Packet
stdK = do
P.char '1'
qstr <- P.take 2
let q = rExt $ P.parseOnly P.decimal qstr
n <- P.decimal
return $ Std q n
stdK2 :: P.Parser Packet
stdK2 = do
P.char '1'
qn <- P.decimal
let q = div qn 10
let n = rem qn 10
return $ Std q n
There must be a better way to achieve something as simple as this. Did I miss something?
source to share
Your code snippet is not self-contained (in particular, imports and datatype are missing Packet
), but you seem to be too offensive.
First, define a parser for one-digit integers. Then use the latter as a building block for parsing for two-digit integers. After that, use applicative operators to combine the two parsers and define a parser for your custom data type Packet
. See below.
Note that you do not need the full power of the monads; there is enough additive parsing here.
-- test_attoparsec.hs {-# LANGUAGE OverloadedStrings #-} import Control.Applicative ((<$>)) import Data.Attoparsec.Text import Data.Char data Packet = Std {-# UNPACK #-} !Int {-# UNPACK #-} !Int deriving (Show) stdK :: Parser Packet stdK = char '1' *> (Std <$> twoDigitInt <*> oneDigitInt) twoDigitInt :: Parser Int twoDigitInt = timesTenPlus <$> oneDigitInt <*> oneDigitInt where timesTenPlus x y = 10 * x + y oneDigitInt :: Parser Int oneDigitInt = digitToInt <$> digit
Tests at GHCi:
λ> :l test_attoparsec.hs
[1 of 1] Compiling Main ( test_attoparsec.hs, interpreted )
Ok, modules loaded: Main.
λ> :set -XOverloadedStrings
λ> parseOnly stdK "1341"
Right (Std 34 1)
λ> parseOnly stdK "212"
Left "1: Failed reading: satisfyWith"
source to share