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 whereimport 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 に例示されていたものだ。