views:

65

answers:

2

hi

i've wrote the following Haskell code

import Data.Attoparsec (Parser)
import qualified Data.Attoparsec.Char8 as A
import qualified Data.ByteString.Char8 as B

someWithSep sep p = A.sepBy p sep

the code is suppose to work this way :

main*> A.parse (someWithSep A.skipSpace A.decimal) $ B.pack "123 45  67 89"
Done "" [123,45,67,89]

but since I've defined someWithSep like in the code written above, I always get the following behavior :

main*> A.parse (someWithSep A.skipSpace A.decimal) $ B.pack "123 45  67 89"
Partial _

unless I provide a corrupted entry :

main*> A.parse (someWithSep A.skipSpace A.decimal) $ B.pack "123 45  67 89f"
Done "f" [123,45,67,89]

How can I correct this ?

thanks to reply

+2  A: 

The Partial constructor doesn't indicate failure, merely that parsing could continue if you wanted it to. You should take the Partial item and feed it the empty ByteString (as per the docs: http://hackage.haskell.org/packages/archive/attoparsec/0.8.1.0/doc/html/Data-Attoparsec-Char8.html#t:Result) to get the final result.

Just to show it works:

> let A.Partial f = A.parse (someWithSep A.skipSpace A.decimal) $ B.pack "123 45  67 89" in f B.empty
Done "" [123,45,67,89]

Of course, you probably want to have a case statement in the end to handle the other cases.

Neil Brown
Addendum: The `feed` function in attoparsec can also be used to supply the empty string afterwards, so you could also use: `A.feed (A.parse (someWithSep A.skipSpace A.decimal) $ B.pack "123 45 67 89") B.empty`
Neil Brown
+1  A: 

attoparsec accepts input in multiple pieces. One gives the first piece to parse, then gives the result from parse and the second piece to feed, then gives that result and the third piece to feed again, and so on.

You feed the parser an empty string to mark the end of input:

A.feed (A.parse (someWithSep A.skipSpace A.decimal) $ B.pack "123 45  67 89") B.empty
Done "" [123,45,67,89] 

Or use Data.Attoparsec.Lazy, where the lazy string handles the end of input for you:

import qualified Data.Attoparsec.Lazy as L
import qualified Data.Attoparsec.Char8 as A
import qualified Data.ByteString.Lazy.Char8 as B
L.parse (someWithSep A.skipSpace A.decimal) $ B.pack "123 45  67 89"
Done "" [123,45,67,89] 

(See also this related Stack Overflow question)

Lee Reeves