Parsec 入門


Parsec コンビネータ getInput, getPosition

Parsec の入力は入力バッファにコピーされ、パーサによる構文解析が行われる。普通に構文解析するときは、入力バッファの状態を気にすることはないが、getInput 関数と、getPosition 関数を使うと入力バッファの消費されていない部分の文字列と、キャラクタポインタの位置を知ることができる。

getInput

まず、入力を受けたあと全くパターンマッチによる消費が行われていない場合を実験してみる。パーサを利用せずに getInput と getPosition のみを利用するのだ。

Prelude Text.Parsec> parseTest (getInput) "hello, world"
"hello, world"

Prelude Text.Parsec> parseTest (getPosition) "hello, world" (line 1, column 1)

そこで、stirng "hello" を実行したあとの入力バッファの状態を getInput 関数によって表示させる。確かに、マッチした "hello" が消費されているのが分かる。

Prelude Text.Parsec> parseTest (string "hello" >> getInput) "hello, world"
", world"

getPosition

また、キャラクタポインタの位置を getPosition で表示させてみる。

Prelude Text.Parsec> parseTest (string "hello" >> getPosition) "hello, world"
(line 1, column 6)

入力バッファを操作する関数については、この他にも setPosition, setInput などの他、入力バッファを操作する多くの関数があるが、詳細は省略する。それらは、Text.Parsec.Pos モジュールに定義されており、このモジュールをインポートすると実験することができる。

Text.Parsec の関数

これまでの記事でつぎに示す Text.Parsec の関数はだいたい調べることができた。次の目標は、実際のパーサを参考に使い方を学習することになるが、ちょっと休憩。

module Text.Parsec
( -- * Parsers
ParsecT
, Parsec
, token
, tokens
, runParserT
, runParser
, parse
, parseTest
, getPosition
, getInput
, getState
, putState
, modifyState
-- * Combinators
, (<|>)
, (<?>)
, label
, labels
, try
, unexpected
, choice
, many
, many1
, skipMany
, skipMany1
, count
, between
, option
, optionMaybe
, optional
, sepBy
, sepBy1
, endBy
, endBy1
, sepEndBy
, sepEndBy1
, chainl
, chainl1
, chainr
, chainr1
, eof
, notFollowedBy
, manyTill
, lookAhead
, anyToken
-- * Character Parsing
, module Text.Parsec.Char
-- * Error messages
, ParseError
, errorPos
-- * Position
, SourcePos
, SourceName, Line, Column
, sourceName, sourceLine, sourceColumn
, incSourceLine, incSourceColumn
, setSourceLine, setSourceColumn, setSourceName
-- * Debugging
--
-- | As a more comprehensive alternative for debugging Parsec parsers,
-- there's also the [parsec-free](http://hackage.haskell.org/package/parsec-free)
-- package.
--
, parserTrace, parserTraced
-- * Low-level operations
, manyAccum
, tokenPrim
, tokenPrimEx
, runPT
, unknownError
, sysUnExpectError
, mergeErrorReply
, getParserState
, setParserState
, updateParserState
, Stream (..)
, runParsecT
, mkPT
, runP
, Consumed (..)
, Reply (..)
, State (..)
, setPosition
, setInput
-- * Other stuff
, setState
, updateState
, parsecMap
, parserReturn
, parserBind
, parserFail
, parserZero
, parserPlus
) where

import Text.Parsec.Pos import Text.Parsec.Error import Text.Parsec.Prim import Text.Parsec.Char import Text.Parsec.Combinator