📄 muparsertest.cpp
字号:
// distinguish constants with same basename
iStat += EqnTest("const", 1, true);
iStat += EqnTest("const1", 2, true);
iStat += EqnTest("const2", 3, true);
iStat += EqnTest("2*const", 2, true);
iStat += EqnTest("2*const1", 4, true);
iStat += EqnTest("2*const2", 6, true);
iStat += EqnTest("2*const+1", 3, true);
iStat += EqnTest("2*const1+1", 5, true);
iStat += EqnTest("2*const2+1", 7, true);
iStat += EqnTest("const", 0, false);
iStat += EqnTest("const1", 0, false);
iStat += EqnTest("const2", 0, false);
// distinguish variables with same basename
iStat += EqnTest("a", 1, true);
iStat += EqnTest("aa", 2, true);
iStat += EqnTest("2*a", 2, true);
iStat += EqnTest("2*aa", 4, true);
iStat += EqnTest("2*a-1", 1, true);
iStat += EqnTest("2*aa-1", 3, true);
// Finally test querying of used variables
try
{
int idx;
mu::Parser p;
mu::value_type vVarVal[] = { 1, 2, 3, 4, 5};
p.DefineVar("a", &vVarVal[0]);
p.DefineVar("b", &vVarVal[1]);
p.DefineVar("c", &vVarVal[2]);
p.DefineVar("d", &vVarVal[3]);
p.DefineVar("e", &vVarVal[4]);
// Test lookup of defined variables
// 4 used variables
p.SetExpr("a+b+c+d");
mu::varmap_type UsedVar = p.GetUsedVar();
int iCount = (int)UsedVar.size();
if (iCount!=4) throw false;
mu::varmap_type::const_iterator item = UsedVar.begin();
for (idx=0; item!=UsedVar.end(); ++item)
{
if (&vVarVal[idx++]!=item->second)
throw false;
}
// Test lookup of undefined variables
p.SetExpr("undef1+undef2+undef3");
UsedVar = p.GetUsedVar();
iCount = (int)UsedVar.size();
if (iCount!=3) throw false;
for (item = UsedVar.begin(); item!=UsedVar.end(); ++item)
{
if (item->second!=0)
throw false; // all pointers to undefined variables must be null
}
// 1 used variables
p.SetExpr("a+b");
UsedVar = p.GetUsedVar();
iCount = (int)UsedVar.size();
if (iCount!=2) throw false;
item = UsedVar.begin();
for (idx=0; item!=UsedVar.end(); ++item)
if (&vVarVal[idx++]!=item->second) throw false;
}
catch(...)
{
iStat += 1;
}
if (iStat==0)
*m_stream << "passed" << endl;
else
*m_stream << "\n failed with " << iStat << " errors" << endl;
return iStat;
}
//---------------------------------------------------------------------------
int ParserTester::TestMultiArg()
{
int iStat = 0;
*m_stream << "testing multiarg functions...";
// picking the right argument
iStat += EqnTest("f1of1(1)", 1, true);
iStat += EqnTest("f1of2(1, 2)", 1, true);
iStat += EqnTest("f2of2(1, 2)", 2, true);
iStat += EqnTest("f1of3(1, 2, 3)", 1, true);
iStat += EqnTest("f2of3(1, 2, 3)", 2, true);
iStat += EqnTest("f3of3(1, 2, 3)", 3, true);
iStat += EqnTest("f1of4(1, 2, 3, 4)", 1, true);
iStat += EqnTest("f2of4(1, 2, 3, 4)", 2, true);
iStat += EqnTest("f3of4(1, 2, 3, 4)", 3, true);
iStat += EqnTest("f4of4(1, 2, 3, 4)", 4, true);
iStat += EqnTest("f1of5(1, 2, 3, 4, 5)", 1, true);
iStat += EqnTest("f2of5(1, 2, 3, 4, 5)", 2, true);
iStat += EqnTest("f3of5(1, 2, 3, 4, 5)", 3, true);
iStat += EqnTest("f4of5(1, 2, 3, 4, 5)", 4, true);
iStat += EqnTest("f5of5(1, 2, 3, 4, 5)", 5, true);
// Too few arguments / Too many arguments
iStat += EqnTest("f1of1(1,2)", 0, false);
iStat += EqnTest("f1of1()", 0, false);
iStat += EqnTest("f1of2(1, 2, 3)", 0, false);
iStat += EqnTest("f1of2(1)", 0, false);
iStat += EqnTest("f1of3(1, 2, 3, 4)", 0, false);
iStat += EqnTest("f1of3(1)", 0, false);
iStat += EqnTest("f1of4(1, 2, 3, 4, 5)", 0, false);
iStat += EqnTest("f1of4(1)", 0, false);
iStat += EqnTest("(1,2,3)", 0, false);
iStat += EqnTest("1,2,3", 0, false);
iStat += EqnTest("(1*a,2,3)", 0, false);
iStat += EqnTest("1,2*a,3", 0, false);
// correct calculation of arguments
iStat += EqnTest("min(a, 1)", 1, true);
iStat += EqnTest("min(3*2, 1)", 1, true);
iStat += EqnTest("min(3*2, 1)", 6, false);
// correct calculation of arguments
iStat += EqnTest("min(3*a+1, 1)", 1, true);
iStat += EqnTest("max(3*a+1, 1)", 4, true);
iStat += EqnTest("max(3*a+1, 1)*2", 8, true);
iStat += EqnTest("2*max(3*a+1, 1)+2", 10, true);
// functions with Variable argument count
iStat += EqnTest("sum(1,2,3)", 6, true);
iStat += EqnTest("2*sum(1,2,3)", 12, true);
iStat += EqnTest("2*sum(1,2,3)+2", 14, true);
iStat += EqnTest("2*sum(-1,2,3)+2", 10, true);
iStat += EqnTest("2*sum(-1,2,-(-a))+2", 6, true);
iStat += EqnTest("2*sum(-1,10,-a)+2", 18, true);
iStat += EqnTest("2*sum(1,2,3)*2", 24, true);
iStat += EqnTest("sum(1,-max(1,2),3)*2", 4, true);
iStat += EqnTest("sum(1*3, 4, a+2)", 10, true);
iStat += EqnTest("sum(1*3, 2*sum(1,2,2), a+2)", 16, true);
iStat += EqnTest("sum(1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2)", 24, true);
// some failures
iStat += EqnTest("sum()", 0, false);
iStat += EqnTest("sum(,)", 0, false);
iStat += EqnTest("sum(1,2,)", 0, false);
iStat += EqnTest("sum(,1,2)", 0, false);
if (iStat==0)
*m_stream << "passed" << endl;
else
*m_stream << "\n failed with " << iStat << " errors" << endl;
return iStat;
}
//---------------------------------------------------------------------------
int ParserTester::TestInfixOprt()
{
int iStat = 0;
*m_stream << "testing infix operators...";
iStat += EqnTest("-1", -1, true);
iStat += EqnTest("-(-1)", 1, true);
iStat += EqnTest("-(-1)*2", 2, true);
iStat += EqnTest("-(-2)*sqrt(4)", 4, true);
iStat += EqnTest("-a", -1, true);
iStat += EqnTest("-(a)", -1, true);
iStat += EqnTest("-(-a)", 1, true);
iStat += EqnTest("-(-a)*2", 2, true);
iStat += EqnTest("-(8)", -8, true);
iStat += EqnTest("-8", -8, true);
iStat += EqnTest("-(2+1)", -3, true);
iStat += EqnTest("-(f1of1(1+2*3)+1*2)", -9, true);
iStat += EqnTest("-(-f1of1(1+2*3)+1*2)", 5, true);
iStat += EqnTest("-sin(8)", -0.989358, true);
iStat += EqnTest("3-(-a)", 4, true);
iStat += EqnTest("3--a", 4, true);
// Postfix / infix priorities
iStat += EqnTest("~2#", 12, true);
iStat += EqnTest("~f1of1(2)#", 12, true);
iStat += EqnTest("~(b)#", 12, true);
iStat += EqnTest("(~b)#", 12, true);
iStat += EqnTest("~(2#)", 8, true);
iStat += EqnTest("~(f1of1(2)#)", 8, true);
if (iStat==0)
*m_stream << "passed" << endl;
else
*m_stream << "\n failed with " << iStat << " errors" << endl;
return iStat;
}
//---------------------------------------------------------------------------
int ParserTester::TestPostFix()
{
int iStat = 0;
*m_stream << "testing postfix operators...";
// application
iStat += EqnTest("3m+5", 5.003, true);
iStat += EqnTest("1000m", 1, true);
iStat += EqnTest("1000 m", 1, true);
iStat += EqnTest("(a)m", 1e-3, true);
iStat += EqnTest("-(a)m", -1e-3, true);
iStat += EqnTest("-2m", -2e-3, true);
iStat += EqnTest("f1of1(1000)m", 1, true);
iStat += EqnTest("-f1of1(1000)m", -1, true);
iStat += EqnTest("-f1of1(-1000)m", 1, true);
iStat += EqnTest("f4of4(0,0,0,1000)m", 1, true);
iStat += EqnTest("2+(a*1000)m", 3, true);
// some incorrect results
iStat += EqnTest("1000m", 0.1, false);
iStat += EqnTest("(a)m", 2, false);
// failure due to syntax checking
iStat += EqnTest("a m", 0, false);
iStat += EqnTest("4 + m", 0, false);
iStat += EqnTest("m4", 0, false);
iStat += EqnTest("sin(m)", 0, false);
iStat += EqnTest("m m", 0, false);
iStat += EqnTest("m(8)", 0, false);
iStat += EqnTest("4,m", 0, false);
iStat += EqnTest("-m", 0, false);
iStat += EqnTest("2(-m)", 0, false);
iStat += EqnTest("2(m)", 0, false);
if (iStat==0)
*m_stream << "passed" << endl;
else
*m_stream << "\n failed with " << iStat << " errors" << endl;
return iStat;
}
//---------------------------------------------------------------------------
/** \brief Test volatile (nonoptimizeable functions). */
int ParserTester::TestVolatile()
{
int iStat = 0;
*m_stream << "testing volatile/nonvolatile functions...";
// First test with volatile flag turned on
try
{
mu::Parser p;
p.DefineFun("rnd", Rnd, false);
p.DefineFun("valueof", RndWithString, false);
// 1st test, compare results from sucessive calculations
p.SetExpr("3+rnd(8)");
if (p.Eval()==p.Eval()) iStat += 1;
// 2nd test, force bytecode creation, compare two results both
// calculated from bytecode
p.SetExpr("3+rnd(8)");
p.Eval(); //<- Force bytecode creation
if (p.Eval()==p.Eval()) iStat += 1;
p.SetExpr("3*rnd(8)+3");
p.Eval(); //<- Force bytecode creation
if (p.Eval()==p.Eval()) iStat += 1;
p.SetExpr("10+3*sin(rnd(8))-1");
p.Eval(); //<- Force bytecode creation
if (p.Eval()==p.Eval()) iStat += 1;
p.SetExpr("3+rnd(rnd(8))*2");
p.Eval(); //<- Force bytecode creation
if (p.Eval()==p.Eval()) iStat += 1;
p.SetExpr("valueof(\"Das ist ein Test\")");
p.Eval(); //<- Force bytecode creation
if (p.Eval()==p.Eval()) iStat += 1;
}
catch(Parser::exception_type &e)
{
*m_stream << "\n " << e.GetExpr() << " : " << e.GetMsg();
iStat += 1;
}
// Second test with volatile flag turned off
try
{
mu::Parser p;
p.DefineFun("rnd", Rnd);
p.DefineFun("valueof", RndWithString);
// compare string parsing with bytecode
p.SetExpr("3+rnd(8)");
if (p.Eval()!=p.Eval()) iStat += 1;
p.SetExpr("3+rnd(8)");
p.Eval(); //<- Force bytecode creation
if (p.Eval()!=p.Eval()) iStat += 1;
p.SetExpr("3*rnd(8)+3");
p.Eval(); //<- Force bytecode creation
if (p.Eval()!=p.Eval()) iStat += 1;
p.SetExpr("10+3*sin(rnd(8))-1");
p.Eval(); //<- Force bytecode creation
if (p.Eval()!=p.Eval()) iStat += 1;
p.SetExpr("3+rnd(rnd(8))*2");
p.Eval(); //<- Force bytecode creation
if (p.Eval()!=p.Eval()) iStat += 1;
p.SetExpr("valueof(\"Das ist ein Test\")");
p.Eval(); //<- Force bytecode creation
if (p.Eval()!=p.Eval()) iStat += 1;
}
catch(Parser::exception_type &e)
{
*m_stream << "\n " << e.GetExpr() << " : " << e.GetMsg();
iStat += 1;
}
if (iStat==0)
*m_stream << "passed" << endl;
else
*m_stream << "\n failed with " << iStat << " errors" << endl;
return iStat;
}
//---------------------------------------------------------------------------
int ParserTester::TestFormula()
{
int iStat = 0;
*m_stream << "testing sample formulas...";
// operator precedencs
iStat += EqnTest("1+2-3*4/5^6", 2.99923, true);
iStat += EqnTest("1^2/3*4-5+6", 2.3333, true);
iStat += EqnTest("1+2*3", 7, true);
iStat += EqnTest("1+2*3", 7, true);
iStat += EqnTest("(1+2)*3", 9, true);
iStat += EqnTest("(1+2)*(-3)", -9, true);
iStat += EqnTest("2/4", 0.5, true);
iStat += EqnTest("exp(ln(7))", 7, true);
iStat += EqnTest("e^ln(7)", 7, true);
iStat += EqnTest("e^(ln(7))", 7, true);
iStat += EqnTest("(e^(ln(7)))", 7, true);
iStat += EqnTest("1-(e^(ln(7)))", -6, true);
iStat += EqnTest("2*(e^(ln(7)))", 14, true);
iStat += EqnTest("10^log(5)", 5, true);
iStat += EqnTest("10^log10(5)", 5, true);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -