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 で例外を発生させる。マッチしていなければ () を戻す。というプログラムのようだ。