topical media & game development

talk show tell print

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.