catch.jp blog

デジタルをわかりやすく。

2014-7-17

yaccによるJavascript電卓

Category: Programming   

※「catch.jp-wiki」から移動したページです。

つい作ってみたくなりました。とりあえずは、yacc/bison系ツール(kmyacc)を使ったJavascript電卓です。特に、日本語プログラミング言語を作るところまで、たどり着きたいのですが・・・

基本的なこと

スクリプト言語は、概ねこんな内部構造になっている(はず)。

スクリプト言語の内部構造

スクリプト言語というソフトウェアは、ソースコードを入れると、ライブラリや入力データと組み合わせて、出力結果を得られるプログラム。その中身は、大きく3つに分かれている。字句解析は、ソースコードの文字を切り分ける。構文解析は、それをコンピュータに分かる命令に変換する。で、それをVM(バーチャルマシン)が実行する。大昔は、リアルなCPUが実行するために、バーチャルマシンではなく、マシン語に変換していたんだけれど、今では、CPUが高性能すぎたり、特定CPUへの依存性をなくすために、こんなふうになっている。

で、スクリプト言語を作るためには、この3つ(字句解析、構文解析、VM)が必要。字句解析は、割と簡単(らしい)。有り物を拾ってくればなんとかなる(だろう)。VMは、他のプログラミング言語でも持っていたり、他の言語自体をVMとして使うとか(つまり、プログラミング言語のトランスレータ/変換器にする)。で、構文解析は、設定ファイルを書くと、yaccが自動変換して構文解析プログラムを作ってくれる。

kmyaccのサンプルファイルでやってみる

というわけで、スクリプト言語の構文解析プログラムを作るために、yaccの使い方でも覚えてみるかなぁ。ここでは、kmyaccを使って、Javascript製の電卓を作ってみます。

実行形式版の入手

とりあえず、下記からダウンロード。

ソースコード版とサンプルファイルの入手

kmyaccのサンプルファイルは、ソースコード版に収録されている。だから、実行形式版だけ使う場合も、ソースコード版を入手しておいたほうがいいです。

準備

kmyaccで、必要なものは以下。

  • kmyacc.exe
  • cygwin1.dll
  • libフォルダ一式
  • calc.jsy(Javascript用電卓のサンプルファイル:ソースコード版に収録)

なぜ、電卓を作るのかというと、「3 + 4 * 5」という式があると、掛け算(*)のほうが足し算(+)より、優先順位が高い、というように手頃な例題になるから。ちなみに、kmyaccのJavascriptサンプルには、字句解析のコードも含まれている。

変換する

では、kmyaccで、サンプルファイル(calc.jsy)を実際の電卓プログラムに変換します。Windowsのコマンドラインで、次のように実行する。

> kmyacc calc.jsy

これで、calc.jsファイルが生成されました。

なおkmyaccは、設定ファイルの拡張子から、以下のルールに従ってホスト言語を推定します。

yacc拡張子 ホスト言語 出力ファイル拡張子
.y C y.tab.c
.jy Java .java
.jsy JavaScript .js
.ply Perl .pl

実行してみる

この「calc.js」ファイルには、Javascript以外にも、すでに必要なコードとかhtmlが組み込まれているので、これを「calc.html」とファイル名を変更してブラウザで開くと、計算できます。ちゃんと、優先順位やカッコも認識してくれる。ただし、整数だけ。

計算には、次の記号が使えます。

  • + 足し算
  • - 引き算
  • * 掛け算
  • / 割り算
  • (...) カッコ内を先に計算する

yaccソースファイルは、こんな感じ。これは、kmyaccのサンプルファイルそのまま(パブリックドメイン)。構文定義の前後に、出力するhtmlファイルやjavascriptも含まれています。

原理などは、下記が参考になります。

電卓練習

上記のサンプルを改良して、いろいろな電卓を作ってみます。

逆ポーランド記法の電卓

上記のBison 1.28マニュアルに記載されているサンプルコードを元にして、逆ポーランド記法(reverse polish notation)の電卓を作ってみた。

例:1 5 + 2 3 + *
> 30

この例は、(1+5)*(2+3)と同じになります。

べき乗と剰余を追加

最初のサンプル電卓に、べき乗(累乗:^)と剰余(割り算の余り:%)を追加。

2 ^ 3 => 8
7 % 2 => 1

複数行電卓

電卓(べき乗と剰余付き)を複数の行で同時に計算できるようにしてみました。

クリアボタンで、計算式と計算結果を消します。

変数付き複数行電卓

さらに、変数を使えるようにしてみた。わーい、わーい!

変数名には、先頭に半角英字(a-z、A-Z)、2文字目以降に半角英数字(a-z、A-Z、0-9)が使えます。

字句解析も少し修正。

a = 10
b = 20
a * b => 200

組み込み関数を追加した電卓

また電卓。次の組み込み関数を追加しました。

使い方は、こんな感じ

test(123) > 123
sqr(4) > 2
rnd(10) > 6.290423613972962

カッコ内に、引数を数値で一個だけ書けます。

2個以上の引数の関数は組み込めません。(num1, num2)とか(num1 num2)といった記法に対応していないためです。

実装的には、組み込んだ関数名をメソッドとして呼び出せるようにしています。


Part2.yaccによるWebスクリプト言語に続く

ソース

参考資料