Formula Parser式解析クラス


FormulaParser     
        ,    .    ,     .

    :

format  :
        ,     if  ,         ,      .          ,  

      .

calculate  :
      ,            ,                .

   :

/* 
* FormulaPareser       
* Version 1.0 
* 2006.8.11 
* Copyright CYJB 
*/ 
// 
/* 
*      ,        (+),  (-),  (*),  (/),  (^),  (%)       . 
* format()     .         : 
* 1."+","-"       ,      、  . 
* 2.        (  "^*"),         ("+""-"  ).        "+","-",   

   +1,-1. 
* 3.         ,          . 
* 4. "(" ")"    ,           . 
* 5.           (  ".0123456789+-/*%^()"). 
* 6.    "(  )"     
* calculate()    .       (     format        ),          
* (    format  ).            ,        . 
*   :          ,         (  flash    ). 
*/ 
// 
class FormulaParser { 
        public static function format(s:String):Array { 
                //      
                var data:Array = []; 
                var backets:Array = []; 
                //       
                var n = 0; 
                var s1 = s.charAt(n); 
                while (s1.length == 1) { 
                        var k = s1.charCodeAt(0); 
                        var l = data.length-1; 
                        var s2 = data[l]; 
                        var k2 = (s2.charCodeAt(s2.length-1) == undefined) ? 0 :  

s2.charCodeAt(s2.length-1); 
                        if (k>=48 && k<=57) { 
                                //trace("     "); 
                                if (k2 == 46 || (k2>=48 && k2<=57)) { 
                                        //trace("      ."); 
                                        data[l] += s1; 
                                } else if (s2 == "--") { 
                                        //trace("     "); 
                                        data[l] = "-"+s1; 
                                } else if (s2 == ")") { 
                                        //trace("   )"); 
                                        data.push("*"); 
                                        data.push(s1); 
                                } else { 
                                        //trace("      +-*/%^ ("); 
                                        data.push(s1); 
                                } 
                        } else if (k == 46) { 
                                //trace("   ."); 
                                if (k2>=48 && k2<=57) { 
                                        //trace("     "); 
                                        if (s2.indexOf(".") == -1) { 
                                                //         
                                                data[l] += s1; 
                                        } 
                                } else if (s2 == "--") { 
                                        //trace("     "); 
                                        data[l] = "-0."; 
                                } else if (s2 == ")") { 
                                        //trace("   )"); 
                                        data.push("*"); 
                                        data.push("0."); 
                                } else if (k2 != 46) { 
                                        //trace("      +-*/%^ ("); 
                                        data.push("0."); 
                                } 
                        } else if (k == 43 || k == 45) { 
                                //trace("   +-"); 
                                if (k2 == 41 || (k2>=48 && k2<=57)) { 
                                        //trace("      )"); 
                                        data.push(s1); 
                                } else if (k2 == 46) { 
                                        //trace("   ."); 
                                        data[l] = data[l].slice(0, -1); 
                                        data.push(s1); 
                                } else if (k == 45) { 
                                        //trace("   -"); 
                                        if (s2 == "--") { 
                                                //trace("     "); 
                                                data.pop(); 
                                        } else if (k2 == 45) { 
                                                //trace("   -"); 
                                                data[l] = "+"; 
                                        } else if (k2 == 43) { 
                                                //trace("   +"); 
                                                data[l] = "-"; 
                                        } else { 
                                                //trace("      +-*/%^ ("); 
                                                data.push("--"); 
                                        } 
                                } 
                        } else if (k == 37 || k == 42 || k == 47 || k == 94) { 
                                //trace("   */%^"); 
                                if (k2 == 41 || (k2>=48 && k2<=57)) { 
                                        //trace("      )"); 
                                        data.push(s1); 
                                } else if (k2 == 46) { 
                                        //trace("   ."); 
                                        data[l] = data[l].slice(0, -1); 
                                        data.push(s1); 
                                } else if (s2 == "--") { 
                                        //trace("     "); 
                                        data[l] = "-1"; 
                                        data.push(s1); 
                                } else if (k2 == 45 || k2 == 43) { 
                                        //trace("   +-"); 
                                        data.push("1"); 
                                        data.push(s1); 
                                } else if (s2 != undefined && k2 != 40) { 
                                        //trace("   */%^"); 
                                        data[l] = s1; 
                                } 
                        } else if (s1 == "(") { 
                                //trace("   ("); 
                                backets.push("("); 
                                if (k2 == 41 || (k2>=48 && k2<=57)) { 
                                        //trace("      )"); 
                                        data.push("*"); 
                                        data.push("("); 
                                } else if (k2 == 46) { 
                                        //trace("   ."); 
                                        data[l] = data[l].slice(0, -1); 
                                        data.push("*"); 
                                        data.push("("); 
                                } else if (s2 == "--") { 
                                        //trace("     "); 
                                        data[l] = "-1"; 
                                        data.push("*"); 
                                        data.push("("); 
                                } else { 
                                        //trace("      +-*/%^ ("); 
                                        data.push("("); 
                                } 
                        } else if (s1 == ")") { 
                                //trace("   )"); 
                                if (s2 != undefined) { 
                                        if (backets[backets.length-1] == "(") { 
                                                backets.pop(); 
                                        } else { 
                                                backets.push(")"); 
                                        } 
                                } 
                                if (k2 == 41 || (k2>=48 && k2<=57)) { 
                                        //trace("      )"); 
                                        data.push(")"); 
                                } else if (s2 == "--") { 
                                        //trace("     "); 
                                        data[l] = "-1"; 
                                        data.push(")"); 
                                } else if (k2 == 46) { 
                                        //trace("   ."); 
                                        data[l] = data[l].slice(0, -1); 
                                        data.push(")"); 
                                } else if (k2 == 40) { 
                                        //trace("   ("); 
                                        data.pop(); 
                                } else if (s2 != undefined) { 
                                        //trace("   +-*/%^"); 
                                        data[l] = ")"; 
                                } 
                        } 
                        n++; 
                        s1 = s.charAt(n); 
                } 
                //          
                while (data[data.length-1] == "(") { 
                        data.pop(); 
                        backets.pop(); 
                } 
                var m = data[data.length-1]; 
                if (m == "+" || m == "-" || m == "*" || m == "/" || m == "%" || m == "^") { 
                        data.pop(); 
                } else if (m == "--") { 
                        data.pop(); 
                        data.pop(); 
                } else if (m.substr(-1) == ".") { 
                        data[data.length-1] = m.slice(0, -1); 
                } 
                //        
                var bs = backets.join(""); 
                var n1 = bs.split("(").length; 
                var n2 = bs.split(")").length; 
                if (n1 != 0) { 
                        n1--; 
                } 
                if (n2 != 0) { 
                        n2--; 
                } 
                while (n1--) { 
                        data.push(")"); 
                } 
                while (n2--) { 
                        data.splice(0, 0, "("); 
                } 
                //  "(  )"     
                var i = 1; 
                //  、      ")" 
                while (i++<data.length) { 
                        if (data == ")") { 
                                if (data[i-2] == "(") { 
                                        data.splice(i, 1); 
                                        data.splice(i-2, 1); 
                                        i -= 2; 
                                } 
                        } 
                } 
                return data; 
        } 
        public static function calculate(s):Number { 
                //     
                var data:Array = []; 
                //        
                if (s instanceof Array) { 
                        data = s; 
                } else if (typeof (s) == "string") { 
                        data = format(s); 
                } 
                var m:Array = []; 
                //       
                var num:String = "0"; 
                var l = data.length; 
                var sign:String = "+"; 
                var n:Number = 0; 
                var i = 0; 
                while (i<l) { 
                        if (data == "(") { 
                                m.push([num, sign, n, false]); 
                                if (data[i+1] == "(") { 
                                        i++; 
                                        num = "0"; 
                                        sign = "+"; 
                                        n = 0; 
                                } else { 
                                        num = data[i+1]; 
                                        sign = data[i+2]; 
                          ,              n = getPriority(sign); 
                                        i += 3; 
                                } 
                        } else { 
                                var sign2 = data[i+1]; 
                                if (sign2 == ")") { 
                                        num = evals(num, sign, data); 
                                        while (m[m.length-1][3]) { 
                                                var arr = m.pop(); 
                                                num = evals(arr[0], arr[1], num); 
                                        } 
                                        m[m.length-1][3] = true; 
                                        while (data[i+2] == ")") { 
                                                while (m[m.length-1][3]) { 
                                                        var arr = m.pop(); 
                                                        num = evals(arr[0], arr[1], num); 
                                                } 
                                                m[m.length-1][3] = true; 
                                                i++; 
                                        } 
                                        sign = data[i+2]; 
                                        n = getPriority(sign); 
                                        while (m[m.length-1][2]>=n && m[m.length-1][3]) { 
                                                var arr = m.pop(); 
                                                num = evals(arr[0], arr[1], num); 
                                        } 
                                        i += 3; 
                                        if (i>=l) { 
                                                for (var j in m) { 
                                                        num = evals(m[j][0], m[j][1], num); 
                                                } 
                                        } 
                                } else { 
                                        var n2 = getPriority(sign2); 
                                        if (n>=n2) { 
                                                num = evals(num, sign, data); 
                                                while (m[m.length-1][2]>=n2 && m[m.length- 

1][3]) { 
                                                        var arr = m.pop(); 
                                                        num = evals(arr[0], arr[1], num); 
                                                } 
                                        } else { 
                                                m.push([num, sign, n, true]); 
                                                num = data; 
                                        } 
                                        sign = sign2; 
                                        n = n2; 
                                        i += 2; 
                                } 
                        } 
                } 
                return Number(num); 
        } 
        private static function getPriority(s:String):Number { 
                //     
                if (s == "+" || s == "-") { 
                        return 1; 
                } else if (s == "*" || s == "/" || s == "%") { 
                        return 2; 
                } else if (s == "^") { 
                        return 3; 
                } else { 
                        return 0; 
                } 
        } 
        private static function evals(n1:String, s:String, n2:String):String { 
                //     
                switch (s) { 
                case "+" : 
                        return String(Number(n1)+Number(n2)); 
                case "-" : 
                        return String(Number(n1)-Number(n2)); 
                case "*" : 
                        return String(Number(n1)*Number(n2)); 
                case "/" : 
                        return String(Number(n1)/Number(n2)); 
                case "%" : 
                        return String(Number(n1)%Number(n2)); 
                case "^" : 
                        return String(Math.pow(Number(n1), Number(n2))); 
                } 
        } 
}