BNF記法の事例として書いたプログラムである。
本来の四則演算の構文規則(BNF記法)は
<addsub> ::= <addsub> + <muldiv> | <addsub> - <muldiv> | <muldiv>
<muldiv> ::= <muldiv> * <factor> | <muldiv> / <factor> | <factor>
<factor> ::= 数値 | ( <addsub> )
であるが、これでは再帰プログラムが書けないので、次のように書き換える。
<addsub> ::= <muldiv> { + <muldiv> | - <muldiv> }
<muldiv> ::= <factor> { * <factor> | / <factor> }
<factor> ::= 数値 | ( <addsub> )
プログラム・ソースを以下に示す。
calc01.js
var input = "";
var items = new Array();
var nItem = 0;
var ix = 0;
var num = "";
function push(c) {
if (c == 'C') {
input = "";
items = new Array();
nItem = 0;
ix = 0;
num = "";
} else if (c.match(/\d|\./)) {
num += c;
input += c;
} else if (c == '=') {
if (num.length > 0) {
items[nItem++] = num;
num = "";
}
input += "=" + calc(items);
} else if (c != '') {
if (num.length > 0) {
items[nItem++] = num;
num = "";
}
items[nItem++] = c;
input += c;
}
document.getElementById('in').value = input;
}
function array(id) {
var labels = [
["0", "1", "2", "+", "("],
["3", "4", "5", "-", ")"],
["6", "7", "8", "*", ""],
["9", ".", "C", "/", "="] ];
var buttons = "<table border='0'>";
for (var i = 0; i < labels.length; i++) {
buttons += "<tr>";
for (var j = 0; j < labels[i].length; j++) {
buttons += "<td><input type='button' value='" + labels[i][j]
+ "' onclick=push('" + labels[i][j] + "')></td>";
}
buttons += "</tr>";
}
buttons += "</table>";
document.getElementById(id).innerHTML = buttons;
input = "";
}
function calc(){
return addsub();
}
function addsub(){
var val = muldiv();
while (ix < items.length && items[ix].match(/[\+-]/)) {
val = ("+" == items[ix++]) ? (val + muldiv()) : (val - muldiv());
}
return val;
}
function muldiv(){
var val = factor();
while (ix < items.length && items[ix].match(/[\*/]/)) {
var op = items[ix++];
val = ("*" == op) ? (val * factor()) : (val / factor());
}
return val;
}
function factor(){
var val;
if ("(" == items[ix]){
ix++;
val = addsub();
if (")" != (items[ix])) alert(")がありません!");
ix++; // ポインタを ) の次へ進める
} else {
val = parseFloat(items[ix++]);
}
return val;
}