Parsec 入門


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,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

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 コンビネータは、セパレータによる区切りが複数行にまたがっている場合に便利だ。