Author: Integer
Miscellaneous
It issuies visual alerts to the screen
0 Views
0 Downloads
0 Favorites
sToken
#property copyright     "Integer"
#property link          "https://login.mql5.com/ru/users/Integer"
#property description   " "
#property description   "      http://dmffx.com"
#property description   " "
#property description   "      mailto:for-good-letters@yandex.ru"
#property script_show_inputs

//--- input parameters
input string Expression1="a+b+c+d";
input string Expression2="e[0]+e[1]+f[0]+f[1]";
input string Expression3="((pow(5,2)+pow(10,2)+25)/30*2)*2/4-2*cos(0)";
input string Expression4="1<2 && 3<4";

/*   
   Supported functions: abs, arccos, arcsin, arctan, ceil, cos, exp, floor, log, log10, max, min, mod, pow, rand, round, sin, sqrt, tan
   Operations: /, %, *, +, -, >, <, >=, <=, ==, !=, &&, ||
*/
//+------------------------------------------------------------------+
//| cTokenBase class                                                 |
//+------------------------------------------------------------------+
class cTokenBase
  {
protected:
   string            UserVariables;
   string            UserArrays;
   void UsersVariables()
     {
      UserVariables="a;b;c;d"; // list of variables used
      UserArrays="e;f";        // list of arrays used
     }
   string UserFunc(string FuncName)
     {
      if(FuncName=="a")return(a());
      if(FuncName=="b")return(b());
      if(FuncName=="c")return(c());
      if(FuncName=="d")return(d());
      Alert("The function for "+FuncName+" variable is not defined");
      return("0");
     }
   string a()
     {
      return("1");
     }
   string b()
     {
      return("2");
     }
   string c()
     {
      return("3");
     }
   string d()
     {
      return("4");
     }
   //===    
   string UserArray(string ArrName,int aIndex)
     {
      if(ArrName=="e")return(e(aIndex));
      if(ArrName=="f")return(f(aIndex));
      Alert("The function for "+ArrName+" array is not defined");
      return("0");
     }
   string e(int Index)
     {
      string v[]={"1","2","3","4","5","6","7","8","9"};
      return(v[Index]);
     }
   string f(int Index)
     {
      string v[]={"10","20","30","40","50","60","70","80","90"};
      return(v[Index]);
     }
  };
