From e848dcab9c26854e384ec0c9551b313026d06844 Mon Sep 17 00:00:00 2001 From: Index Int Date: Tue, 12 May 2015 23:43:34 +0300 Subject: [PATCH] Add `bounded` and `upperBounded` combinators closes #52 --- src/Turtle/Pattern.hs | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/src/Turtle/Pattern.hs b/src/Turtle/Pattern.hs index e6d6399..518ffc0 100644 --- a/src/Turtle/Pattern.hs +++ b/src/Turtle/Pattern.hs @@ -86,6 +86,8 @@ module Turtle.Pattern ( , selfless , choice , count + , upperBounded + , bounded , option , between , skip @@ -524,6 +526,47 @@ choice = msum count :: Int -> Pattern a -> Pattern [a] count = replicateM +{-| Apply the given pattern 0 or more times, up to a given bound, + colleting the results + +>>> match (upperBounded 5 dot) "123" +["123"] +>>> match (upperBounded 2 dot) "123" +[] +>>> match ((,) <$> upperBounded 2 dot <*> chars) "123" +[("12","3"),("1","23")] +-} + +upperBounded :: Int -> Pattern a -> Pattern [a] +upperBounded n p + | n <= 0 = mempty + | n == 1 = fmap pure p + | otherwise = (:) <$> p <*> option (upperBounded (n - 1) p) + +{-| Apply the given pattern a number of times restricted by given + lower and upper bounds, collecting the results + +>>> match (bounded 2 5 "cat") "catcatcat" +[["cat","cat","cat"]] +>>> match (bounded 2 5 "cat") "cat" +[] +>>> match (bounded 2 5 "cat") "catcatcatcatcatcat" +[] + +`bounded` could be implemented naively as follows: + +> bounded m n p = do +> x <- choice (map pure [m..n]) +> count x p + +-} + +bounded :: Int -> Int -> Pattern a -> Pattern [a] +bounded m n p + | m == n = count m p + | m < n = (++) <$> count m p <*> option (upperBounded (n - m) p) + | otherwise = mzero + {-| Transform a parser to a succeed with an empty value instead of failing See also: `optional`