graphic-canvas-example-function-parse.js / js
********************************************************\ * Created by Benjamin Joffe * * This is a function that takes a string such as: * * x^sin(x) * * And will turn it into a JavaScript evaluatable string: * * Math.pow(x, Math.sin(x)); * * * \**********************************************************
Math.csc = function(x){ return 1 / Math.sin(x); }; Math.sec = function(x){ return 1 / Math.cos(x); }; Math.cot = function(x){ return 1 / Math.tan(x); }; Math.acsc = function(x){ return Math.asin(1/x); }; Math.asec = function(x){ return Math.acos(1/x); }; Math.acot = function(x){ return Math.atan(1/x); }; Math.sinh = function(x){ x = Math.exp(x); return (x - 1/x) / 2; }; Math.cosh = function(x){ x = Math.exp(x); return (x + 1/x) / 2; }; Math.tanh = function(x){ x = Math.exp(x); return (x*x - 1) / (x*x + 1); }; Math.asinh = function(x){ return Math.log(x + Math.sqrt(1+x*x)); }; Math.acosh = function(x){ return 2 * Math.log( Math.sqrt((x+1)/2) + Math.sqrt((x-1)/2) ); }; Math.atanh = function(x){ return (Math.log(1+x) - Math.log(1-x)) / 2; }; Math.csch = function(x){ x = Math.exp(x); return 2 / (x - 1/x); }; Math.sech = function(x){ x = Math.exp(x); return 2 / (x + 1/x); }; Math.coth = function(x){ x = Math.exp(x); return (x*x + 1) / (x*x - 1); }; Math.acsch = function(x){ x = 1/x; return Math.log(x + Math.sqrt(1+x*x)); }; Math.asech = function(x){ x = 1/x; return 2 * Math.log( Math.sqrt((x+1)/2) + Math.sqrt((x-1)/2) ); }; Math.acoth = function(x){ x = 1/x; return (Math.log(1+x) - Math.log(1-x)) / 2; }; // Enough Trig!!! Math.log10 = function(x){ return Math.log(x)/2.302585092994046; }; Math.sqr = function(x){ return x*x; }; Math.sign = function(x){ return x > 0 ? 1 : x < 0 ? -1 : x==0 ? 0 : undefined; }; function parseMath(a){ a = a.split(' ').join('').toLowerCase().split(''); if (a.length==0) return [false, 'Error 000. Nothing entered']; var c_alpha = "abcdefghijklmnopqrstuvwxyz"; var c_numero = "0.123456789"; var c_opera = ",+-*/%^"; var c_all = c_alpha + c_numero + c_opera + '()'; var i,j,k; var level=0; var word; var decimal; var level2; var mode = 'ready'; i=0, j; var functionList = '\ -sin-cos-tan-\ -asin-acos-atan-\ -csc-sec-cot-\ -acsc-asec-acot-\ -sinh-cosh-tanh-\ -asinh-acosh-atanh-\ -csch-sech-coth-\ -acsch-asech-acoth-\ '; functionList += '-sqrt-exp-abs-sign-sqr-log-'; while (i<a.length) switch (mode) { case 'end' : if (a[i]=='+' || a[i]=='-' || a[i]=='*' || a[i]=='/') { i++; mode = 'ready'; break; } if (a[i]=='^') { mode = 'power'; break; } if (a[i]=='(') { a.splice(i,0,'*'), i++; mode = 'ready'; break; } if (a[i]==')') { if (level<1) return [false, '<A href="http://Error 002. Grouping symbol error']; level--; i++; break; } if (c_numero.indexOf(a[i])>=0) { a.splice(i,0,'*'), i++; mode = 'numero'; break; } if (c_alpha.indexOf(a[i])>=0) { a.splice(i,0,'*'), i++; mode = 'alpha'; break; } return [false, 'Error 001. Invalid character after a term']; case 'ready' : for (; i<a.length; i++) { if (a[i]=='-') { if (i>0) { if (a[i-1]=='-') a.splice(i-1,2,'+'), i--; else if (a[i-1]=='+') a.splice(i-1,1), i--; } continue; } if (a[i]=='+') { if (i>0 && (a[i-1]=='-' || a[i-1]=='+')) a.splice(i,1), i--; continue; } if (c_numero.indexOf(a[i])>=0) { mode='numero'; break; } if (c_alpha.indexOf(a[i])>=0) { mode='alpha'; break; } if (a[i]=='(') { level++; continue; } if (a[i]==')') return [false, 'Error 002. Grouping symbol error']; return [false, 'Syntax Error (mode: ready)']; } break; case 'numero' : decimal = a[i++]=='.'; for (; i<a.length; i++) { if (c_numero.indexOf(a[i])>=0) { if (a[i]=='.') { if (decimal) return [false, 'Error 003. Decimal place error']; decimal=true; } continue; } mode = 'end'; break; } break; case 'alpha' : word = a[i++]; for (; i<a.length; i++) { if (c_alpha.indexOf(a[i])>=0) word+=a[i]; else break; } if (i<a.length && c_numero.indexOf(a[i])>=0) return [false, 'Error 004. Numeral illegally following a pronumeral']; mode = 'end'; if (word=='pi') a.splice(i-2, 2, '3.141592653589793'), i-=1; else if (word=='e') a[i-1]='2.718281828459045'; else if (word=='phi') a.splice(i-3, 3, '1.618033988749895'), i-=2; else if (word=='rand') a.splice(i-4, 4, '(','Math.random(',')',')'); else if (functionList.indexOf('-'+word+'-')>=0) { if (i<a.length && a[i]=='(') { a.splice(i-word.length, word.length+1, 'Math.'+word+'('); i-=word.length-1; level++; mode = 'ready'; } else return [false, 'Error 005. Function: <B>'+word+'</B> is being treated as a constant']; } else if (word!='x' && word!='y') { return [false, 'Error 006. Unknown variable: <B>'+(word.length<13 ? word : word.substr(0,13)+'...')+'</B>']; } break; case 'power' : a[i]=','; // look left... level2=0; for (j=i-1; j>=0; j--) { if (a[j]==')') level2++; else if (level2==0 && (a[j].indexOf('(')>=0 || a[j]==',' || a[j]=='+' || a[j]=='-' || a[j]=='*' || a[j]=='/')) { break; } else if (a[j].indexOf('(')>=0) level2--; } a.splice(j+1, 0, 'Math.pow('), i++; // look right... decimal = false; // decimal means not a + or a - level2 = 0; for (j=i+1; j<a.length; j++) { if (a[j]!='+' && a[j]!='-') decimal=true; if (a[j]=='(') level2++; else if (decimal && level2==0 && (a[j]==')' || a[j]=='+' || a[j]=='-' || a[j]=='*' || a[j]=='/')) { break; } else if (a[j]==')') level2--; } a.splice(j, 0, ')'); // no need to increment i, this is after i, level++; i++ mode = 'ready'; break; default : i++; } if (level!=0) return [false, 'Error 008. Grouping symbol error']; if (mode=='start' || mode=='ready') return [false, 'Error 007. Invalid final character']; return [true, a.join('')]; }
(C) Æliens 20/2/2008
You may not copy or print any of this material without explicit permission of the author or the publisher. In case of other copyright issues, contact the author.