JavaScriptで中置記法から後置記法(逆ポーランド表記法)への変換

昨日作った VBScriptJavaScript版。配列操作が組み込み関数で出来るので楽ちん。
ブラウザで表示させながら、逆ポーランド表記法がどんなもんか説明しようと思ったが、
はてなダイアリーでは JavaScript が使用できなかった。

postfix.js

function usage() {
    var s = "(a+b)*(c+d)";
    var infix   = split_formula(s);
    var postfix = get_postfix(infix);
    alert(s + " =>" + postfix.join(" "));
}


// 数式を演算子とオペランドに分割する
function split_formula(s) {
    var a = new Array();
    
    s = s + " "; var literal = "";
    for (i = 0; i < s.length; i++) {
        var c = s.charAt(i);
        if ("+-*/() ".indexOf(c) != -1) {
            if (literal != "") a.push(literal)
            if (c != " ")      a.push(c)
            literal = "";
        } else {
            literal = literal + c;
        }
    }
    return a;
}

// 中置記法を後置記法に変換する
function get_postfix(infix) {
    var postfix = new Array();
    expression(infix, postfix);
    return postfix;
}

function factor(infix, postfix) {
    if (infix[0] == "(") {
        infix.shift();
        expression(infix, postfix);
        if (infix[0] == ")") infix.shift();
    } else {
        postfix.push(infix.shift());
    }
}

function term(infix, postfix) {
    factor(infix, postfix);
    while (1) {
        var c = infix[0];
        if (c == "*" || c == "/") {
            infix.shift(); factor(infix, postfix); postfix.push(c);
        } else {
            break;
        }
    }
}

function expression(infix, postfix) {
    term(infix, postfix);
    while (1) {
        var c = infix[0];
        if (c == "+" || c == "-") {
            infix.shift(); term(infix, postfix); postfix.push(c);
        } else {
            break;
        }
    }
}


ついでに、計算方法も

calcPosfix.js

function usage() {
    var expr = "1 2 3 * +";      // 1 + 2 * 3 = 7
    var postfix = expr.split(' ');
    var result = calcPostfix(postfix);
    alert(result);
}


function calcPostfix(postfix) {
    var stack = new Array();
    for (i = 0; i < postfix.length; i++) {
        var c = postfix[i];
        switch (c) {
            case '+': stack.push(  stack.pop() + stack.pop()); break;
            case '-': stack.push( -stack.pop() + stack.pop()); break;
            case '*': stack.push(  stack.pop() * stack.pop()); break;
            case '/': stack.push(1/stack.pop() * stack.pop()); break;
            default:  stack.push(isNaN(c) ? 0 : parseInt(c));
        }
    }
    return stack[0];
}