Parsec try

string パーサは文字列にマッチするパーサなので、testOr = string "(a)" <|> "(b)" は、"(a)" または "(b)" にマッチするように思うが、"(a)" にはマッチするが、"(b)" にはマッチしてくれない。

Hugs> :l Text.ParserCombinators.Parsec
Text.ParserCombinators.Parsec> parseTest (string "(a)" <|> string "(b)") "(a)"
"(a)"

Text.ParserCombinators.Parsec> parseTest (string "(a)" <|> string "(b)") "(b)"
parse error at (line 1, column 1):
unexpected "b"
expecting "(a)"

これはエラーメッセージの unexpected "b" で分かるように、最初の "(a)" とのマッチが失敗した時に、"(b)" の '(' が消費されてしまって、次に "(b)" とマッチさせようとしたときに、入力文字が "b)" になってしまっているからだ。Parsec は "predictive" (予見的)なパーサなので、指示しなければバックトラックをしてくれない。Parsec にバックトラックをさせようと思ったら、次のように try 関数を使う。

Text.ParserCombinators.Parsec> parseTest ((try (string "(a)")) <|> string "(b)") "(b)"
"(b)"
[PR]
by tnomura9 | 2009-09-29 06:59 | Haskell | Comments(0)
<< Parsec 意味論 Parsec 連接と選択 >>