Parsec コンビネータ sepEndBy
sepEndBy1
sepEndBy1 は "foo, bar\nbuz,qux\n" のようにセパレータで区切られたデータが複数行にまたがっている場合にマッチし、データのリストを返す。Prelude Text.Parsec> multiline = "foo,bar\nbuz,qux" Prelude Text.Parsec> putStrLn multiline foo,bar buz,quxPrelude Text.Parsec> parseTest (sepEndBy1 (many1 letter) (oneOf ",\n")) multiline ["foo","bar","buz","qux"]
sepEndBy1 は次のように自分で関数を定義することもできる。
Prelude Text.Parsec> my_sepEndBy1 p sep = (:) <$> p <*> ((sep *> my_sepEndBy1 p sep) <|> return [])
my_sepEndBy1 も sepEndBy1 と同じように動作する。
Prelude Text.Parsec> parseTest (my_sepEndBy1 (many1 letter) (oneOf ",\n")) multiline ["foo","bar","buz","qux"]
sepEndBy1 は最初の p がマッチしないときはエラーになる。
Prelude Text.Parsec> parseTest (sepEndBy1 (many1 letter) (oneOf ",\n")) "123" parse error at (line 1, column 1): unexpected "1" expecting letter
sepEndBy
sepEndBy は次のように定義されているので、先頭の p のマッチが失敗した場合は空リストを返す。
Prelude Text.Parsec> my_sepEndBy p sep = sepEndBy1 p sep <|> return [] Prelude Text.Parsec> parseTest (my_sepEndBy (many1 letter) (oneOf ",\n")) "123" []
sepEndBy の動作も上の my_sepEndBy と同じ動作になる。
Prelude Text.Parsec> parseTest (sepEndBy (many1 letter) (oneOf ",\n")) "123" []
sepEndBy コンビネータは、セパレータによる区切りが複数行にまたがっている場合に便利だ。