Edited at

haskell parsec個人メモ

More than 1 year has passed since last update.


haskell parsec個人メモ

parsecのドキュメント

http://jakewheat.github.io/intro_to_parsing/#_first_parser

を参考にメモをしていく。

使うにはbuild-dependsにparsecを追加する。

モジュールはたくさんあるが、とりあえず


パーサの実行

パーサの実行にはparse関数を使う。

引数は

parse <パーサ> <名前> <パースしたい文字列>

みたいにして渡す。

<名前>は単に識別としてつかうので別に"hoge"とかでもいい。

parsecのドキュメントどおり、パースの実行を簡易にするためのrunという関数を

定義すると便利だろう。

import           Text.Parsec.Char

import Text.Parsec.Prim
import Text.Parsec.String

--パーサの簡易実行と出力をする関数
run::Show a => Parser a -> String -> IO ()
run p input =
case parse p "hoge" input of
Left err ->
putStr "parse error at" >> print err
Right x -> print x


Text.Parsec.Char

文字のパーサが定義されている。


oneOf

任意の文字列kを設定し、パース対象の文字列から一文字受け取り、文字列kのどれか一文字に一致したらパースを成功させる

run (oneOf "abc") "aaa" --  'a'がパースされる 

run (oneOf "abc") "bac" -- 'b'がパースされる
run (oneOf "abc") "zabc" -- パース失敗


noneOf

任意の文字列kを設定し、パース対象の文字列から一文字受け取り、文字列kのどの文字にも一致しなければパースを成功させる

run (noneOf "abc") "aaa" --  パース失敗 

run (noneOf "abc") "bac" -- パース失敗
run (noneOf "abc") "zabc" -- 'z'がパースされる


Text.Parsec.Prim

パーサの実行など、パーサの基本的な操作が定義されている。


Text.Parsec.String

String型をパースするパーサの型Parserが型シノニムとして定義されている。


Text.Parsec.Combinator

コンビネータを定義している。

eof

文字列の終端が来たらパースを成功させる

run (char 'a') "abc" --"a"がパースされる

run (char 'a' >> eof) "abc" --パース失敗。文字列が残っている!


charパーサ

--"()"をパースする

openClose :: Parser String
openClose =do
a <- char '('
b <- char ')'
return [a,b]

main :: IO ()
main = do
run openClose "()"
print "-----------"
run openClose "(4)"
print "-----------"
run openClose "(("
print "-----------"
run openClose "()44444"

実行結果

"()"

"-----------"
parse error at"hoge" (line 1, column 2):
unexpected "4"
expecting ")"
"-----------"
parse error at"hoge" (line 1, column 2):
unexpected "("
expecting ")"
"-----------"
"()"

むむむ、最後の結果には注意だ。

()44444がパースに成功している。

どうやら余った文字があったとしても成功判定になるらしい。


<|>コンビネータ

<|>コンビネータを使うと「または」を表現することができる。

例えばaまたはbまたはcにマッチするパーサはこう。

a_b_c ::Parser Char

a_b_c = char 'a' <|> char 'b' <|> char 'c'

main :: IO ()
main = do
run a_b_c "a"
run a_b_c "b"
run a_b_c "c"
run a_b_c "d"

実行結果



'a'

"-------------------"

'b'

"-------------------"

'c'

"-------------------"

parse error at"hoge" (line 1, column 1):

unexpected "d"

expecting "a", "b" or "c"

"-------------------"


パーサの再帰

パーサは、自分自身を再帰的に呼び出すことができる。

parens :: Parser String

parens = do
a <- char '('
c <- parens
b <- char ')'
return $ a:c++[b]
<|>
return []

main :: IO ()
main = do
run parens "()"
run parens "(())"
run parens "((()))"
run parens ")"
run parens "(("

実行結果



"()"

"-------------------"

"(())"

"-------------------"

"((()))"

"-------------------"

""

"-------------------"

parse error at"hoge" (line 1, column 3):

unexpected end of input

expecting "(" or ")"

"-------------------"


この記事はどんどん追記していきます!!