これで勝つる! PEGベースのコンパイラコンパイラpaccに触れる
PEG-MLにPEGベースのコンパイラコンパイラ、pacc-0.0のリリースが告知された。
今までyaccやbisonなどを使わなければならなかったパーサも、paccを利用すれば強力なPEGベースのメタ言語を使って記述できる。この記事ではこの登場したばかりのコンパイラコンパイラ、paccに触れてみた。
インストール
コンパイルに必要なboostライブラリを予めインストールしておく。Macならhomebrewからインストールできる。
$ brew install boost
ソースコードをダウンロードしてきて解凍してmake。
$ tar -xvf pacc-0.0.tar.bz2 $ cd pacc-0.0 $ make
エラーが出ずにpaccを叩ければ成功。なんか0.0のバージョン名なのかronin(浪人?)と書いてある。
./pacc -v pacc 0.0 (rōnin) Written by Tobold Jayne Goodwin <toby@paccrat.org> Copyright (C) 2012 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
実際に使ってみる
ドキュメントのチュートリアル通りにやってみる。
まず文法ファイルparser.paccを作成。入力が"yes"であれば1を、"no"であれば0を返す簡単なパーサ。メタ言語の文法はPEGをいくらか拡張しているので、メタ言語の詳細はドキュメントのGrammerの章やソースコードのpacc-0.0/test/pacc以下に含まれているテストケースを参考にする。
/* parser.pacc */ Start <- "yes" {1} / "no" {0}
paser.paccをparser.cにコンパイル。
$ path/to/pacc parser.pacc --output=parser.c
次にmain関数のコードを書く。コマンドラインの引数をそのままパーサに引き渡す。pacc_wrap関数は、生成されたパーサを簡単に呼び出してくれる便利な関数。
/* main.c */ #include <stdio.h> #include <string.h> #include "parser.c" int main(int argc, char **argv) { int result; if (argc != 2) { fprintf(stderr, "one argument please\n"); return 1; } if (pacc_wrap("arg", argv[1], strlen(argv[1]), &result)) { printf("parsed with value %d\n", result); } else { return 1; } return 0; }
$ gcc main.c
試す。
$ ./a.out one argument please $ ./a.out yes parsed with value 1 $ ./a.out no parsed with value 0 $ ./a.out hoge arg:1:1: expected Start
yesやnoを入力するとそれに応じた結果が返り、それ以外の入力を与えるとパースに失敗していることがわかる。