Parsec 入門


Parsec コンビネータ notFollowedBy

notFollowedBy

Parsec のパーサコンビネータ notFollowedBy は引数のパーサが入力にマッチしない場合にマッチと判断する。
Prelude Text.Parsec> parseTest (notFollowedBy digit) "foo"
()
Prelude Text.Parsec> parseTest (notFollowedBy digit) "123"
parse error at (line 1, column 2):
unexpected '1'

何に使うのかというと、たとえば予約語の let と識別子の lets を区別するなどの用途が考えられる。

Prelude Text.Parsec> parseTest (string "let" <* notFollowedBy alphaNum)
 "let a = .. "
"let"
Prelude Text.Parsec> parseTest (string "let" <* notFollowedBy alphaNum)
 "lets = .. "
parse error at (line 1, column 5):
unexpected 's'

makeTokenParser

しかし、自分の言語処理に使う場合、makeTokenParser などが準備するパーサに活用されているので、自分で notFollowedBy パーサをつかってプログラムを書く必要はない。自分用言語のパーサを書くときは、makeTokenPraser や buildExpressionParser を利用することになるだろう。

notFollowedBy の定義

notFollowedBy パーサコンビネータのソースは Hackage によると次のようになっている。

notFollowedBy :: (Stream s m t, Show a) => ParsecT s u m a -> ParsecT s u m ()
notFollowedBy p = try (do{ c <- try p; unexpected (show c) }
                      <|> return ()
                      )

try p でパーサ p を試してマッチしたら、unexpected で例外を発生させる。マッチしていなければ () を戻す。というプログラムのようだ。