ちょっとしたツールを Common Lisp で試作するため、Parsing Expression Grammar パーサ生成器があると便利だったため、esarap-peg パッケージを入れてみた。その際の覚書。
esrap-peg を使うには、esrap パッケージがもれなく必要。
インストール
Quicklisp を入れてあれば
(ql:quickload “esrap-peg”)
とすればそれで終わり。利用に際しては、
(require “esrap-peg”) ;; require に asdf が織り込まれていない場合は (asdf:load-sytem :esrap-peg) など適宜
;; パッケージ名をいちいち打つのが面倒なら
(use-package ‘(:esrap-peg))
とでもしておけばよい。
使い方
例えば、C 言語風の整数定数表現を解釈するパーサ(まあほとんど字句解析)を PEG で
integer_constant <- hexadecimal_integer_constant / octal_integer_constant / ecimal_integer_constant
hexadecimal_integer_constant <- ((‘0’ (‘x’ / ‘X’) [0-9a-fA-F]+) / ([0-9a-fA-F]+ (‘h’ / ‘H’))) integer_constant_postfix
octal_integer_constant <- ‘0’ [0-7]+ integer_constant_postfix
decimal_integer_constant <- (‘+’ / ‘-‘)? [0-9] [0-9]* integer_constant_postfix
integer_constant_postfix <- (‘u’ / ‘U’)? (‘l’ / ‘L’)?
などと定義して、foo.peg ファイルにでも突っ込んで置く。その上で、
(esrap-peg:peg-compile (esrap-peg:parse-peg-file “foo.peg”))
(esrap:parse ‘integer_constant “0x1f”)
=> (INTEGER_CONSTANT (HEXADECIMAL_INTEGER_CONSTANT ((“0” “x” (“1” “f”)) (INTEGER_CONSTANT_POSTFIX (NIL NIL)))))
NIL
T
とかなんとか。要するに
- esrap-peg:parse-peg-file で PEG 定義ファイルを読み込むと相応する S 式の文法定義が得られる
- それを esrap-peg:peg-compile に食わせると相応する esrap:parse 関数が出来る
- その esrap:parse に第一引数に文法構成要素、第二引数にパース対象文字列を渡して呼べば、パース対象が指定した文法に合致するものであるかどうかを解釈してくれる
大筋は上のような感じ。実際のところは、構文エラーの場合のコンディション処理とかいろいろあるわけだけれど。
正直、esrap-peg 側の説明だけだと何をどうすれば良いのか全然わからなかった。esrap 側の説明見て、やっと合点がいった次第。
あと、esrap-peg にせよ esrap にせよ、利用例などの情報がネット上にほとんどない(グーグル先生に訊ねても有用な回答が得られない)ため、案外利用者は少ないのか?