Parsec 入門


Parsec buildExpressionParser

buildExpressionParser

Text.Parsec.Expr モジュールの buildEpressionParser を使うと、式 (expression) のパーサを自動的に作成できる。

手順としては、先ず makeTokenParser 関数で必要なトークンパーサを作する。次に項 (term) の定義を行う。そのあとで、演算を定義するテーブルを作成する。テーブルの prefix, postfix, bainary などはユーザが定義する関数だ。最後にそのテーブルと項を引数に式のパーサを作成することになる。

expr.hs

以下に実際に動作確認したプログラムを示す。このプログラムは色々な式のパーサの作成の雛形に利用できる。(アンダースコアは空白に置き換える)

実行例:

Prelude> :l expr.hs
[1 of 1] Compiling Expression ( expr.hs, interpreted )
*Expression> parseTest expr "2++"
3
*Expression> parseTest expr "-2 + 3"
1
*Expression> parseTest expr "(1 + 2) * (3 + 4)"
21

ファイル名:expr.hs

module Expression where

import Text.Parsec import qualified Text.Parsec.Token as P import Text.Parsec.Language (emptyDef) import Text.Parsec.Expr

lexer = P.makeTokenParser emptyDef natural = P.natural lexer parens = P.parens lexer reservedOp = P.reservedOp lexer

expr = buildExpressionParser table term <?> "expression"

term = parens expr <|> natural <?> "simple expression"

table = [ [prefix "-" negate, prefix "+" id] , [postfix "++" (+1)] , [binary "*" (*) AssocLeft, binary "/" (div) AssocLeft] , [binary "+" (+) AssocLeft, binary "-" (-) AssocLeft] ]

binary name fun assoc = Infix (reservedOp name >> return fun) assoc prefix name fun = Prefix (reservedOp name >> return fun) postfix name fun = Postfix (reservedOp name >> return fun)

パーサのプログラムは理解するのは難しいが、定型的になるので、参考になるプログラムがあれば、改造して利用することが可能だろう。問題はその参考プログラムをどこから探すかということだ。ちなみに、上のプログラムは Hackage の Text.Parsec.Expr に例示されていたものだ。