#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