さかとくです。最近では、JavaScript上でJavaバイトコードが実行できたり(Orto)、JavaScriptでScheme(jsScheme)が動いたりと、とても楽しい状況ですね。ブラウザさえあれば、その上でいろんなプログラミング言語を体験することができるのですから!
私も、これまで、マクロ言語やスクリプト言語をいくつか作ってきました。(代表作は、音楽のプログラミング言語「サクラ」や、日本語プログラミング言語「なでしこ」などです。)今は、ブラウザ上で動く日本語プログラミング言語を開発中ですが、これはまだ見せられる状況ではありません。
そこで、ウノウラボを書くのに与えられただろう時間(約1時間)で、オリジナルのプログラミング言語を作ってみようと思います。もちろん、JavaScriptだけで。
では、はじめてみましょう!
(1) コンパイラコンパイラをゲットする
はじめに用意するのは、コンパイラコンパイラです。これは、文法規則を与えると、自動的にプログラミング言語のソースコードを吐いてくれるというとても便利な道具です。今回は、時間も限られているので、とにかく、Googleで「javascript コンパイラコンパイラ」で検索してみます。
すると、弊社CTOの尾藤が書いた、「ベイエリア情報局: Javascriptも出力できるコンパイラコンパイラ」が見つかりました。既に「JavaScriptなでしこ」なる言語を作って公開しているようです。
その時、使ったのが「kmyacc - 多言語対応LALRパーサー生成系」のようで、時間もないのでさっそく、これをダウンロードして、マニュアルを見ながら、Cygwin上でmakeしてみました。何の障害もなくインストール完了です。でも、よく見たら、実行ファイル版(VC++版)もあるようなので、自分でmakeしなくてもよかったのです。いきなり時間浪費してしまいました。
(2) サンプルを研究する
次に、用意されているデモプログラムのソースを見て、だいたいの感じをつかみます。幸いなことに、文法の定義方法は、Yaccとほとんど同じようです。本来なら、Yaccの使い方も解説したいところですが、何しろ1時間と限られていますので諦めます。Yaccが分かれば、ほとんど悩むことなしに、kmyaccを使いこなせるでしょう。
(3) 変数が使えるようにする
次にサンプルをコピーして適当に文法を付け加えていきます。サンプルでは、四則演算ができるだけのものでした。そこで、とりあえず、変数が使えるように、代入の定義を追加してみます。
start : lines { parser_result = $1; } ; lines : /**/ { $$ = null; } | line { $$ = $1; } | lines EOL { $$ = $1; } | lines EOL line { $$ = $3; } ; line : expr | let ; let : WORD '=' expr { variables[$1] = $3; } ; expr : expr '+' expr { $$ = $1 + $3; } | expr '-' expr { $$ = $1 - $3; } | expr '*' expr { $$ = $1 * $3; } | expr '/' expr { $$ = $1 / $3; } | expr '%' expr { $$ = $1 / $3; } | value ; value : NUMBER { $$ = $1; } | WORD { $$ = variables[$1]; } ; |
まず、複数行のプログラムを読めるように、linesという定義を加え、次に、「WORD '=' expr」という定義を追加したのです。
(4) タイムアウト
・・・と、このような感じで、1時間終了です。やはり、1時間では、変数が使える電卓が限度のようです。もう半日あれば、変な言語に改良できるんでけど、これは、またの機会にしてみます。
ここまでで作ったものは、以下のような感じです。
[calc]ボタンを押すと計算できます。