//+------------------------------------------------------------------+
//| cToken class                                                     |
//+------------------------------------------------------------------+
class cToken: public cTokenBase
  {
protected:
   string            a[];
   string            b[];
   string            c[];
   string            all[];
   string            r[];
   string            e;
   string            uv[];
   int               uri[];
   int               uvi[];
   string            fn[];
   string            an[];
   int               ai[];
   string            av[];
   int               uari[];
   int               uavi[];
   string            un[];
   string            uan[];
   string            t[];
   void Prepare()
     {
      // Conversion of string with experession into the array with verification of functions
      StringTrimLeft(e);
      StringTrimRight(e);
      if(e=="")
        {
         e="0";
        }
      // 1. Prepare array
      AddArrays(all,a);
      AddArrays(all,b);
      AddArrays(all,c);
      // 2. Sort array by length (decreasing order)
      SortByLen(all);
      // 3. Convert expression string to lower case
      StringToLower(e);
      // 4. Delete all spaces
      e=DelSpaces(e);
      // 5. Split expression to array
      SplitExprToArray(e,all,r);
      // 6. Remove unused functions
      RemUnUsed(a,r);
      // 7. Remove unused variables
      RemUnUsed(un,r);
      ArrayResize(uv,ArraySize(un));
      // 8. Create lists for replace of the user's variables
      CreateReplaceLists(r,un,uri,uvi);
      // 9. Create lists for arrays
      CreateElementsList(r,uan,fn,an,ai,av);
      ArrayResize(av,ArraySize(fn));
      // 10. create replace lists for arrays (correspondence: index in the expression array - index in the element list)
      CreateReplaceLists(r,fn,uari,uavi);
      // 11. prepare array
      ArrayResize(t,ArraySize(r));
     }
   void AddArrays(string  &aAr1[],string  &aAr2[])
     {
      int from=ArraySize(aAr1);
      int cnt=ArraySize(aAr2);
      ArrayResize(aAr1,from+cnt);
      ArrayCopy(aAr1,aAr2,from,0,cnt);
     }
   void SortByLen(string  &aAr[])
     {
      for(int i=ArraySize(aAr)-1;i>0;i--)
        {
         for(int j=0;j<i;j++)
           {
            if(StringLen(aAr[j])<StringLen(aAr[j+1]))
              {
               string tmp=aAr[j];
               aAr[j]=aAr[j+1];
               aAr[j+1]=tmp;
              }
           }
        }
     }
   string DelSpaces(string aStr)
     {
      string rs="";
      for(int i=0;i<StringLen(aStr);i++)
        {
         string chr=StringSubstr(aStr,i,1);
         if(chr!=" ")rs=rs+chr;
        }
      return(rs);
     }
   void SplitExprToArray(string aExp,string  &aSplitBy[],string  &aAr[])
     {
      string t=aExp;
      string p="";
      ArrayResize(aAr,0);
      while(t!="")
        {
         bool exist=false;
         for(int j=0;j<ArraySize(aSplitBy);j++)
           {
            if(StringSubstr(t,0,StringLen(aSplitBy[j]))==aSplitBy[j])
              {
               if(p!="")
                 {
                  ArrayResize(aAr,ArraySize(aAr)+1);
                  aAr[ArraySize(aAr)-1]=p;
                 }
               ArrayResize(aAr,ArraySize(aAr)+1);
               aAr[ArraySize(aAr)-1]=aSplitBy[j];
               p="";
               t=StringSubstr(t,StringLen(aSplitBy[j]),StringLen(t)-StringLen(aSplitBy[j]));
               exist=true;
               break;
              }
           }
         if(!exist)
           {
            p=p+StringSubstr(t,0,1);
            t=StringSubstr(t,1,StringLen(t)-1);
           }
        }
      if(p!="")
        {
         ArrayResize(aAr,ArraySize(aAr)+1);
         aAr[ArraySize(aAr)-1]=p;
        }
     }
   void RemUnUsed(string  &aAr[],string  &aEAr[])
     {
      string tAr[];
      ArrayResize(tAr,0);
      for(int i=0;i<ArraySize(aAr);i++)
        {
         if(ExistInArray(aAr[i],aEAr))
           {
            AddIfNotExist(aAr[i],tAr);
           }
        }
      ArrayResize(aAr,ArraySize(tAr));
      if(ArraySize(tAr)!=0)
        {
         ArrayCopy(aAr,tAr);
        }
     }
   void CreateReplaceLists(string  &aExp[],string  &aNames[],int  &aInExpIndex[],int  &aInNamesIndex[])
     {
      ArrayResize(aInExpIndex,0);
      ArrayResize(aInNamesIndex,0);
      for(int i=0;i<ArraySize(aExp);i++)
        {
         for(int j=0;j<ArraySize(aNames);j++)
           {
            if(aExp[i]==aNames[j])
              {
               AddToArrayI(i,aInExpIndex);
               AddToArrayI(j,aInNamesIndex);
              }
           }
        }
     }
   void CreateElementsList(string  &aExp[],string  &aUserArrays[],string  &aFull[],string  &aName[],int  &aIndex[],string  &aValues[])
     {
      ArrayResize(aFull,0);
      ArrayResize(aName,0);
      ArrayResize(aIndex,0);
      for(int i=0;i<ArraySize(aUserArrays);i++)
        {
         string search=aUserArrays[i]+"[";
         int slen=StringLen(search);
         for(int j=0;j<ArraySize(aExp);j++)
           {
            if(StringSubstr(aExp[j],0,slen)==search)
              {
               int Index=(int)StringToInteger(StringSubstr(r[j],slen,StringLen(r[j])-slen-1));
               if(!ExistInArray(aExp[j],aFull))
                 {
                  AddToArrayS(aExp[j],aFull);
                  AddToArrayS(uan[i],aName);
                  AddToArrayI(Index,aIndex);
                 }
              }
           }
        }
      ArrayResize(aValues,ArraySize(aFull));
     }
   void SolveArguments(string  &aExp[],int aFrom,int aTo,string  &aRes[])
     {
      ArrayResize(aRes,0);
      string ex[];
      int cnt=aTo-aFrom+1;
      ArrayResize(ex,cnt);
      ArrayCopy(ex,aExp,0,aFrom,cnt);
      int strt=0;
      int i;
      for(i=0;i<ArraySize(ex);i++)
        {
         if(ex[i]==",")
           {
            ArrayResize(aRes,ArraySize(aRes)+1);
            aRes[ArraySize(aRes)-1]=SolveSimple(ex,strt,i-1);
            strt=i+1;
           }
        }
      ArrayResize(aRes,ArraySize(aRes)+1);
      aRes[ArraySize(aRes)-1]=SolveSimple(ex,strt,i-1);

     }
   string SolveSimple(string  &aExp[],int aFrom,int aTo)
     {
      string ex[];
      int cnt=aTo-aFrom+1;
      ArrayResize(ex,cnt);
      ArrayCopy(ex,aExp,0,aFrom,cnt);
      int i,j;
      bool exist;
      // %
      exist=true;
      while(exist)
        {
         exist=false;
         for(i=0;i<cnt;i++)
           {
            if(ex[i]=="%")
              {
               ex[i-1]=IntegerToString(StringToInteger(ex[i-1])%StringToInteger(ex[i+1]));
               for(j=i;j<cnt-2;j++)
                 {
                  ex[j]=ex[j+2];
                 }
               cnt--;
               cnt--;
               exist=true;
               break;
              }
           }
        }
      //===
      // /
      exist=true;
      while(exist)
        {
         exist=false;
         for(i=0;i<cnt;i++)
           {
            if(ex[i]=="/")
              {
               if(StringToDouble(ex[i+1])!=0)
                 {
                  ex[i-1]=DoubleToString(StringToDouble(ex[i-1])/StringToDouble(ex[i+1]));
                 }
               else
                 {
                  ex[i-1]=DoubleToString(StringToDouble(ex[i-1])/0.00000001);
                 }
               for(j=i;j<cnt-2;j++)
                 {
                  ex[j]=ex[j+2];
                 }
               cnt--;
               cnt--;
               exist=true;
               break;
              }
           }
        }
      // *
      exist=true;
      while(exist)
        {
         exist=false;
         for(i=0;i<cnt;i++)
           {
            if(ex[i]=="*")
              {
               ex[i-1]=DoubleToString(StringToDouble(ex[i-1])*StringToDouble(ex[i+1]));
               for(j=i;j<cnt-2;j++)
                 {
                  ex[j]=ex[j+2];
                 }
               cnt--;
               cnt--;
               exist=true;
               break;
              }
           }
        }
      // +-
      exist=true;
      while(exist)
        {
         exist=false;
         for(i=0;i<cnt;i++)
           {
            if(ex[i]=="+")
              {
               ex[i-1]=DoubleToString(StringToDouble(ex[i-1])+StringToDouble(ex[i+1]));
               for(j=i;j<cnt-2;j++)
                 {
                  ex[j]=ex[j+2];
                 }
               cnt--;
               cnt--;
               exist=true;
               break;
              }
            if(ex[i]=="-")
              {
               ex[i-1]=DoubleToString(StringToDouble(ex[i-1])-StringToDouble(ex[i+1]));
               for(j=i;j<cnt-2;j++)
                 {
                  ex[j]=ex[j+2];
                 }
               cnt--;
               cnt--;
               exist=true;
               break;
              }
           }
        }
      //===
      // >
      exist=true;
      while(exist)
        {
         exist=false;
         for(i=0;i<cnt;i++)
           {
            if(ex[i]==">")
              {
               ex[i-1]=DoubleToString(StringToDouble(ex[i-1])>StringToDouble(ex[i+1]));
               for(j=i;j<cnt-2;j++)
                 {
                  ex[j]=ex[j+2];
                 }
               cnt--;
               cnt--;
               exist=true;
               break;
              }
           }
        }
      // <
      exist=true;
      while(exist)
        {
         exist=false;
         for(i=0;i<cnt;i++)
           {
            if(ex[i]=="<")
              {
               ex[i-1]=DoubleToString(StringToDouble(ex[i-1])<StringToDouble(ex[i+1]));
               for(j=i;j<cnt-2;j++)
                 {
                  ex[j]=ex[j+2];
                 }
               cnt--;
               cnt--;
               exist=true;
               break;
              }
           }
        }
      // >=
      exist=true;
      while(exist)
        {
         exist=false;
         for(i=0;i<cnt;i++)
           {
            if(ex[i]==">=")
              {
               ex[i-1]=DoubleToString(StringToDouble(ex[i-1])>=StringToDouble(ex[i+1]));
               for(j=i;j<cnt-2;j++)
                 {
                  ex[j]=ex[j+2];
                 }
               cnt--;
               cnt--;
               exist=true;
               break;
              }
           }
        }
      // <=
      exist=true;
      while(exist)
        {
         exist=false;
         for(i=0;i<cnt;i++)
           {
            if(ex[i]=="<=")
              {
               ex[i-1]=DoubleToString(StringToDouble(ex[i-1])<=StringToDouble(ex[i+1]));
               for(j=i;j<cnt-2;j++)
                 {
                  ex[j]=ex[j+2];
                 }
               cnt--;
               cnt--;
               exist=true;
               break;
              }
           }
        }
      // ==
      exist=true;
      while(exist)
        {
         exist=false;
         for(i=0;i<cnt;i++)
           {
            if(ex[i]=="==")
              {
               ex[i-1]=DoubleToString(StringToDouble(ex[i-1])==StringToDouble(ex[i+1]));
               for(j=i;j<cnt-2;j++)
                 {
                  ex[j]=ex[j+2];
                 }
               cnt--;
               cnt--;
               exist=true;
               break;
              }
           }
        }
      // ==
      exist=true;
      while(exist)
        {
         exist=false;
         for(i=0;i<cnt;i++)
           {
            if(ex[i]=="!=")
              {
               ex[i-1]=DoubleToString(StringToDouble(ex[i-1])!=StringToDouble(ex[i+1]));
               for(j=i;j<cnt-2;j++)
                 {
                  ex[j]=ex[j+2];
                 }
               cnt--;
               cnt--;
               exist=true;
               break;
              }
           }
        }
      //===
      // ||
      exist=true;
      while(exist)
        {
         exist=false;
         for(i=0;i<cnt;i++)
           {
            if(ex[i]=="||")
              {
               ex[i-1]=DoubleToString(StringToDouble(ex[i-1]) || StringToDouble(ex[i+1]));
               for(j=i;j<cnt-2;j++)
                 {
                  ex[j]=ex[j+2];
                 }
               cnt--;
               cnt--;
               exist=true;
               break;
              }
           }
        }
      // &&
      exist=true;
      while(exist)
        {
         exist=false;
         for(i=0;i<cnt;i++)
           {
            if(ex[i]=="&&")
              {
               ex[i-1]=DoubleToString(StringToDouble(ex[i-1]) && StringToDouble(ex[i+1]));
               for(j=i;j<cnt-2;j++)
                 {
                  ex[j]=ex[j+2];
                 }
               cnt--;
               cnt--;
               exist=true;
               break;
              }
           }
        }
      return(ex[0]);
     }
   int SolveFunc(string Func,string  &aRes[])
     {
      if(Func=="abs")
        {
         aRes[0]=DoubleToString(MathAbs(StringToDouble(aRes[0])));
         return(1);
        }
      if(Func=="arccos")
        {
         aRes[0]=DoubleToString(MathArccos(StringToDouble(aRes[0])));
         return(1);
        }
      if(Func=="arcsin")
        {
         aRes[0]=DoubleToString(MathArcsin(StringToDouble(aRes[0])));
         return(1);
        }
      if(Func=="arctan")
        {
         aRes[0]=DoubleToString(MathArctan(StringToDouble(aRes[0])));
         return(1);
        }
      if(Func=="ceil")
        {
         aRes[0]=DoubleToString(MathCeil(StringToDouble(aRes[0])));
         return(1);
        }
      if(Func=="cos")
        {
         aRes[0]=DoubleToString(MathCos(StringToDouble(aRes[0])));
         return(1);
        }
      if(Func=="exp")
        {
         aRes[0]=DoubleToString(MathExp(StringToDouble(aRes[0])));
         return(1);
        }
      if(Func=="floor")
        {
         aRes[0]=DoubleToString(MathFloor(StringToDouble(aRes[0])));
         return(1);
        }
      if(Func=="log")
        {
         aRes[0]=DoubleToString(MathLog(StringToDouble(aRes[0])));
         return(1);
        }
      if(Func=="log10")
        {
         aRes[0]=DoubleToString(MathLog10(StringToDouble(aRes[0])));
         return(1);
        }
      if(Func=="max")
        {
         aRes[0]=DoubleToString(MathMax(StringToDouble(aRes[0]),StringToDouble(aRes[1])));
         return(1);
        }
      if(Func=="min")
        {
         aRes[0]=DoubleToString(MathMin(StringToDouble(aRes[0]),StringToDouble(aRes[1])));
         return(1);
        }
      if(Func=="mod")
        {
         aRes[0]=DoubleToString(MathMod(StringToInteger(aRes[0]),StringToInteger(aRes[1])));
         return(1);
        }
      if(Func=="pow")
        {
         aRes[0]=DoubleToString(MathPow(StringToDouble(aRes[0]),StringToDouble(aRes[1])));
         return(1);
        }
      if(Func=="rand")
        {
         aRes[0]=DoubleToString(MathRand());
         return(1);
        }
      if(Func=="round")
        {
         aRes[0]=DoubleToString(MathRound(StringToDouble(aRes[0])));
         return(1);
        }
      if(Func=="sin")
        {
         aRes[0]=DoubleToString(MathSin(StringToDouble(aRes[0])));
         return(1);
        }
      if(Func=="sqrt")
        {
         aRes[0]=DoubleToString(MathSqrt(StringToDouble(aRes[0])));
         return(1);
        }
      if(Func=="tan")
        {
         aRes[0]=DoubleToString(MathTan(StringToDouble(aRes[0])));
         return(1);
        }
      return(0);
     }
   void ReplaceVarsToValues(string  &aExp[],string  &aValues[],int  &aExpIndexes[],int  &aValIndexes[])
     {
      for(int i=0;i<ArraySize(aExpIndexes);i++)
        {
         aExp[aExpIndexes[i]]=aValues[aValIndexes[i]];
        }
     }
   void FillUserVariables(string  &aNames[],string  &aValues[])
     {
      for(int i=0;i<ArraySize(aNames);i++)
        {
         aValues[i]=UserFunc(aNames[i]);
        }
     }
   void FillUserArraysElements(string  &aFullNames[],string  &aNames[],int  &aIndexes[],string  &aValues[])
     {
      for(int i=0;i<ArraySize(aFullNames);i++)
        {
         aValues[i]=UserArray(aNames[i],aIndexes[i]);
        }
     }
   bool ExistInArray(string aVal,string  &aAr[])
     {
      for(int i=0;i<ArraySize(aAr);i++)
        {
         if(aVal==aAr[i])return(true);
        }
      return(false);
     }
   void AddIfNotExist(string aVal,string  &aAr[])
     {
      if(!ExistInArray(aVal,aAr))
        {
         ArrayResize(aAr,ArraySize(aAr)+1);
         aAr[ArraySize(aAr)-1]=aVal;
        }
     }
   void AddToArrayS(string aVal,string  &aAr[])
     {
      ArrayResize(aAr,ArraySize(aAr)+1);
      aAr[ArraySize(aAr)-1]=aVal;
     }
   void AddToArrayI(int aVal,int  &aAr[])
     {
      ArrayResize(aAr,ArraySize(aAr)+1);
      aAr[ArraySize(aAr)-1]=aVal;
     }
public:
   void Init(string aExpression)
     {

      ArrayResize(a,0);
      ArrayResize(b,0);
      ArrayResize(c,0);
      ArrayResize(all,0);
      ArrayResize(r,0);

      ArrayResize(uv,0);
      ArrayResize(uri,0);
      ArrayResize(uvi,0);
      ArrayResize(fn,0);
      ArrayResize(an,0);
      ArrayResize(ai,0);
      ArrayResize(av,0);
      ArrayResize(uari,0);
      ArrayResize(uavi,0);
      ArrayResize(un,0);
      ArrayResize(uan,0);
      ArrayResize(t,0);
      UserVariables="";
      UserArrays="";
      e="";

      e=aExpression;
      UsersVariables();
      StringSplit(UserVariables,';',un);
      StringSplit(UserArrays,';',uan);
      string as="abs;arccos;arcsin;arctan;ceil;cos;exp;floor;log;log10;max;min;mod;pow;rand;round;sin;sqrt;tan";
      string bs="/;%;*;+;-;>;<;>=;<=;==;!=;&&;||";
      string cs=",;(;)";
      StringSplit(as,';',a);
      StringSplit(bs,';',b);
      StringSplit(cs,';',c);
      Prepare();
     }
   double SolveExpression()
     {
      ArrayCopy(t,r);

      // expression solver!!!
      // 1. fill array with user variables with its current values
      FillUserVariables(un,uv);
      // 2. fill user array elements with its current values
      FillUserArraysElements(fn,an,ai,av);
      // 3. replace user variables to values
      ReplaceVarsToValues(r,uv,uri,uvi);
      // 4. replace user array elements to values
      ReplaceVarsToValues(r,av,uari,uavi);

      // 1. Find internal expression
      string Result="";
      string Res[];
      bool solved=true;
      int cnt=ArraySize(t);
      int cn=0;
      while(solved)
        {
         cn++;
         solved=false;
         int lb=-1;
         for(int i=0;i<cnt;i++)
           {
            if(r[i]=="(")
              {
               lb=i;
              }
            if(r[i]==")")
              {
               if(lb!=-1)
                 {
                  SolveArguments(r,lb+1,i-1,Res); // expressions separated by commas
                  int func=0;
                  if(lb>0)
                    {
                     func=SolveFunc(r[lb-1],Res);
                    }
                  r[lb-func]=Res[0];
                  ArrayCopy(r,r,lb+1-func,i+1,cnt-i-1);
                  cnt=cnt-(i+1-(lb+1-func));
                  solved=true;
                 }
               lb=-1;
              }
           }
        }

      // Result
      return(StringToDouble(SolveSimple(r,0,cnt-1)));

      // All OK
     }
   string About()
     {
      return("Integer's cToken class. https://login.mql5.com/ru/users/Integer");
     }
   void AboutDlg()
     {
      Alert(About());
     }
  };

cToken token1;
cToken token2;
cToken token3;
cToken token4;
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+

void OnStart()
  {
   token1.Init(Expression1);
   token2.Init(Expression2);
   token3.Init(Expression3);
   token4.Init(Expression4);

   Alert(
         "Expression1="+DoubleToString(token1.SolveExpression())+"\n"+
         "Expression2="+DoubleToString(token2.SolveExpression())+"\n"+
         "Expression3="+DoubleToString(token3.SolveExpression())+"\n"+
         "Expression4="+DoubleToString(token4.SolveExpression())
         );
  }
//+------------------------------------------------------------------+

Comments