あどけない話

インターネットに関する技術的な話など

Parsecで範囲指定

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

素敵!