How to combine parsers up to n times in Haskell?

I am trying to combine parsers in Haskell so that I can parse specific patterns up to n times. To illustrate, imagine that I want to parse up to eight input digits. I know that I can use countfrom Text.Parser.Combinatorsto parse n occurrences, for example:

import Text.Parser.Char        (digit)
import Text.Parser.Combinators (count)

eightDigits :: Parser [Char]
eightDigits = count 8 digit

This, however, fails if it does not find exactly 8 digits. I could also use someone or more digits to parse:

import Text.Parser.Char        (digit)
import Text.Parser.Combinators (some)

someDigits :: Parser [Char]
someDigits = some digit

The problem with the above is that it can consume more digits than I want. Finally, I could use tryparsers that combine the parsers, which can consume the input, and if they fail, return to where they were run:

import Text.Parser.Char        (digit)
import Text.Parser.Combinators (count, try)
import Control.Applicative     ((<|>))

twoOrThreeDigits :: Parser [Char]
twoOrThreeDigits = try (count 3 digit) <|> count 2 digit

8 , , , 1 n ?

+4
1

many :

upto :: Int -> Parser a -> Parser [a]
upto n p | n > 0 = (:) <$> try p <*> upto (n-1) p <|> return []
upto _ _ = return []

1 n, a many1 - :

upto1 :: Int -> Parser a -> Parser [a]
upto1 n p | n > 0 = (:) <$> p <*> upto (n-1) p
upto1 _ _ = return []

:

> map (parse (upto 8 digitChar) "") ["", "123", "1234567890"]
[Right "",Right "123",Right "12345678"]
+6

Source: https://habr.com/ru/post/1696013/


All Articles