parent
7b0ad8a747
commit
de5cfa955d
@ -0,0 +1,81 @@ |
||||
# PEGで言語をデザインしてみよう |
||||
|
||||
PEGについて一言で説明しなさいと言われたら,「言語を定義するための言語」と答えるつもりです。パーサジェネレータは,このPEGを使って定義されたプログラミング言語の厳密な文法定義を読み込んで,パーサを生成することができます。 |
||||
|
||||
この「PEG言語」はC++やJavaScriptなどの処理手続きを記述する言語とはずいぶん毛色が違います。むしろ正規表現,XML Schemer,DBのテーブルスキーマのような「規則を定義」するタイプの言語に似ています。 |
||||
|
||||
この章では,次の「言語」をPEGを使って定義してみます。 |
||||
|
||||
* 日本語の「文」 |
||||
* カンマ区切り行 |
||||
* 括弧付き四則計算式 |
||||
* JSON |
||||
* JavaScriptの小さなサブセット |
||||
|
||||
下に行くほど文法定義が難しくなり,PEGのより多くの記法を使う必要が出てきます。これらの例が終わる頃には,簡単なスクリプト言語を自分でデザインできるようになるでしょう。(もちろん文法を定義しただけなので,コードを動きませんが。^^;) |
||||
|
||||
PEGの記法については,この章を読み進めるうちに自然に学べるように書いているつもりです。しかし時間があれば,kimizuさんの[「PEG基礎文法最速マスター」][Link_BasicGrammar]をご覧ください。PEGの記法について,とても簡潔にわかりやすくまとめられています。下記の例題を始める前に一読するなら,理解が確実に速まること間違いなしです。 |
||||
|
||||
「習うより慣れろ」と古くから言われるように,実際に手を動かしてコードを書くことは理解を深めるための早道です。その際[「PEG Playground」](http://yhirose.github.io/peglint/)ご活用ください。このWeb アプリは,PEGの文法定義コードと定義される言語のコードをリアルタイムに行ってくれます。 |
||||
|
||||
ではさっそく一番目の例から見てみましょう。 |
||||
|
||||
## 日本語の「文」を定義する |
||||
|
||||
文法と聞くと,遠い昔の国語の授業を懐かしく思い出します。ではPEGを使って,簡単な「文」のルールを作ってみましょう。こんな感じでどうでしょうか? |
||||
|
||||
文 <- 主語 述語 '。' |
||||
|
||||
「文」は,連続する「主語」「述語」「'。'」で成り立っています。さらに「主語」と「述語」は, |
||||
|
||||
主語 <- 名詞 助詞 |
||||
述語 <- 動詞 助詞 |
||||
|
||||
と品詞を使って定義してみました。それぞれの品詞に実際の言葉を幾つか入れてみましょう。 |
||||
|
||||
名詞 <- 'サーバー' / 'クライアント' |
||||
動詞 <- '落ち' / '復旧し' |
||||
助詞 <- 'が' / 'を' / 'た' / 'ます' |
||||
|
||||
ではこのルールにマッチする文を考えましょう。例えば, |
||||
|
||||
サーバーが落ちた。 |
||||
|
||||
悲しいですが,この文はルールにマッチします。 |
||||
|
||||
サーバーを復旧します。 |
||||
|
||||
希望が見えてきました。 |
||||
|
||||
プログラムが落ちた。 |
||||
|
||||
プログラムが「名詞」のリストにないので,マッチしません! |
||||
|
||||
文法を少し修正しましょう。 |
||||
|
||||
文 <- 修飾語? 主語 述語 '。' |
||||
名詞 <- 'サーバー' / 'クライアント' |
||||
形容詞 <- '古い' / '新しい' |
||||
動詞 <- '落ち' / '復旧し' |
||||
助詞 <- 'が' / 'を' / 'た' / 'ます' / 'に' |
||||
|
||||
「文」ルールに「修飾語」を追加しました。`?`が付いていますが,これは「出現してもしなくてもよい」という意味です。また「形容詞」ルールも加わりました。これで次のような文全てがマッチします。 |
||||
|
||||
サーバーが落ちた。 |
||||
古いサーバーが落ちた。 |
||||
サーバーを復旧します。 |
||||
新しいサーバーに復旧します。 |
||||
|
||||
PEGの感覚がつかめてきましたか? |
||||
|
||||
さて,ここまでで使用した4つの記法についておさらいしましょう。 |
||||
|
||||
| 記法 | 意味 | | |
||||
|:-----|:---------------------------------------------| |
||||
| <- | ルールの定義 | 右側がルール名,左側はPEGの式 | |
||||
| / | 選択|右から左へ順番にマッチを試みる | |
||||
| ? | 0回または1回 | | |
||||
| '' | 文字列リテラル | | |
||||
|
||||
|
||||
[Link_BasicGrammar]: http://kmizu.hatenablog.com/entry/20100203/1265183754 |
@ -1,16 +1,30 @@ |
||||
前書き |
||||
===== |
||||
# 前書き |
||||
|
||||
今この本をに目を通してくださっているみなさんは、「ぜひプログラミング言語を作ってみたい!」と考えている方のお一人でしょう。でも自分で言語を作ってみるなんて敷居が高過ぎるのでは?何を隠そう少し前の私も,『コンパイラ』と名の付く技術書をパラっと眺める度に,その内容の難しさに恐れを抱きました。orz... |
||||
今この文章をに目を通してくださっているみなさんは、「いつか自分でプログラミング言語を作ってみたい!」と思ったことがあるかもしれません。でもほとんどの人は「正直言って,言語を作るなんて自分には敷居が高過ぎる」とあきらめてしまいます。ご安心を! |
||||
|
||||
しばらく前のこと,仕事で数十万行にも及ぶ大きなデータファイルを作成する必要がありました。エディタを使って手作業するなら軽く数ヶ月かかってしまいます。それでは大変なので,設定ファイルを定義してプログラムにデータを生成させようということになりました。数千行の設定ファイルを作れば,ものの数分で膨大なデータを生成してくれるのです。 |
||||
何を隠そうこれまでの私も,「コンパイラ」とか「インタープリタ」名の付く技術書を幾つも眺めてきました。「字句解析,構文解析,インタープリタ,VM…」など,本に書かれている概念自体はある程度理解できるものの,それを実装して実際に動くものを作るのは別問題です。 |
||||
|
||||
はたして「プログラミング言語のようなもの」を作ることになりました。「さて,どう実装する? YACCを使う? パーサーを手書きで書く? でも面倒で難しそう...」と悩みつつWebで検索していたところ,偶然[『PEG』](https://ja.wikipedia.org/wiki/Parsing_Expression_Grammar)という可愛らしい言葉が目に入りました。PEGとは「Parsing Expression Grammar」の略号です。調べてみると,難しそうなYACCより簡単に文法が定義でき,かつPEGをサポートするライブラリがパーサーを生成してくれるのです。さらに調べてみると,PEGライブラリ自体が誰にでも比較的簡単に実装可能ということも発見しました! |
||||
でもしばらく前のこと,仕事で数十万行にも及ぶ大きなデータファイルを作成する必要がありました。エディタを使って手作業するなら軽く数ヶ月かかってしまいます。それでは大変なので,設定ファイルを定義してプログラムにデータを生成させようということになりました。数千行の特別な書式の設定ファイルを準備すれば,ものの数分で膨大かつ正確なデータを生成してくれるのです。 |
||||
|
||||
それでWeb上の記事をいろいろ漁りながら,仕事で使っているC++用のPEGライブラリを見よう見まねで作り始めました。はい,コンピュータサイエンスを正式に学ぶことのなかった私でも、意外とあっさり実装できました。そのあと設定ファイルの文法をデザインし(これがまたとても面白い!),そのパーサーをPEGライブラリでいとも簡単に作ることができました。嬉しいことに、仕事のプロジェクトはとてもうまくいきました。 |
||||
はたして「プログラミング言語のようなもの」を作ることになりました。まずは設定ファイルをパースしなければなりません。「さて,パーサをどう実装する? Yaccのようなパーサージェネレータ使う? パーサーを手書きで書く? いずれにしても面倒で難しそう…」と悩みつつWebで検索していたところ,偶然[『PEG』][Link_PEG]という言葉を目にしました。PEGとは「Parsing Expression Grammar」の略号です。調べてみると,Yaccより簡単に扱えるパーサージェネレータだそうです。さらに調べていくとPEGパーサジェネレータ自体を実装する記事がWeb上に幾つもあり,誰でも比較的簡単に実装できるということがわかりました! |
||||
|
||||
これが契機となって、「もう少し頑張れば、自分にもプログラミング言語を作ることができるかも」と思えるようになりました。文法定義とパーサーの生成がとても簡単になったので,言語作成の敷居がぐっと下がったように感じたのです。さらにこのPEGライブラリをもっと使いやすくなるよう改良を重ね,実際にミニプログラミング言語を作って動かすことができました。これがまたとても面白い! |
||||
さっそく日々の仕事で使っているC++で,PEGパーサジェネレータを作り始めました。はい,コンパイラ作成の授業など取ったことのなかった私でも,意外にあっさり実装できてしまいました。その後,先の設定ファイルの文法をPEGでデザインし(これがまたとても面白い!),そのパーサーをPEGライブラリでいとも簡単に作ることができました。嬉しいことに、仕事のプロジェクトはとても上手くいきました。 |
||||
|
||||
恥ずかしい話ですが,今でも「字句解析,構文解析,構文木,意味解析,コード生成,最適化...」について、そこそこの深い知識しか持ち合わせていません。PEGの[オリジナルの論文](http://bford.info/pub/lang/peg)理論も完璧に理解しているわけではありません。それでも言語処理系を作ることの楽しさを十分経験でき,さらにこの分野をもっと勉強したいというモチベーションを得ることもできたことは大きな収穫でした。 |
||||
これが契機となって、「もう少し頑張れば、自分にもプログラミング言語を作ることができるかも」と思えるようになりました。文法定義とパーサーの生成がとても簡単になったので,言語作成の敷居がぐっと下がったように感じたのです。さらにこのPEGパーサジェネレータ改良を重ね,実際にシンプルな言語を作って動かすことができるようになりました! |
||||
|
||||
皆さんにもこの同じ喜びを味わっていただきたと思い,この文章を書いています。必要なのはテキストエディタ(当然Vimですよね?)とC++11対応のコンパイラだけです。最新のClang,GCC,Visual C++をお持ちであれば,さっそく始めましょう! |
||||
正直なところ,今でも「コンパイラ技術」についての深い知識は持ち合わせていません。PEGの[オリジナルの論文][Link_Paper]に書かれている理論も完璧に理解しているわけではありません。それでも言語処理系を作ることの楽しさを十分味わい,この分野についてもっと勉強したいというモチベーションを得ることもできたことは素晴らしい経験でした。 |
||||
|
||||
皆さんにもこの同じ喜びを味わっていただきたと思い,この文章を書いています。想定している読者は,ある程度のプログラミングの経験を持っていて,自分で言語を創りあげたいとの熱意を持っている方です。 |
||||
|
||||
必要な道具はC++11対応のコンパイラだけです。最新の主要C++コンパイラは,Clang,GCC,Visual C++にかかわらず,全てC++11に対応しています。以下のおなじみHello Worldコードをコンパイル・実行できる環境があれば,準備は完了です。 |
||||
|
||||
```cpp |
||||
#include <iostream> |
||||
int main(void) { |
||||
std::cout << "hello world!\n"; |
||||
}``` |
||||
|
||||
では,さっそく始めましょう! |
||||
|
||||
[Link_PEG]: https://ja.wikipedia.org/wiki/Parsing_Expression_Grammar |
||||
[Link_Paper]: http://bford.info/pub/lang/peg |
||||
|
Loading…
Reference in new issue