2007年6月6日水曜日

逆ポーランド記法の式を解く

逆ポーランド記法の式を解く。整数の四則演算(+-*/)のみ対応。
数値は1ケタ限定だが、容易に拡張できると思われる。

エラー報告を比較的丁寧にやっているため、標準エラーは出現しないはず。

関連:

#module
#enum global NO_ERROR = 0
#enum global ERROR_DIVIDE_BY_ZERO
#enum global ERROR_NO_OPERAND
#enum global ERROR_UNKNOWN_CHARCTER
// モジュールで利用するためのスタック
#deffunc _put int p1
    stack(count) = p1
    count++
    return

#defcfunc _get
    if count > 0 {
        count--
    } else {
        // なにもないスタックから取り出そうとした → エラー
        iStat = ERROR_NO_OPERAND
    }
    return stack(count)

#deffunc calc var ans, str p1, local sExp, local iTmp
    sExp = p1
    iStat = NO_ERROR
    count = 0
    repeat strlen(sExp)
        i = peek(sExp, cnt)
        switch i
            case '0':case '1':case '2':case '3':case '4'
            case '5':case '6':case '7':case '8':case '9'
                // 数値の場合はスタックに積む
                _put i - '0'
                swbreak
            // 以下、オペランドの場合はスタックから2つ取り出して演算する
            case '+'
                _put _get() + _get()
                swbreak
            case '-'
                iTmp = _get()
                _put _get() - iTmp
                swbreak
            case '*'
                _put _get() * _get()
                swbreak
            case '/'
                iTmp = _get()
                if iTmp == 0 {
                    // 0で割ろうとした → エラー
                    iStat = ERROR_DIVIDE_BY_ZERO
                } else {
                    _put _get() / iTmp
                }
                swbreak
            default
                // 規定されていない文字 → エラー
                iStat = ERROR_UNKNOWN_CHARCTER
                swbreak
        swend
        if iStat != NO_ERROR : break
    loop
    if iStat == NO_ERROR : ans = _get()
    return iStat
#global

    question = "12+5*""10/""123*1+-2/""12~""1+1"
    repeat length(question)
        calc answer, question(cnt)
        switch stat
            case NO_ERROR
                mes question(cnt) + " = " + answer
                swbreak

            case ERROR_DIVIDE_BY_ZERO
                mes question(cnt) + " = エラー:0で除算しました"
                swbreak

            case ERROR_NO_OPERAND
                mes question(cnt) + " = エラー:オペランドが不足しています"
                swbreak

            case ERROR_UNKNOWN_CHARCTER
                mes question(cnt) + " = エラー:規定されていない文字が含まれています"
                swbreak

            default
                mes question(cnt) + " = エラー:規定されていないエラーです"
                swbreak
        swend
    loop

0 件のコメント: