中置記法から逆ポーランド記法への変換

中置記法から逆ポーランド記法への変換 - みずぴー日記 にインスパイヤされて awk で中置記法から逆ポーランド記法への変換を行います。 awk ユーザーにとっての経典でもある『Amazon.co.jp: プログラミング言語AWK (新紀元社情報工学シリーズ): A. V. エイホ, P. J. ワインバーガー, B. W. カーニハン, Alfred V. Aho, Peter J. Weinberger, Brian W. Kernighan, 足立 高徳: 本』に既に中置記法の計算方法は記載されていますし、今でも同書籍のサンプルはここから入手することができます。

#! /usr/local/bin/nawk -f
# infix2rep.awk
# 中置記法から逆ポーランド記法への変換
# usage: nawk -f infix2rep.awk

BEGIN {
    print infix2rep("( 1 + 2 / 2 ) - ( 3 + 4 * 5 )");
}

# infix2rep():  中置記法から逆ポーランド記法への変換
#   in:     数式 (eqn)
#   out:    expr
function infix2rep(eqn) {
    num_term = split(eqn, term, /[ ]+/);
    i = 1;
    return expr();
}

# Ref: 『プログラミング言語AWK』
#       Alfred V.Aho (著), Brian W.Kernighan (著), Peter J.Weinberger (著)
# Ref: http://cs.bell-labs.com/cm/cs/who/bwk/awkcode.txt - calc3
function expr(    e) {
    e = terms();
     while (term[i] == "+" || term[i] == "-") {
        e = term[i++] == "+" ? e " " terms() " +" : e " " terms() " -";
    }
    return e;
}

function terms(    e) {
    e = factor();
    while (term[i] == "*" || term[i] == "/") {
        e = term[i++] == "*" ? e " " factor() " *" : e " " factor() " /";
    }
    return e;
}

function factor(    e) {
    if (term[i] ~ /^[+-]?([0-9]+[.]?[0-9]*|[.][0-9]+$)/) {
        return term[i++];
    } else if (term[i] == "("){
        i++;
        e = expr();
        i++;
        return e;
    } else {
        return 0;
    }
}

実行してみましょう。

$ nawk -f infix2rep.awk
1 2 2 / + 3 4 5 * + -

このように逆ポーランドに変換されました。

ちなみに awk では Kenny McCormack が作った中置記法電卓が有名で、これを xgawk の MPFR 拡張で書き直したものはOSC2008 Tokyo/Spring :: Calculator に置いてありますので、参考にしてみてください。

tag_nawk.png tag_nawk.png tag_nawk.png tag_nawk.png