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)));
}
}
}