Parsec 入門


Parsec コンビネータ option

Parsec コンビネータの option, optionMaybe, optional はいずれもパーサのマッチが失敗してもエラーで終了しないためのコンビネータだ。

option x p

option x p はパーサ p のマッチが失敗したとき x のデフォールト値をモナド値として返す。

Prelude Text.Parsec> parseTest (option "default value" (string "foo")) "bar buz" "default value"

パーサがマッチしたときはその値を返す。

Prelude Text.Parsec> parseTest (option "default value" (string "foo")) "foo bar buz" "foo"

optionMaybe p

optionMaybe p はパーサがマッチしたらその値を Just にくるんで返す。マッチしなければ Nothing を返す。

Prelude Text.Parsec> parseTest (optionMaybe (string "foo")) "foo bar"
Just "foo"
Prelude Text.Parsec> parseTest (optionMaybe (string "foo")) "bar buz"
Nothing

optional p

optional p はパーサ p がマッチしてもマッチしなくても () ユニットが返される。しかし、マッチしたときはマッチした文字が消費される。

Prelude Text.Parsec> parseTest (optional (string "foo")) "foo bar"
()
Prelude Text.Parsec> parseTest (optional (string "foo")) "bar buz"
()

これだけでは、マッチが成功したときと失敗したときの区別がつかないが、入力バッファの文字列が消費されたかどうかは getInput パーサで確認できる。次のように使う。

Prelude Text.Parsec> parseTest (optional (string "foo") >> getInput) "foo bar"
" bar"
Prelude Text.Parsec> parseTest (optional (string "foo") >> getInput) "bar buz"
"bar buz"

option の定義

option 関数の定義は呆れるほど簡単だ。

Prelude Text.Parsec> myOption x p = p <|> return x
Prelude Text.Parsec> parseTest (myOption "default value" (string "foo"))
 "bar buz"
"default value"

optionMaybe の定義

optionMaybe は次のようになる。liftM を使うためには Control.Monad のインポートが必要だ。少し技巧的な感じがする。

Prelude Text.Parsec Control.Monad> myOptionMaybe p = option Nothing
 (liftM Just p)
Prelude Text.Parsec Control.Monad> parseTest (myOptionMaybe (string "foo"))
 "foo bar"
Just "foo"

optional の定義

optional の定義は次のようになる。

Prelude Text.Parsec Control.Monad> myOptional p = ((p >> return ()) <|>
 return ()) :: Parsec String () ()
Prelude Text.Parsec Control.Monad> parseTest (myOptional (string "foo"))
 "foo bar"
()

option 系のパーサコンビネータは、マッチが失敗してもエラーで停止しないようなパーサを作るのに役立っている。