part2.yaccによるWebスクリプト言語Part1.でJavascript電卓ができたので、次は簡単なスクリプト言語を作ってみます。スクリプト言語の開発に必要な基本的な技術を確認するために、ものすごーく簡単なスクリプト言語を作ります。このページでは、kmyaccをツールとして、Javascriptで動くものを作ります。構文木などは作らないで、別のプログラミング言語へ変換だけやります。Script(猿真似スクリプト)という名前を付けることにします。†スクリプト言語では、電卓と違って、文字列やコメントなどを扱うので、まずスキャナー(字句解析)を作り直します。構文解析に先立って、コードの文字の切り出しと分類を行うのが、このスキャナー。analyzer)と呼ばれます。電卓では、yaccのサンプル定義ファイルに、スキャナーのコードが埋め込まれていましたが、それを差し替えます。ここでは、スキャナーが動作するサンプルページを用意しました。サンプルページ文字の判別には、正規表現を使っています。元の電卓用スキャナーとyaccの実装スタイルに合わせて、グローバル変数(!)を使っています。†スキャナは、コードを次のように分類して構文解析に送ります。IDENT役割:識別子(変数名や関数名)規則:最初の文字が、英文字(a-zとA-Z)にアンダーバー(_)。規則:小数点も使える。規則:ダブルクォーテーション(")かシングルクォーテーション(')で囲むCOMMENT役割:コード中のコメント(注釈)。計算記号やカッコなど次のように入力した場合123abc"xyz"//comment次のように表示されます。COMMENT1先頭は改行位置(改行記号がない場合は「-1」)。そのあと、現在解析している文字、切り出し結果、分類結果と続きます。コメント文を判別できるようにしています。通常、コメント文は無視して捨てるけれど、この簡易スクリプト言語は変換器なので残すようにしています。動作確認のため、スキャナーで分類した結果を素通しするような構文解析器(parser:パーサー)を作ってみました。};サンプルページスキャナーが分類した結果は、構文解析側で判断して、分類とデータを表示します。//456と表示されます。次は、パーサーを拡張して、代入文と関数と引数を書けるようにします。これで、プログラムっぽいものが、記述できるようになります。//comment次のように、そのまま表示されます。a=200x()y(100)z(1,2,3,4)a=1*(2+3)b=x(100)c=200//comment入力したプログラムを、いったんスキャナーでバラバラにして、それをパーサーで組み立てなおしているのです。ここまでの段階で対応しているのは、次の構文です。error」と表示されます。error」と表示されます。abcここまでの、ソースファイルは次のようになっています。†ここで作っている簡易スクリプト言語は、ターゲット言語をProcessing.jsにしています。Processing.jsは、ビジュアルデザイン用プログラミング言語Processing(プロセッシング)のWeb版です(JavascriptベースのProcessing)。グラフィックアニメーションやユーザーによる操作が取り扱いやすくなっています。Processing.jsによる、アニメーションサンプルはこんな感じです。mouse_move簡易スクリプト言語の主な機能は、次のような感じにします。命令や関数などはProcessing.jsとおんなじ。末尾のセミコロン(;)は不要。If文とかFor文とかWhile文とかも、(とりあえず)なし。Processing.jsだと、なしでもそれらしいプログラムが作れるので。クラス定義はあるけれど、クラス生成は(今のところ)なし。mouseY)}こんなふうに、Processinng.jsに変換されます。mouseY);}サンプルページとソースファイルは次のようになっています。サンプルページyaccソースファイルこれだけでは、機能的には特別うれしいところはありませんが、独自文法のスクリプト言語の作るもとになるはず。†ついに、できました!変換したコードをProcessing.jsに渡して実行します。サンプルページのRunボタンをクリック。それから、右側の黒色エリアにマウスポインタを合わせると、その位置に合わせて楕円が描かれます。そのすぐ下には、変換後のスクリプトが表示されます。非常に簡易的なスクリプト言語なので、次のような注意が必要です。*/」を使った、複数行にまたがるコメントは、今のところ使えません。†スクリプトは、変換して直接実行しているので、デバッグツールを適用できません。変換後のスクリプトを、Processing.jsに直接貼り付けるともう少しやりやすくなるかも。Scriptは、いくつかグローバル変数を使っています(yyyBuffer、yyyToken、yylval)。特別な名前にしてあるので、衝突することは、ほとんどないと思いますが、念のため注意してください。グローバル変数を使っていると、他のプログラムと衝突するので、Javascriptの場合は変換プログラムをクロージャーにするとか、対策しなくちゃならないなー。思っていたけれど、調べてみたら、ちょっと手間がかかるので、後回しにしました。Amazonあなたは「+-><.,[]」の8つの記号しかないプログラミング言語や、空白だけで構成されるプログラミング言語があるのをご存じだろうか。Language)を題材にプログラミング言語の作り方を解説します。AmazonRuby+Raccなら、プログラミング言語開発だって楽しくなる!パーサジェネレータという硬派なネタを256倍流に完全解説。メタプログラミングhttp://itpro.nikkeibp.co.jp/article/COLUMN/20070604/273453/まとめてみると,Rubyは非常にDSL向きな言語だと分かります。