更新:下面是错误的 - 例如 rangeGreedy 2 4 a <* string "aab"
,正则表达式a{2,4}aab
相当于不匹配。提问者的解决方案正确。我不会删除答案,以防止其他人犯同样的错误。
=========
这不是一个完整的答案,只是写的贪婪 版本一个可行的办法。我还没有找到一个很好的方式来做懒惰的版本。
定义的option
返回Maybes左偏版本:
greedyOption :: ReadP a -> ReadP (Maybe a)
greedyOption p = (Just <$> p) <++ pure Nothing
然后,我们可以做的最多的事情n,其中他们的replicateM
:
upToGreedy :: Int -> ReadP a -> ReadP [a]
upToGreedy n p = catMaybes <$> replicateM n (greedyOption p)
要允许最小计数,分别做强制性部分并附加 它:
rangeGreedy :: Int -> Int -> ReadP a -> ReadP [a]
rangeGreedy lo hi p = (++) <$> count lo p <*> upToGreedy (hi - lo) p
其余的我的测试代码,以防万一它对任何人都有用:
module Main where
import Control.Monad (replicateM)
import Data.Maybe (catMaybes)
import Text.ParserCombinators.ReadP
main :: IO()
main = mapM_ go ["aaaaa", "aaaab", "aaabb", "aabbb", "abbbb", "bbbbb"]
where
go = print . map fst . readP_to_S test
test :: ReadP [String]
test = ((++) <$> rangeGreedy 2 4 a <*> many aOrB) <* eof
where
a = char 'a' *> pure "ay"
aOrB = (char 'a' +++ char 'b') *> pure "ayorbee"