問題
あなたのコードは自己完結型ではなく、実際の問題は不明です。ただし、実際にはキーの解析方法が原因であると思われます。特に、\r\nk
パーサーによると、次のようなものが有効なキーです。
λ> parseOnly parsePair "\r\nk: v\r\n"
Right ("\r\nk","v")
それを修正する必要があります。
さらに、1 つの EOLが (終了するのではなく) キーと値のペアを分離するため、EOL はパーサーの最後で消費されるべきではありません。parsePair
別の接線の問題:many1
コンビByteString
ネーター指向のパーサー ( などtakeTill
) を使用するため、値の型String
は ではなく になりByteString
ます。それは、そもそも使用の目的に反するため、ここではおそらくあなたが望むものではありません。; パフォーマンスに関する考慮事項ByteString
を参照してください。
解決
次のリファクタリングをお勧めします。
{-# LANGUAGE OverloadedStrings #-}
import Data.ByteString ( ByteString )
import Data.Attoparsec.ByteString.Char8 ( Parser
, count
, endOfLine
, parseOnly
, sepBy
, string
, takeTill
)
-- convenient type synonyms
type KVPair = (ByteString, ByteString)
type Msg = [KVPair]
pair :: Parser KVPair
pair = do
k <- key
_ <- string ": "
v <- value
return (k, v)
where
key = takeTill (\c -> c == ':' || isEOL c)
value = takeTill isEOL
isEOL c = c == '\n' || c == '\r'
-- one EOL separates key-value pairs
msg :: Parser Msg
msg = sepBy pair endOfLine
-- two EOLs separate messages
msgs :: Parser [Msg]
msgs = sepBy msg (count 2 endOfLine)
のパーサーとの一貫性を保つために、あなたのパーサーの名前を変更しattoparsec
ました。
parsePair
-->pair
parseListPairs
-->msg
parseMsg
-->msgs
GHCi でのテスト
λ> parseOnly keyValuePair "\r\nk: v"
Left "string"
良い; この場合、失敗が必要です。
λ> parseOnly keyValuePair "k: v"
Right ("k","v")
λ> parseOnly msg "k: v\r\nk2: v2\r\n"
Right [("k","v"),("k2","v2")]
λ> parseOnly msgs "k1: v1\r\nk2: v2\r\n\r\nk3: v3\r\nk4: v4"
Right [[("k1","v1"),("k2","v2")],[("k3","v3"),("k4","v4")]]
λ> parseOnly msgs "k: v"
Right [[("k","v")]]