2017-04-07 6 views
2

正規表現では、\d{1,5}のような何かを行うことで範囲を取得することができます。これは数字を1〜5回貪欲に解析します。または、怠け者にするには\d{1,5}?を実行します。Haskell Text Parser範囲を正確に解析するコンビネータ

ハスケルのText.ParserCombinators.ReadPでこれをどうやって行いますか?

あなたは rangeParse (satisfy isDigit) ([5,4..1])のようにそれを行う場合は5回に桁1の貪欲解析を実行します
rangeParse :: Read a => ReadP a -> [Int] -> ReadP [a] 
rangeParse parse ranges = foldr1 (<++) $ fmap (\n -> count n $ parse) ranges 

を:

私の試みはこれを与えました。数字を[1..5]にスワップすると、怠惰な解析が行われます。

パーサーコンビネータでこれを行う方が良いか慣用的な方法がありますか?

答えて

1

更新:以下間違っている - たとえば rangeGreedy 2 4 a <* string "aab"のために、正規表現a{2,4}aabの同等は、一致していません。質問者の解決策はこの権利を得る。他の人が同じミスをしないようにするために、私はまだ答えを削除しません。

=========

これは完全な答え、貪欲 バージョンを記述するだけで可能な方法ではありません。私は怠惰なバージョンを行う良い方法を発見していない。

Maybesを返すoptionの左バイアスされたバージョンを定義します。そして、我々は彼らのreplicateMで何かのn個まで行うことができます

greedyOption :: ReadP a -> ReadP (Maybe a) 
greedyOption p = (Just <$> p) <++ pure Nothing 

を:

upToGreedy :: Int -> ReadP a -> ReadP [a] 
upToGreedy n p = catMaybes <$> replicateM n (greedyOption p) 

を最小カウントを可能にするには別途必須の部分を行い、 を添付してください。

rangeGreedy :: Int -> Int -> ReadP a -> ReadP [a] 
rangeGreedy lo hi p = (++) <$> count lo p <*> upToGreedy (hi - lo) p 

他のテストコードは、誰にとっても役立ちます。

関連する問題