-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathparsemath.min.js
1 lines (1 loc) · 4.58 KB
/
parsemath.min.js
1
class Stack{constructor(){this.top=-1,this.bottom=0,this.arr=[]}isEmpty(){return -1===this.top}push(t){this.arr.push(t),this.top++}pop(t=null){if(this.isEmpty())return null;if(this.top--,null===t)return this.arr.pop();{let r=this.arr[t];return this.arr.splice(t,1),r}}peek(t=null){return this.isEmpty()?null:null===t?this.arr[this.top]:this.arr[t]}replace(t,r){this.arr[t]=r}}const precedences={"^":0,"*":1,"/":1,"+":2,"-":2},brackets={"(":1,")":-1,"[":1,"]":-1},isOperator=t=>t in precedences,isInteger=t=>/^\d+$/.test(t),isLetter=t=>/[a-zA-Zα-ωΑ-Ω]/.test(t),isBracket=t=>t in brackets?[!0,brackets[t]]:[!1,0],MAXIMUM_PRECEDENCE=3,CONSTANTS={e:Math.E,π:Math.PI};let VARIABLES=CONSTANTS;const OPERATORS={"^":(t,r)=>t**r,"*":(t,r)=>t*r,"/"(t,r){if(0===r)throw Error("Division by zero error");return t/r},"+":(t,r)=>t+r,"-":(t,r)=>t-r,sqrt:(t,r)=>Math.sqrt(t),sin:(t,r,e)=>"rad"===e?Math.sin(t):Math.sin(t*Math.PI/180),cos:(t,r,e)=>"rad"===e?Math.cos(t):Math.cos(t*Math.PI/180),tan:(t,r,e)=>"rad"===e?Math.tan(t):Math.tan(t*Math.PI/180),asin(t,r,e){if(t<-1||t>1)throw Error("Trigonometric error: asin value not in domain");return"rad"===e?Math.asin(t):180*Math.asin(t)/Math.PI},acos(t,r,e){if(t<-1||t>1)throw Error("Trigonometric error: acos value not in domain");return"rad"===e?Math.acos(t):180*Math.acos(t)/Math.PI},atan:(t,r,e)=>"rad"===e?Math.atan(t):180*Math.atan(t)/Math.PI,arcsin:(t,r,e)=>OPERATORS.asin(t,r,e),arccos:(t,r,e)=>OPERATORS.acos(t,r,e),arctan:(t,r,e)=>OPERATORS.atan(t,r,e),abs:(t,r)=>Math.abs(t),ln(t,r){if(t<=0)throw Error("Logarithm error: value not in domain");return Math.log(t)}},performCalculation=(t,r,e=0,n)=>{if(isNaN(t)||isNaN(e))throw Error("Syntax error: performing an operation on a NaN type");return(r=r.toLowerCase())in OPERATORS?OPERATORS[r](t,e,n):null},containsFinalString=t=>{let r=t.charAt(t.length-1);if(!isLetter(r))return!1;if(1===t.length)return r;{let e=r,n=!0,a=t.length-2;for(;n;)if(isLetter(t.charAt(a))){if(e=t.charAt(a)+e,t.length-1===a)break;a--}else n=!1;return e}},letterIsPartOfFunction=(t,r)=>{let e=r,n=!0,a=!1,s=t.charAt(r);for(;n&&r<t.length-1;)if(r+=1,isLetter(t.charAt(r)))s+=t.charAt(r);else{if(n=!1,!isBracket(t.charAt(r))[0])return!1;a=!0}let i=!0;for(a=!1,r=e;i&&r>0;)r-=1,isLetter(t.charAt(r))?s=t.charAt(r)+s:i=!1;return s.toLowerCase() in OPERATORS},removeInnerBrackets=(t,r,e,n)=>{let a=t.split(""),s=0,i=-1,o=-1,l=-1;if(a.forEach((t,r)=>{let e=isBracket(t);if(e[0]){let n=s+e[1];n>i&&-1===l?(i=n,o=r):s===i&&n<i&&-1===l&&(l=r),s=n}}),-1===l)throw Error("Bracket error: imbalanced brackets");let c=t.substring(o+1,l);if(""===c)throw Error("Bracket error: no expression within brackets");let h=ParseMath(c,r,e,n),_=t.substring(0,o),p=t.substring(l+1,t.length);if(isInteger(_.charAt(_.length-1))||1!==brackets[_.charAt(_.length-1)]&&_.charAt(_.length-1)&&!letterIsPartOfFunction(_,_.length-1)&&!isOperator(_.charAt(_.length-1)))_+="*";else if(containsFinalString(_)){let u=containsFinalString(_);_=_.substring(0,_.length-u.length),h=performCalculation(h,u,null,n),(isInteger(_.charAt(_.length-1))||1!==brackets[_.charAt(_.length-1)]&&_.charAt(_.length-1)&&!letterIsPartOfFunction(_,_.length-1)&&!isOperator(_.charAt(_.length-1)))&&(_+="*")}(isInteger(p.charAt(0))||"("===p.charAt(0)||"["===p.charAt(0)||isLetter(p.charAt(0)))&&(p="*"+p);let A=_+h+p;return A},containsBracket=t=>/[\(\)\[\]]/g.test(t);function ParseMath(t,r=!0,e=null,n="rad"){for(t=t.replace(/\s/g,""),r?r&&(VARIABLES=CONSTANTS):VARIABLES={},null!==e&&"object"==typeof e&&Object.keys(e).forEach(t=>{let r=e[t];"string"==typeof r&&(r in VARIABLES)&&(r=VARIABLES[r]),VARIABLES[t]=r});containsBracket(t);)t=removeInnerBrackets(t,r,e,n);let a=t.split(""),s=new Stack,i=new Stack,o=new Stack,l="operator";for(a.forEach((r,e)=>{if(" "!=r){if(isOperator(r))"operator"===l&&"-"===r?(o.push(r),l="number"):(i.push(r),l="operator");else if(isInteger(r)){if(e!==t.length-1&&(isInteger(t.charAt(e+1))||"."===t.charAt(e+1)))o.push(r);else if(0!==e&&(isInteger(t.charAt(e-1))||"."===t.charAt(e-1)||"-"===t.charAt(e-1)&&"number"===l)){o.push(r);let n="";for(;!o.isEmpty();)n+=o.pop(0);s.push(n)}else s.push(r);l="number"}else if("."===r)o.push(".");else if((r in VARIABLES)&&!letterIsPartOfFunction(t,e))0!==e&&"number"===l&&i.push("*"),r=VARIABLES[r].toString(),s.push(r),l="number";else throw Error("Syntax error: Variable '"+r+"' not defined")}});0!==s.top;){let c="+",h=3,_=-1,p=[-1,-1];for(let u=0;u<=i.top;u++){let A=i.peek(u),f=precedences[A];f<h&&(c=A,h=f,_=u,p=[u,u+1])}let g=performCalculation(parseFloat(s.peek(p[0])),c,parseFloat(s.peek(p[1])));s.pop(p[1]),s.replace(p[0],g.toString()),i.pop(_)}let $=Number(s.pop());return $}module.exports=ParseMath;