haskellparsec

Parsec how to find "matches" within a string


How can I use parsec to parse all matched input in a string and discard the rest?

Example: I have a simple number parser, and I can find all the numbers if I know what separates them:

num :: Parser Int
num = read <$> many digit

parse (num `sepBy` space) "" "111 4 22"

But what if I don't know what is between the numbers?

"I will live to be 111 years <b>old</b> if I work out 4 days a week starting at 22."

many anyChar doesn't work as a separator, because it consumes everything.

So how can I get things that match an arbitrary parser surrounded by things I want to ignore?


EDIT: Note that in the real problem, my parser is more complicated:

optionTag :: Parser Fragment
optionTag = do
    string "<option"
    manyTill anyChar (string "value=")
    n <- many1 digit
    manyTill anyChar (char '>')
    chapterPrefix
    text <- many1 (noneOf "<>")
    return $ Option (read n) text
  where
    chapterPrefix = many digit >> char '.' >> many space

Solution

  • For an arbitrary parser myParser, it's quite easy:

    solution = many (let one = myParser <|> (anyChar >> one) in one)
    

    It might be clearer to write it this way:

    solution = many loop
        where 
            loop = myParser <|> (anyChar >> loop)
    

    Essentially, this defines a recursive parser (called loop) that will continue searching for the first thing that can be parsed by myParser. many will simply search exhaustively until failure, ie: EOF.