人気ブログランキング | 話題のタグを見る

Parsec コンビネータ sepEndBy

sepEndBy1 は "foo, bar\nbuz,qux\n" のようにセパレータで区切られたデータが複数行にまたがっている場合にマッチし、データのリストを返す。

Prelude Text.Parsec> multiline = "foo,bar\nbuz,qux"
Prelude Text.Parsec> putStrLn multiline
foo,bar
buz,qux

Prelude 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 は次のように定義されているので、先頭の 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 コンビネータは、セパレータによる区切りが複数行にまたがっている場合に便利だ。

by tnomura9 | 2019-06-14 07:30 | Haskell | Comments(0)
<< Parsec コンビネータ c... Parsec コンビネータ s... >>