[Haskell-beginners] attoparsec: How to use the many1 combinator
Roland Senn
rsx at bluewin.ch
Sat Jun 21 13:51:20 UTC 2014
David,
Many thanks! Yes I had the infinite loop to0.
Regards
Roland
Am 21.06.2014 15:33, schrieb David McBride:
> You have a couple problems here.
>
> P.many1 $ pNumber <* (string "END") ... which is the same as ...
> P.many1 (pNumber <* string "END")
>
> In other words it matches 111 END 222 END 333 END. Try this:
>
> ns <- (P.many1 pNumber) <* string "END"
>
> This almost works, but when you actually run it you'll get an infinite
> loop. The reason is because pNumber if it doesn't find a match it
> will never actually fail, therefore many1 will continue using it
> forever attempting to find a match that will never occur. The reason
> why it never fails is that it is composed of combinators that never
> fail, pSkipSpaces and itself are both composed entirely of takeWhiles,
> which if they don't find a match they just continue on without doing
> anything. If you make a small change though:
>
> term <- P.takeWhile1 (\c -> c >= 0x31 && c <= 0x39)
>
> then it works fine.
>
>
>
>
> On Sat, Jun 21, 2014 at 8:47 AM, Roland Senn <rsx at bluewin.ch
> <mailto:rsx at bluewin.ch>> wrote:
>
> I'm trying to do a first very simple example with attoparsec.
>
> The file "test.txt" contains the line:
>
> START 111 2222 333 END
>
> The following code works and gives the result: Done "\n"
> ["111","2222","333"]
>
> {-# LANGUAGE OverloadedStrings #-}
> import qualified Data.ByteString as BS
> import Control.Applicative
> import Data.Attoparsec.ByteString as P
> main :: IO()
> main = do
> bs <- BS.readFile "test.txt"
> parseTest pTest bs
> pTest :: Parser [BS.ByteString]
> pTest = do
> string "START"
> n1 <- pNumber
> n2 <- pNumber
> n3 <- pNumber
> string "END"
> return [n1, n2, n3]
> pNumber :: Parser BS.ByteString
> pNumber = do
> pSkipSpaces
> term <- P.takeWhile (\c -> c >= 0x31 && c <= 0x39)
> pSkipSpaces
> return term
> pSkipSpaces :: Parser ()
> pSkipSpaces = do
> P.takeWhile (\c -> c == 0x20)
> return ()
>
> Unfortunately I must have exactly three numbers between START and
> END. To make this more flexible, I changed pTest:
>
> pTest :: Parser [BS.ByteString]
> pTest = do
> string "START"
> ns <- P.many1 $ pNumber <* (string "END")
> return ns
>
> Now the program fails with: Fail "2222 333 END\n" [] "Failed
> reading: takeWith"
> Why ??
>
> Many thanks for your help!
>
> _______________________________________________
> Beginners mailing list
> Beginners at haskell.org <mailto:Beginners at haskell.org>
> http://www.haskell.org/mailman/listinfo/beginners
>
>
>
>
> _______________________________________________
> Beginners mailing list
> Beginners at haskell.org
> http://www.haskell.org/mailman/listinfo/beginners
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.haskell.org/pipermail/beginners/attachments/20140621/beb15b8b/attachment.html>
More information about the Beginners
mailing list