parsing - Haskell Text Parser Combinators to parse a Range Greedily like Regex range notation -
in regex can acquire range of parse doing \d{1,5}
, parses digit 1 5 times greedily. or \d{1,5}?
make lazy.
how in haskell's text.parsercombinators.readp?
my attempt gave this:
rangeparse :: read => readp -> [int] -> readp [a] rangeparse parse ranges = foldr1 (<++) $ fmap (\n -> count n $ parse) ranges
which if rangeparse (satisfy isdigit) ([5,4..1])
perform greedy parse of digits 1 5 times. while if swap number sequent [1..5]
, lazy parse.
is there better or more idiomatic way parser combinators?
update: below wrong - example rangegreedy 2 4 <* string "aab"
, equivalent of regexp a{2,4}aab
, doesn't match. questioner's solution gets right. won't delete answer yet in case keeps else making same mistake.
=========
this isn't complete answer, possible way write greedy version. haven't found nice way lazy version.
define left-biased version of option
returns maybes:
greedyoption :: readp -> readp (maybe a) greedyoption p = (just <$> p) <++ pure nothing
then can n of replicatem
of them:
uptogreedy :: int -> readp -> readp [a] uptogreedy n p = catmaybes <$> replicatem n (greedyoption p)
to allow minimum count, mandatory part separately , append it:
rangegreedy :: int -> int -> readp -> readp [a] rangegreedy lo hi p = (++) <$> count lo p <*> uptogreedy (hi - lo) p
the rest of test code in case it's useful anyone:
module main import control.monad (replicatem) import data.maybe (catmaybes) import text.parsercombinators.readp main :: io () main = mapm_ go ["aaaaa", "aaaab", "aaabb", "aabbb", "abbbb", "bbbbb"] go = print . map fst . readp_to_s test test :: readp [string] test = ((++) <$> rangegreedy 2 4 <*> many aorb) <* eof = char 'a' *> pure "ay" aorb = (char 'a' +++ char 'b') *> pure "ayorbee"
Comments
Post a Comment