Parsec --- 2.2 Sequence and choice
パーサをつなげてみようというお話.Parserはモナドだからdo記法でつなげることができます.
openClose:: Parser Char openClose = do char '(' char ')'
これで () だけをパースするパーサになるわけですか.
*Main> parseTest openClose "()" ')' *Main> parseTest parens "(" parse error at (line 1, column 2): unexpected end of input expecting "(" or ")"
たしかに () を与えたときには「最後の )」を出力してますし,おかしな入力ではエラーを返してますね.すこしいじってみます.
openClose2:: Parser () openClose2 = do char '(' >> char ')' return ()
モナドなので,クラスメソッド(でいいのかな)>> で連結させて,閉じパーレンだけを返すのも何なので何も返さないようにしてみました.結果,
*Main> parseTest openClose2 "()" () *Main> parseTest openClose "(" parse error at (line 1, column 2): unexpected end of input expecting ")"
うまくいきました.なるほど.
パーサをつなげる(連接)のほかにも「選択」があります.入れ子のパーレンは
parens::Parser () parens = do char '(' >> parens >> char ')' parens <|> -- これが「選択」 return ()
とかけるようです.Parsecのドキュメントの記法は少し見にくいので書きかえています.(,入れ子のパーレン,),入れ子のパーレンとすることで,入れ子のパーレンそのものを再帰的に定義してます.パーレンの組以外のものがきたら,何も返さずに戻っています.
*Main> parseTest parens "(()())()" () *Main> parseTest parens "((()" parse error at (line 1, column 5): unexpected end of input expecting "(" or ")" *Main> parseTest parens "()))" ()
あれ?でも何で最後のOKなんでしょう?
あー・・・全部,パースしきってるわけではないということですか.(と)をパースしたあとに,)がきてるから,return ()に処理がうつってそれで終わりということですね.