Parsec には以下のようなコンビネーターが存在する。
- many p -- p を 0 回以上
- many1 p -- p を 1 回以上
- count n p -- p を n 回
しかし、正規表現の"{min,max}"のような範囲指定はない。そこで実装してみた。
import ApplicativeParsec range :: Int -> Int -> GenParser tok st a -> GenParser tok st [a] range n m p = (++) <$> count n p <*> upto (m - n) p upto :: Int -> GenParser tok st a -> GenParser tok st [a] upto 0 _ = return [] upto n p = (:) <$> p <*> upto (n - 1) p <|> return []
最近は Applicative スタイルの信者になったので、このコードも Applicative スタイルになっている。ApplicativeParsec は、Real World Haskell の16章から取ってきて欲しい。
実行してみる。
parseTest (range 1 3 (char 'a')) "aa" → "aa" parseTest (range 1 3 (char 'a')) "aaaa" → "aaa" parseTest (range 2 3 (char 'a')) "aa" → "aa" parseTest (range 3 5 (char 'a')) "aa" → parse error at (line 1, column 3): unexpected end of input
素敵!