git.iko.soy/typeable/attoparsec
on master help sign in
Merge pull request #29 from tibbe/strict-combinators

Strict versions of list-producing combinators

commit00ce9c912671d9b19673a7b9c951b75ce37fbdbf authorBryan O'Sullivan <bos@serpentine.com> dateMon 19 Nov 2012, 17:06 (14 years ago) parentbe7a6e90ebd3b3
1 file changed+91−1
Data/Attoparsec/Combinator.hs+91−1
Data/Attoparsec/Combinator.hs+91−1
@@ -14,10 +14,15 @@ module Data.Attoparsec.Combinator
1414 choice
1515 , count
1616 , option
17+ , many'
1718 , many1
19+ , many1'
1820 , manyTill
21+ , manyTill'
1922 , sepBy
23+ , sepBy'
2024 , sepBy1
25+ , sepBy1'
2126 , skipMany
2227 , skipMany1
2328 , eitherP
@@ -60,6 +65,20 @@ option x p = p <|> pure x
6065{-# SPECIALIZE option :: a -> Z.Parser a -> Z.Parser a #-}
6166#endif
6267
68+-- | @many' p@ applies the action @p@ /zero/ or more times. Returns a
69+-- list of the returned values of @p@. The value returned by @p@ is
70+-- forced to WHNF.
71+--
72+-- > word = many' letter
73+many' :: (Alternative f, Monad f) => f a -> f [a]
74+many' p = many_p
75+ where many_p = some_p <|> pure []
76+ some_p = do
77+ !a <- p
78+ as <- many_p
79+ return (a : as)
80+{-# INLINE many' #-}
81+
6382-- | @many1 p@ applies the action @p@ /one/ or more times. Returns a
6483-- list of the returned values of @p@.
6584--
@@ -68,6 +87,18 @@ many1 :: Alternative f => f a -> f [a]
6887many1 p = liftA2 (:) p (many p)
6988{-# INLINE many1 #-}
7089
90+-- | @many1' p@ applies the action @p@ /one/ or more times. Returns a
91+-- list of the returned values of @p@. The value returned by @p@ is
92+-- forced to WHNF.
93+--
94+-- > word = many1' letter
95+many1' :: (Alternative f, Monad f) => f a -> f [a]
96+many1' p = do
97+ !a <- p
98+ as <- many' p
99+ return (a : as)
100+{-# INLINE many1' #-}
101+
71102-- | @sepBy p sep@ applies /zero/ or more occurrences of @p@, separated
72103-- by @sep@. Returns a list of the values returned by @p@.
73104--
@@ -81,10 +112,29 @@ sepBy p s = liftA2 (:) p ((s *> sepBy1 p s) <|> pure []) <|> pure []
81112{-# SPECIALIZE sepBy :: Z.Parser a -> Z.Parser s -> Z.Parser [a] #-}
82113#endif
83114
115+-- | @sepBy' p sep@ applies /zero/ or more occurrences of @p@, separated
116+-- by @sep@. Returns a list of the values returned by @p@. The value
117+-- returned by @p@ is forced to WHNF.
118+--
119+-- > commaSep p = p `sepBy'` (symbol ",")
120+sepBy' :: (Alternative f, Monad f) => f a -> f s -> f [a]
121+sepBy' p s = scan <|> pure []
122+ where
123+ scan = do
124+ !a <- p
125+ as <- (s *> sepBy1' p s) <|> pure []
126+ return (a : as)
127+#if __GLASGOW_HASKELL__ >= 700
128+{-# SPECIALIZE sepBy' :: Parser ByteString a -> Parser ByteString s
129+ -> Parser ByteString [a] #-}
130+{-# SPECIALIZE sepBy' :: Parser Text a -> Parser Text s -> Parser Text [a] #-}
131+{-# SPECIALIZE sepBy' :: Z.Parser a -> Z.Parser s -> Z.Parser [a] #-}
132+#endif
133+
84134-- | @sepBy1 p sep@ applies /one/ or more occurrences of @p@, separated
85135-- by @sep@. Returns a list of the values returned by @p@.
86136--
87−-- > commaSep p = p `sepBy` (symbol ",")
137+-- > commaSep p = p `sepBy1` (symbol ",")
88138sepBy1 :: Alternative f => f a -> f s -> f [a]
89139sepBy1 p s = scan
90140 where scan = liftA2 (:) p ((s *> scan) <|> pure [])
@@ -95,6 +145,23 @@ sepBy1 p s = scan
95145{-# SPECIALIZE sepBy1 :: Z.Parser a -> Z.Parser s -> Z.Parser [a] #-}
96146#endif
97147
148+-- | @sepBy1' p sep@ applies /one/ or more occurrences of @p@, separated
149+-- by @sep@. Returns a list of the values returned by @p@. The value
150+-- returned by @p@ is forced to WHNF.
151+--
152+-- > commaSep p = p `sepBy1'` (symbol ",")
153+sepBy1' :: (Alternative f, Monad f) => f a -> f s -> f [a]
154+sepBy1' p s = scan
155+ where scan = do !a <- p
156+ as <- (s *> scan) <|> pure []
157+ return (a : as)
158+#if __GLASGOW_HASKELL__ >= 700
159+{-# SPECIALIZE sepBy1' :: Parser ByteString a -> Parser ByteString s
160+ -> Parser ByteString [a] #-}
161+{-# SPECIALIZE sepBy1' :: Parser Text a -> Parser Text s -> Parser Text [a] #-}
162+{-# SPECIALIZE sepBy1' :: Z.Parser a -> Z.Parser s -> Z.Parser [a] #-}
163+#endif
164+
98165-- | @manyTill p end@ applies action @p@ /zero/ or more times until
99166-- action @end@ succeeds, and returns the list of values returned by
100167-- @p@. This can be used to scan comments:
@@ -113,6 +180,29 @@ manyTill p end = scan
113180{-# SPECIALIZE manyTill :: Z.Parser a -> Z.Parser b -> Z.Parser [a] #-}
114181#endif
115182
183+-- | @manyTill' p end@ applies action @p@ /zero/ or more times until
184+-- action @end@ succeeds, and returns the list of values returned by
185+-- @p@. This can be used to scan comments:
186+--
187+-- > simpleComment = string "<!--" *> manyTill' anyChar (try (string "-->"))
188+--
189+-- Note the overlapping parsers @anyChar@ and @string \"<!--\"@, and
190+-- therefore the use of the 'try' combinator. The value returned by @p@
191+-- is forced to WHNF.
192+manyTill' :: (Alternative f, Monad f) => f a -> f b -> f [a]
193+manyTill' p end = scan
194+ where scan = (end *> pure []) <|> scan'
195+ scan' = do
196+ !a <- p
197+ as <- scan
198+ return (a : as)
199+#if __GLASGOW_HASKELL__ >= 700
200+{-# SPECIALIZE manyTill' :: Parser ByteString a -> Parser ByteString b
201+ -> Parser ByteString [a] #-}
202+{-# SPECIALIZE manyTill' :: Parser Text a -> Parser Text b -> Parser Text [a] #-}
203+{-# SPECIALIZE manyTill' :: Z.Parser a -> Z.Parser b -> Z.Parser [a] #-}
204+#endif
205+
116206-- | Skip zero or more instances of an action.
117207skipMany :: Alternative f => f a -> f ()
118208skipMany p = scan