mirror of
https://github.com/fish-shell/fish-shell.git
synced 2024-11-28 12:13:55 +08:00
[muparser] Propogate and check for lots more errors
This commit is contained in:
parent
0be08e4683
commit
d3822e4cb3
|
@ -272,6 +272,14 @@ void Parser::InitFun() {
|
|||
}
|
||||
}
|
||||
|
||||
/// assert that the given optional error \p oerr is not an error.
|
||||
/// This is used only during initialization, when it ought to be impossible
|
||||
/// to generate an error.
|
||||
static void assertNoError(OptionalError oerr) {
|
||||
assert(!oerr.has_error() && "Unexpected error during initialization");
|
||||
(void)oerr;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Initialize constants.
|
||||
|
||||
|
@ -279,13 +287,8 @@ void Parser::InitFun() {
|
|||
number ("_e").
|
||||
*/
|
||||
void Parser::InitConst() {
|
||||
OptionalError oerr;
|
||||
oerr = DefineConst(_T("_pi"), (value_type)PARSER_CONST_PI);
|
||||
assert(!oerr.has_error() && "Error defining _pi constant");
|
||||
(void)oerr;
|
||||
oerr = DefineConst(_T("_e"), (value_type)PARSER_CONST_E);
|
||||
assert(!oerr.has_error() && "Error defining _e constant");
|
||||
(void)oerr;
|
||||
assertNoError(DefineConst(_T("_pi"), (value_type)PARSER_CONST_PI));
|
||||
assertNoError(DefineConst(_T("_e"), (value_type)PARSER_CONST_E));
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
@ -294,8 +297,8 @@ void Parser::InitConst() {
|
|||
By default only the unary minus operator is added.
|
||||
*/
|
||||
void Parser::InitOprt() {
|
||||
DefineInfixOprt(_T("-"), UnaryMinus);
|
||||
DefineInfixOprt(_T("+"), UnaryPlus);
|
||||
assertNoError(DefineInfixOprt(_T("-"), UnaryMinus));
|
||||
assertNoError(DefineInfixOprt(_T("+"), UnaryPlus));
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
|
|
@ -207,6 +207,14 @@ void ParserInt::InitFun() {
|
|||
DefineFun(_T("max"), Max);
|
||||
}
|
||||
|
||||
/// assert that the given optional error \p oerr is not an error.
|
||||
/// This is used only during initialization, when it ought to be impossible
|
||||
/// to generate an error.
|
||||
static void assertNoError(OptionalError oerr) {
|
||||
assert(!oerr.has_error() && "Unexpected error during initialization");
|
||||
(void)oerr;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Initialize operators. */
|
||||
void ParserInt::InitOprt() {
|
||||
|
@ -216,31 +224,31 @@ void ParserInt::InitOprt() {
|
|||
|
||||
// Disable all built in operators, they wont work with integer numbers
|
||||
// since they are designed for floating point numbers
|
||||
DefineInfixOprt(_T("-"), UnaryMinus);
|
||||
DefineInfixOprt(_T("!"), Not);
|
||||
assertNoError(DefineInfixOprt(_T("-"), UnaryMinus));
|
||||
assertNoError(DefineInfixOprt(_T("!"), Not));
|
||||
|
||||
(void)DefineOprt(_T("&"), LogAnd, prLOGIC);
|
||||
(void)DefineOprt(_T("|"), LogOr, prLOGIC);
|
||||
(void)DefineOprt(_T("&&"), And, prLOGIC);
|
||||
(void)DefineOprt(_T("||"), Or, prLOGIC);
|
||||
assertNoError(DefineOprt(_T("&"), LogAnd, prLOGIC));
|
||||
assertNoError(DefineOprt(_T("|"), LogOr, prLOGIC));
|
||||
assertNoError(DefineOprt(_T("&&"), And, prLOGIC));
|
||||
assertNoError(DefineOprt(_T("||"), Or, prLOGIC));
|
||||
|
||||
(void)DefineOprt(_T("<"), Less, prCMP);
|
||||
(void)DefineOprt(_T(">"), Greater, prCMP);
|
||||
(void)DefineOprt(_T("<="), LessEq, prCMP);
|
||||
(void)DefineOprt(_T(">="), GreaterEq, prCMP);
|
||||
(void)DefineOprt(_T("=="), Equal, prCMP);
|
||||
(void)DefineOprt(_T("!="), NotEqual, prCMP);
|
||||
assertNoError(DefineOprt(_T("<"), Less, prCMP));
|
||||
assertNoError(DefineOprt(_T(">"), Greater, prCMP));
|
||||
assertNoError(DefineOprt(_T("<="), LessEq, prCMP));
|
||||
assertNoError(DefineOprt(_T(">="), GreaterEq, prCMP));
|
||||
assertNoError(DefineOprt(_T("=="), Equal, prCMP));
|
||||
assertNoError(DefineOprt(_T("!="), NotEqual, prCMP));
|
||||
|
||||
(void)DefineOprt(_T("+"), Add, prADD_SUB);
|
||||
(void)DefineOprt(_T("-"), Sub, prADD_SUB);
|
||||
assertNoError(DefineOprt(_T("+"), Add, prADD_SUB));
|
||||
assertNoError(DefineOprt(_T("-"), Sub, prADD_SUB));
|
||||
|
||||
(void)DefineOprt(_T("*"), Mul, prMUL_DIV);
|
||||
(void)DefineOprt(_T("/"), Div, prMUL_DIV);
|
||||
(void)DefineOprt(_T("%"), Mod, prMUL_DIV);
|
||||
assertNoError(DefineOprt(_T("*"), Mul, prMUL_DIV));
|
||||
assertNoError(DefineOprt(_T("/"), Div, prMUL_DIV));
|
||||
assertNoError(DefineOprt(_T("%"), Mod, prMUL_DIV));
|
||||
|
||||
(void)DefineOprt(_T("^"), Pow, prPOW, oaRIGHT);
|
||||
(void)DefineOprt(_T(">>"), Shr, prMUL_DIV + 1);
|
||||
(void)DefineOprt(_T("<<"), Shl, prMUL_DIV + 1);
|
||||
assertNoError(DefineOprt(_T("^"), Pow, prPOW, oaRIGHT));
|
||||
assertNoError(DefineOprt(_T(">>"), Shr, prMUL_DIV + 1));
|
||||
assertNoError(DefineOprt(_T("<<"), Shl, prMUL_DIV + 1));
|
||||
}
|
||||
|
||||
} // namespace mu
|
||||
|
|
|
@ -47,6 +47,12 @@ static value_type getOrThrow(mu::ValueOrError voerr) {
|
|||
return *voerr;
|
||||
}
|
||||
|
||||
static void throwIfError(mu::OptionalError oerr) {
|
||||
if (oerr.has_error()) {
|
||||
throw oerr.error();
|
||||
}
|
||||
}
|
||||
|
||||
int ParserTester::c_iCount = 0;
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
|
@ -95,10 +101,10 @@ int ParserTester::TestInterface() {
|
|||
Parser p;
|
||||
|
||||
try {
|
||||
p.DefineVar(_T("a"), &afVal[0]);
|
||||
p.DefineVar(_T("b"), &afVal[1]);
|
||||
p.DefineVar(_T("c"), &afVal[2]);
|
||||
p.SetExpr(_T("a+b+c"));
|
||||
throwIfError(p.DefineVar(_T("a"), &afVal[0]));
|
||||
throwIfError(p.DefineVar(_T("b"), &afVal[1]));
|
||||
throwIfError(p.DefineVar(_T("c"), &afVal[2]));
|
||||
throwIfError(p.SetExpr(_T("a+b+c")));
|
||||
getOrThrow(p.Eval());
|
||||
} catch (...) {
|
||||
iStat += 1; // this is not supposed to happen
|
||||
|
@ -283,21 +289,17 @@ int ParserTester::TestBinOprt() {
|
|||
//---------------------------------------------------------------------------------------------
|
||||
/** \brief Check muParser name restriction enforcement. */
|
||||
int ParserTester::TestNames() {
|
||||
int iStat = 0, iErr = 0;
|
||||
int failures = 0;
|
||||
|
||||
mu::console() << "testing name restriction enforcement...";
|
||||
|
||||
Parser p;
|
||||
OptionalError oerr;
|
||||
|
||||
#define PARSER_THROWCHECK(DOMAIN, FAIL, EXPR, ARG) \
|
||||
iErr = 0; \
|
||||
ParserTester::c_iCount++; \
|
||||
try { \
|
||||
p.Define##DOMAIN(EXPR, ARG); \
|
||||
} catch (Parser::exception_type &) { \
|
||||
iErr = (FAIL == false) ? 0 : 1; \
|
||||
} \
|
||||
iStat += iErr;
|
||||
#define PARSER_THROWCHECK(DOMAIN, SHOULDPASS, EXPR, ARG) \
|
||||
ParserTester::c_iCount++; \
|
||||
oerr = p.Define##DOMAIN(EXPR, ARG); \
|
||||
failures += (oerr.has_error() == SHOULDPASS);
|
||||
|
||||
// constant names
|
||||
PARSER_THROWCHECK(Const, false, _T("0a"), 1)
|
||||
|
@ -374,12 +376,12 @@ int ParserTester::TestNames() {
|
|||
PARSER_THROWCHECK(Oprt, true, _T("||"), f1of2)
|
||||
#undef PARSER_THROWCHECK
|
||||
|
||||
if (iStat == 0)
|
||||
if (failures == 0)
|
||||
mu::console() << _T("passed") << endl;
|
||||
else
|
||||
mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl;
|
||||
mu::console() << _T("\n failed with ") << failures << _T(" errors") << endl;
|
||||
|
||||
return iStat;
|
||||
return failures;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
@ -970,17 +972,17 @@ int ParserTester::ThrowTest(const string_type &a_str, int a_iErrc, bool a_bFail)
|
|||
value_type fVal[] = {1, 1, 1};
|
||||
Parser p;
|
||||
|
||||
p.DefineVar(_T("a"), &fVal[0]);
|
||||
p.DefineVar(_T("b"), &fVal[1]);
|
||||
p.DefineVar(_T("c"), &fVal[2]);
|
||||
p.DefinePostfixOprt(_T("{m}"), Milli);
|
||||
p.DefinePostfixOprt(_T("m"), Milli);
|
||||
throwIfError(p.DefineVar(_T("a"), &fVal[0]));
|
||||
throwIfError(p.DefineVar(_T("b"), &fVal[1]));
|
||||
throwIfError(p.DefineVar(_T("c"), &fVal[2]));
|
||||
throwIfError(p.DefinePostfixOprt(_T("{m}"), Milli));
|
||||
throwIfError(p.DefinePostfixOprt(_T("m"), Milli));
|
||||
p.DefineFun(_T("ping"), Ping);
|
||||
p.DefineFun(_T("valueof"), ValueOf);
|
||||
p.DefineFun(_T("strfun1"), StrFun1);
|
||||
p.DefineFun(_T("strfun2"), StrFun2);
|
||||
p.DefineFun(_T("strfun3"), StrFun3);
|
||||
p.SetExpr(a_str);
|
||||
throwIfError(p.SetExpr(a_str));
|
||||
getOrThrow(p.Eval());
|
||||
} catch (ParserError &e) {
|
||||
// output the formula in case of an failed test
|
||||
|
@ -1021,8 +1023,8 @@ int ParserTester::EqnTestWithVarChange(const string_type &a_str, double a_fVar1,
|
|||
value_type var = 0;
|
||||
|
||||
// variable
|
||||
p.DefineVar(_T("a"), &var);
|
||||
p.SetExpr(a_str);
|
||||
throwIfError(p.DefineVar(_T("a"), &var));
|
||||
throwIfError(p.SetExpr(a_str));
|
||||
|
||||
var = a_fVar1;
|
||||
fVal[0] = getOrThrow(p.Eval());
|
||||
|
@ -1069,21 +1071,21 @@ int ParserTester::EqnTest(const string_type &a_str, double a_fRes, bool a_fPass)
|
|||
|
||||
p1.reset(new mu::Parser());
|
||||
// Add constants
|
||||
p1->DefineConst(_T("pi"), (value_type)PARSER_CONST_PI);
|
||||
p1->DefineConst(_T("e"), (value_type)PARSER_CONST_E);
|
||||
p1->DefineConst(_T("const"), 1);
|
||||
p1->DefineConst(_T("const1"), 2);
|
||||
p1->DefineConst(_T("const2"), 3);
|
||||
throwIfError(p1->DefineConst(_T("pi"), (value_type)PARSER_CONST_PI));
|
||||
throwIfError(p1->DefineConst(_T("e"), (value_type)PARSER_CONST_E));
|
||||
throwIfError(p1->DefineConst(_T("const"), 1));
|
||||
throwIfError(p1->DefineConst(_T("const1"), 2));
|
||||
throwIfError(p1->DefineConst(_T("const2"), 3));
|
||||
// string constants
|
||||
p1->DefineStrConst(_T("str1"), _T("1.11"));
|
||||
p1->DefineStrConst(_T("str2"), _T("2.22"));
|
||||
throwIfError(p1->DefineStrConst(_T("str1"), _T("1.11")));
|
||||
throwIfError(p1->DefineStrConst(_T("str2"), _T("2.22")));
|
||||
// variables
|
||||
value_type vVarVal[] = {1, 2, 3, -2};
|
||||
p1->DefineVar(_T("a"), &vVarVal[0]);
|
||||
p1->DefineVar(_T("aa"), &vVarVal[1]);
|
||||
p1->DefineVar(_T("b"), &vVarVal[1]);
|
||||
p1->DefineVar(_T("c"), &vVarVal[2]);
|
||||
p1->DefineVar(_T("d"), &vVarVal[3]);
|
||||
throwIfError(p1->DefineVar(_T("a"), &vVarVal[0]));
|
||||
throwIfError(p1->DefineVar(_T("aa"), &vVarVal[1]));
|
||||
throwIfError(p1->DefineVar(_T("b"), &vVarVal[1]));
|
||||
throwIfError(p1->DefineVar(_T("c"), &vVarVal[2]));
|
||||
throwIfError(p1->DefineVar(_T("d"), &vVarVal[3]));
|
||||
|
||||
// custom value ident functions
|
||||
p1->AddValIdent(&ParserTester::IsHexVal);
|
||||
|
@ -1107,9 +1109,9 @@ int ParserTester::EqnTest(const string_type &a_str, double a_fRes, bool a_fPass)
|
|||
p1->DefineFun(_T("f5of5"), f5of5);
|
||||
|
||||
// binary operators
|
||||
p1->DefineOprt(_T("add"), add, 0);
|
||||
p1->DefineOprt(_T("++"), add, 0);
|
||||
p1->DefineOprt(_T("&"), land, prLAND);
|
||||
throwIfError(p1->DefineOprt(_T("add"), add, 0));
|
||||
throwIfError(p1->DefineOprt(_T("++"), add, 0));
|
||||
throwIfError(p1->DefineOprt(_T("&"), land, prLAND));
|
||||
|
||||
// sample functions
|
||||
p1->DefineFun(_T("min"), Min);
|
||||
|
@ -1127,16 +1129,16 @@ int ParserTester::EqnTest(const string_type &a_str, double a_fRes, bool a_fPass)
|
|||
// infix / postfix operator
|
||||
// Note: Identifiers used here do not have any meaning
|
||||
// they are mere placeholders to test certain features.
|
||||
p1->DefineInfixOprt(_T("$"), sign, prPOW + 1); // sign with high priority
|
||||
p1->DefineInfixOprt(_T("~"), plus2); // high priority
|
||||
p1->DefineInfixOprt(_T("~~"), plus2);
|
||||
p1->DefinePostfixOprt(_T("{m}"), Milli);
|
||||
p1->DefinePostfixOprt(_T("{M}"), Mega);
|
||||
p1->DefinePostfixOprt(_T("m"), Milli);
|
||||
p1->DefinePostfixOprt(_T("meg"), Mega);
|
||||
p1->DefinePostfixOprt(_T("#"), times3);
|
||||
p1->DefinePostfixOprt(_T("'"), sqr);
|
||||
p1->SetExpr(a_str);
|
||||
throwIfError(p1->DefineInfixOprt(_T("$"), sign, prPOW + 1)); // sign with high priority
|
||||
throwIfError(p1->DefineInfixOprt(_T("~"), plus2)); // high priority
|
||||
throwIfError(p1->DefineInfixOprt(_T("~~"), plus2));
|
||||
throwIfError(p1->DefinePostfixOprt(_T("{m}"), Milli));
|
||||
throwIfError(p1->DefinePostfixOprt(_T("{M}"), Mega));
|
||||
throwIfError(p1->DefinePostfixOprt(_T("m"), Milli));
|
||||
throwIfError(p1->DefinePostfixOprt(_T("meg"), Mega));
|
||||
throwIfError(p1->DefinePostfixOprt(_T("#"), times3));
|
||||
throwIfError(p1->DefinePostfixOprt(_T("'"), sqr));
|
||||
throwIfError(p1->SetExpr(a_str));
|
||||
|
||||
// Test bytecode integrity
|
||||
// String parsing and bytecode parsing must yield the same result
|
||||
|
@ -1201,13 +1203,13 @@ int ParserTester::EqnTestInt(const string_type &a_str, double a_fRes, bool a_fPa
|
|||
try {
|
||||
value_type fVal[2] = {-99, -999}; // results: initially should be different
|
||||
ParserInt p;
|
||||
p.DefineConst(_T("const1"), 1);
|
||||
p.DefineConst(_T("const2"), 2);
|
||||
p.DefineVar(_T("a"), &vVarVal[0]);
|
||||
p.DefineVar(_T("b"), &vVarVal[1]);
|
||||
p.DefineVar(_T("c"), &vVarVal[2]);
|
||||
throwIfError(p.DefineConst(_T("const1"), 1));
|
||||
throwIfError(p.DefineConst(_T("const2"), 2));
|
||||
throwIfError(p.DefineVar(_T("a"), &vVarVal[0]));
|
||||
throwIfError(p.DefineVar(_T("b"), &vVarVal[1]));
|
||||
throwIfError(p.DefineVar(_T("c"), &vVarVal[2]));
|
||||
|
||||
p.SetExpr(a_str);
|
||||
throwIfError((p.SetExpr(a_str)));
|
||||
fVal[0] = getOrThrow(p.Eval()); // result from stringparsing
|
||||
fVal[1] = getOrThrow(p.Eval()); // result from bytecode
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user