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