プログラミング勉強日記

勉強したことを書きます。Haskellとか。

Attoparsecのメモ

blog.chaps.io

上のサイトを見ながら、Bencodeのパースをするコードを書いていたら、そもそもParsecやAttoparsecというパースライブラリについて全然わからなかったので、メモがてら記録をしておきます。
ParsecよりもAttoparsecの方が早いと聞いたのと、上のサイトはAttoparsecを使ってるのもあって、こっちを触ってみます。


http://hackage.haskell.org/package/attoparsec-0.13.1.0/docs/Data-Attoparsec-ByteString-Char8.html

パース実行するときに使う関数がparseです。

parse :: Parser a -> ByteString -> Result a

パーサーとパース文字列を入れると結果が返ってくる。わかりやすいです。


日付のパーサーだったらこんな感じで書けそうですね。

{-# LANGUAGE OverloadedStrings #-}

import Data.Attoparsec.ByteString
import qualified Data.Attoparsec.ByteString.Char8 as B
import Data.ByteString

parseDate :: Parser [Integer]
parseDate = do
    y <- B.decimal
    B.char '/'
    m <- B.decimal
    B.char '/'
    d <- B.decimal
    return [y, m, d]

ghciを起動して読み込んでみます。

*Data.Attoparsec.ByteString B> parse parseDate "2016/10/25"
Partial _

あれ?

Partial (i -> IResult i r)
Supply this continuation with more input so that the parser can resume. To indicate that no more input is available, pass an empty string to the continuation.

どうやらパーサーが途中で止まっているかららしい。
”2016/10/25”という文字列だと、最後が数字なので、「次の数字はまだかー?」ってパーサーが待っているってことなんでしょうか。

*Data.Attoparsec.ByteString B> parse parseDate "2016/10/25x"
Done "x" [2016,10,25]

入力文字列の最後に数字以外の文字を入れたらパーサーが止まったらしく、終了しました。

1回だけパースを実行したいときには、parseOnlyという関数があるみたいです。

*Data.Attoparsec.ByteString B> parseOnly parseDate "2016/10/25"
Right [2016,10,25]

Bencodeのパースをするコードはもうちょっと複雑そうですね。
それはまた今度で。