Parsec anyToken
anyToken
anyToken はどんなトークンもマッチする。しかし、トークンが空のときだけエラーを返す。トークンというのがよくわからないが、文字の場合もトークンとして反応するようだ。Prelude Text.Parsec> parseTest anyToken "abc" 'a' Prelude Text.Parsec> parseTest anyToken "\n" '\n' Prelude Text.Parsec> parseTest anyToken "" parse error at (line 1, column 1):
多バイト文字にも反応する。
Prelude Text.Parsec> parseTest anyToken "あいうえお" '\12354'
notFollowedBy
notFollowedBy パーサと組み合わせると eof パーサを作ることができる。
Prelude Text.Parsec> parseTest (notFollowedBy anyToken) "" () Prelude Text.Parsec> parseTest (notFollowedBy anyToken) "abc" parse error at (line 1, column 1): unexpected 'a'Prelude Text.Parsec> parseTest eof "" () Prelude Text.Parsec> parseTest eof "abc" parse error at (line 1, column 1): unexpected 'a' expecting end of input
トークンとは何か
トークンとは何なのかが気になったので anyToken の型を調べてみた。
Prelude Text.Parsec> :t anyToken anyToken :: (Show t, Stream s m t) => ParsecT s u m t
この中で Stream というクラスが気になったので調べてみた。
Prelude Text.Parsec> :i Stream class Monad m => Stream s (m :: * -> *) t | s -> t where uncons :: s -> m (Maybe (t, s)) {-# MINIMAL uncons #-} -- Defined in ‘Text.Parsec.Prim’ instance [safe] Monad m => Stream [tok] m tok -- Defined in ‘Text.Parsec.Prim’
Stream クラスの uncons という関数があるようだ。
Prelude Text.Parsec> uncons "foo" Just ('f',"oo")
引数の先頭の文字と、残りの文字列のペアを作る関数のようだ。
結局トークンの意味は分からなかった。Parsec はまだ謎が多い。とにかく anyToken パーサは文字列が空ではないことに反応することがわかった。