mirror of
https://github.com/Karaka-Management/jsOMS.git
synced 2026-02-13 16:08:41 +00:00
Implement shunting yard + evaluation
This commit is contained in:
parent
1ccf075366
commit
fb5eb8e463
|
|
@ -1,137 +1,104 @@
|
||||||
//+ Jonas Raoni Soares Silva
|
/**
|
||||||
//@ http://jsfromhell.com/classes/math-processor [rev. #1]
|
* Standard library
|
||||||
|
*
|
||||||
|
* This library provides useful functionalities for the DOM and other manipulations.
|
||||||
|
*
|
||||||
|
* @copyright Dennis Eichhorn
|
||||||
|
* @license OMS License 1.0
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
(function (jsOMS) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
var MathProcessor = function () {
|
jsOMS.mathEvaluate = function(equation)
|
||||||
var o = this;
|
{
|
||||||
o.o = {
|
const stack = [];
|
||||||
"+": function (a, b) {
|
const postfix = jsOMS.shuntingYard(equation);
|
||||||
return +a + b;
|
const length = postfix.length;
|
||||||
},
|
|
||||||
"-": function (a, b) {
|
for(let i = 0; i < length; i++) {
|
||||||
return a - b;
|
if (!isNaN(parseFloat(postfix[i])) && isFinite(postfix[i])) {
|
||||||
},
|
stack.push(postfix[i]);
|
||||||
"%": function (a, b) {
|
} else {
|
||||||
return a % b;
|
let a = jsOMS.parseValue(stack.pop());
|
||||||
},
|
let b = jsOMS.parseValue(stack.pop());
|
||||||
"/": function (a, b) {
|
|
||||||
return a / b;
|
if(postfix[i] === '+') {
|
||||||
},
|
stack.push(a + b);
|
||||||
"*": function (a, b) {
|
} else if (postfix[i] === '-') {
|
||||||
return a * b;
|
stack.push(b - a);
|
||||||
},
|
} else if (postfix[i] === '*') {
|
||||||
"^": function (a, b) {
|
stack.push(a * b);
|
||||||
return Math.pow(a, b);
|
} else if (postfix[i] === '/') {
|
||||||
},
|
stack.push(b / a);
|
||||||
"~": function (a, b) {
|
} else if (postfix[i] === '^') {
|
||||||
return Math.sqrt(a, b);
|
stack.push(Math.pow(b, a));
|
||||||
}
|
|
||||||
};
|
|
||||||
o.s = {"^": 3, "~": 3, "*": 2, "/": 2, "%": 1, "+": 0, "-": 0};
|
|
||||||
o.u = {"+": 1, "-": -1}, o.p = {"(": 1, ")": -1};
|
|
||||||
};
|
|
||||||
with ({p: MathProcessor.prototype}) {
|
|
||||||
p.methods = {
|
|
||||||
div: function (a, b) {
|
|
||||||
return parseInt(a / b);
|
|
||||||
},
|
|
||||||
fra: function (a) {
|
|
||||||
return a - parseInt(a);
|
|
||||||
},
|
|
||||||
sum: function (n1, n2, n3, n) {
|
|
||||||
for (var r = 0, a, l = (a = arguments).length; l; r += a[--l]) {
|
|
||||||
;
|
|
||||||
}
|
|
||||||
return r;
|
|
||||||
},
|
|
||||||
medium: function (n1, n2, n3, n) {
|
|
||||||
for (var r = 0, a, l = (a = arguments).length; l; r += a[--l]) {
|
|
||||||
;
|
|
||||||
}
|
|
||||||
return r / a.length;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
p.parse = function (e) {
|
|
||||||
for (var n, x, _ = this, o = [], s = [x = _.RPN(e.replace(/ /g, "").split(""))]; s.length;) {
|
|
||||||
for ((n = s[s.length - 1], --s.length); n[2]; o[o.length] = n, s[s.length] = n[3], n = n[2]) {
|
|
||||||
;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (; (n = o.pop()) != undefined; n[0] = _.o[n[0]](isNaN(n[2][0]) ? _.f(n[2][0]) : n[2][0], isNaN(n[3][0]) ? _.f(n[3][0]) : n[3][0])) {
|
|
||||||
;
|
|
||||||
}
|
|
||||||
return +x[0];
|
|
||||||
};
|
|
||||||
p.RPN = function (e) {
|
|
||||||
var x, r, _ = this, c = r = [, , , 0];
|
|
||||||
if (e[0] in _.u || !e.unshift("+")) {
|
|
||||||
for (; e[1] in _.u; e[0] = _.u[e.shift()] * _.u[e[0]] + 1 ? "+" : "-") {
|
|
||||||
;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
(c[3] = [_.u[e.shift()], c, , 0])[1][0] = "*", (r = [, , c, 0])[2][1] = r;
|
|
||||||
(c[2] = _.v(e))[1] = c;
|
|
||||||
(!e.length && (r = c)) || (e[0] in _.s && ((c = r)[0] = e.shift(), !e.length && _.error()));
|
|
||||||
while (e.length) {
|
|
||||||
if (e[0] in _.u) {
|
|
||||||
for (; e[1] in _.u; e[0] = _.u[e.shift()] * _.u[e[0]] + 1 ? "+" : "-") {
|
|
||||||
;
|
|
||||||
}
|
|
||||||
(c = c[3] = ["*", c, , 0])[2] = [-1, c, , 0];
|
|
||||||
}
|
|
||||||
(c[3] = _.v(e))[1] = c;
|
|
||||||
e[0] in _.s && (c = _.s[e[0]] > _.s[c[0]] ?
|
|
||||||
((c[3] = (x = c[3], c[2]))[1][2] = [e.shift(), c, x, 0])[2][1] = c[2]
|
|
||||||
: r == c ? (r = [e.shift(), , c, 0])[2][1] = r
|
|
||||||
: ((r[2] = (x = r[2], [e.shift(), r, , 0]))[2] = x)[1] = r[2]);
|
|
||||||
}
|
|
||||||
return r;
|
|
||||||
};
|
|
||||||
p.v = function (e) {
|
|
||||||
var i, j, l, _ = this;
|
|
||||||
if ("0123456789.".indexOf(e[0]) + 1) {
|
|
||||||
for (i = -1, l = e.length; ++i < l && "0123456789.".indexOf(e[i]) + 1;) {
|
|
||||||
;
|
|
||||||
}
|
|
||||||
return [+e.splice(0, i).join(""), , , 0];
|
|
||||||
}
|
|
||||||
else if (e[0] == "(") {
|
|
||||||
for (i = 0, l = e.length, j = 1; ++i < l && (e[i] in _.p && (j += _.p[e[i]]), j);) {
|
|
||||||
;
|
|
||||||
}
|
|
||||||
return _.RPN(l = e.splice(0, i), l.shift(), !j && e.shift());
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (((j = e[0].toLowerCase()) >= "a" && j <= "z") || j == "_") {
|
|
||||||
for (i = 0; ((j = e[++i].toLowerCase()) >= "a" && j <= "z") || j == "_" || (j >= 0 && j <= 9);) {
|
|
||||||
;
|
|
||||||
}
|
|
||||||
if (j == "(") {
|
|
||||||
for (var l = e.length, j = 1; ++i < l && (e[i] in _.p && (j += _.p[e[i]]), j);) {
|
|
||||||
;
|
|
||||||
}
|
|
||||||
return [e.splice(0, i + 1).join(""), , , 0];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_.error();
|
|
||||||
|
return stack.pop();
|
||||||
};
|
};
|
||||||
p.f = function (e) {
|
|
||||||
var n, i = 0, _ = this;
|
jsOMS.parseValue = function(value)
|
||||||
if (((e = e.split(""))[i] >= "a" && e[i] <= "z") || e[i] == "_") {
|
{
|
||||||
while ((e[++i] >= "a" && e[i] <= "z") || e[i] == "_" || (e[i] >= 0 && e[i] <= 9)) {
|
return value.indexOf('.') === -1 ? parseInt(value) : parseFloat(value);
|
||||||
;
|
}
|
||||||
}
|
|
||||||
if (e[i] == "(") {
|
jsOMS.shuntingYard = function(equation)
|
||||||
!_.methods[n = e.splice(0, i).join("")] && _.error("Function \"" + n + "\" not found"), e.shift();
|
{
|
||||||
for (var a = [], i = -1, j = 1; e[++i] && (e[i] in _.p && (j += _.p[e[i]]), j);) {
|
const stack = [];
|
||||||
j == 1 && e[i] == "," && (a.push(_.parse(e.splice(0, i).join(""))), e.shift(), i = -1);
|
const operators = {
|
||||||
|
'^': {precedence: 4, order: 1},
|
||||||
|
'/': {precedence: 3, order: -1},
|
||||||
|
'*': {precedence: 3, order: -1},
|
||||||
|
'+': {precedence: 3, order: -1},
|
||||||
|
'-': {precedence: 3, order: -1},
|
||||||
|
};
|
||||||
|
let output = [];
|
||||||
|
|
||||||
|
equation = equation.replace(/\s+/g, '');
|
||||||
|
equation = equation.split(/([\+\-\*\/\^\(\)])/).filter(function (n) { return n !== '' });
|
||||||
|
|
||||||
|
let length = equation.length;
|
||||||
|
for(let i = 0; i < length; i++) {
|
||||||
|
let token = equation[i];
|
||||||
|
|
||||||
|
if (!isNaN(parseFloat(token)) && isFinite(token)) {
|
||||||
|
output.push(token);
|
||||||
|
} else if('^*/+-'.indexOf(token) !== -1) {
|
||||||
|
let o1 = token;
|
||||||
|
let o2 = stack[stack.length - 1];
|
||||||
|
|
||||||
|
while ('^*/+-'.indexOf(o2) !== -1 &&
|
||||||
|
(
|
||||||
|
(operators[o1].order === -1 && operators[o1].precedence <= operators[o2].precedence)
|
||||||
|
|| (operators[o1].order === 1 && operators[o1].precedence < operators[o2].precedence)
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
output.push(stack.pop());
|
||||||
|
o2 = stack[stack.length - 1];
|
||||||
}
|
}
|
||||||
a.push(_.parse(e.splice(0, i).join(""))), !j && e.shift();
|
|
||||||
|
stack.push(o1);
|
||||||
|
} else if(token === '(') {
|
||||||
|
stack.push(token);
|
||||||
|
} else if (token === ')') {
|
||||||
|
while(stack[stack.length - 1] !== '(') {
|
||||||
|
output.push(stack.pop());
|
||||||
|
}
|
||||||
|
|
||||||
|
stack.pop();
|
||||||
}
|
}
|
||||||
return _.methods[n].apply(_, a);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
while(stack.length > 0) {
|
||||||
|
output.push(stack.pop());
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
};
|
};
|
||||||
p.error = function (s) {
|
|
||||||
//throw new Error("MathProcessor: " + (s || "Wrong expression"));
|
|
||||||
};
|
}(window.jsOMS = window.jsOMS || {}));
|
||||||
}
|
|
||||||
Loading…
Reference in New Issue
Block a user