Search code examples
parsinghaskelltext-parsingstring-parsing

Parse multiple instances of a string using ReadP


Problem Statement: Parse the string "AB" in "ABCDFGABIJABGHA"

Constraint: Using ReadP

Expected Solution : (["AB","AB","AB"],"whatever is left")

Attempt:

getAll :: ReadP a -> ReadP [a]
getAll p = many loop
  where
    loop = p <|> (get >> loop)

readP_to_S (getAll $ string "AB") "ABCDFGABIJABGHA"
[([],"ABCDFGABIJABGHA"),(["AB"],"CDFGABIJABGHA"),(["AB","AB"],"IJABGHA"),(["AB"],"IJABGHA"),(["AB","AB","AB"],"GHA"),(["AB","AB"],"GHA"),(["AB","AB"],"GHA"),(["AB"],"GHA")]

I wanted the last state to be (["AB","AB","AB"],"GHA"). Is it possible to do the same using ReadP?


Solution

  • The problem is that you are doing a symmetric choice with <|>. If you want your parser to match all the ps without exception use the provided left-biased choice: <++.

    getAll :: ReadP a -> ReadP [a]
    getAll p = many loop
      where
        loop = p <++ (get >> loop)