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

Simple, simple Parsec

Parsec というのは Haskell のパーサコンビネータだ。これを使うと15分で Perl の処理系が書けるらしい。パーサコンビネータという名前が怖い気がするが、せっかくだからちょっと除いてみた。

まず、Hugs に Parsec が入っているかの確認。

Hugs> :load Text.ParserCombinators.Parsec
Text.ParserCombinators.Parsec>

ばんざい!!管理人の Hugs にも入っていた。(あたりまえか。)

そこで、ものすごく簡単な Parsec を使ったプログラムを作ってみた。下のがそれ。

import Text.ParserCombinators.Parsec

simple :: Parser Char
simple = letter

これで全部。Parsec はパーサだから、どこかで文字列をパースするはずだ。parse がその関数らしい。parse 関数は3つの引数をとる。第1はパーサを定義した関数。上の例の simple だ。単に letter 関数をバインドしただけ。第2は入力の名前だが初心者はとくに使わなくていいらしい。第3がパースする文字列。したがって、parse simple "" "abc" で文字列がパースされて情報が取り出せるらしい。さっそくやってみよう。

Hugs> :e simple.hs
Hugs> :l simple.hs
Main> parse simple "" "abc"
Right 'a'

成功だ。文字列、"abc" がパースされ先頭のキャラクタ 'a' が取り出されている。Right というデータコンストラクタがくっついているがきっと戻り値がモナドなのだろう。ということは、Maybe モナドの場合のようにパースが失敗したときの戻り値もあるはずだ。

Main> parse simple "" "123"
Left (line 1, column 1):
unexpected "1"
expecting letter

やはりそうだ。1は文字ではなく数字なので、文字ではありませんというエラーメッセージがでる。成功したときのデータコンストラクタは Rigth だったが、失敗した時は Left になっている。Leftのフィールドには失敗した場所の行と列の情報が入っている。

初心者には不要とのことで省略した第2引数だが、気になるので使ってみた。

Main> parse simple "hello" "123"
Left "hello" (line 1, column 1):
unexpected "1"
expecting letter

パースが失敗したときの、Left のフィールドに "hello" が追加されている。エラーメッセージか何かに使うのだろうか。

letter のような標準のパーサは他に何があるのだろうと気になったので調べてみた。
Main> :l Text.ParserCombinators.Parsec
Text.ParserCombinators.Parsec> :b

upper :: CharParser a Char
lower :: CharParser a Char
alphaNum :: CharParser a Char
letter :: CharParser a Char
digit :: CharParser a Char
hexDigit :: CharParser a Char
octDigit :: CharParser a Char
char :: Char -> CharParser a Char
string :: String -> CharParser a String
anyChar :: CharParser a Char
oneOf :: [Char] -> CharParser a Char
noneOf :: [Char] -> CharParser a Char
satisfy :: (Char -> Bool) -> CharParser a Char

使えそうなのを試してみたら、letter と同じようなものがあった。

Main> parse digit "" "123"
Right '1'
Main> parse lower "" "abc"
Right 'a'
Main> parse upper "" "ABC"
Right 'A'
by tnomura9 | 2009-09-27 18:01 | Haskell | Comments(0)
<< Parsec パーサコンビネー... Haskell による血圧のシ... >>