mirror of
https://github.com/fish-shell/fish-shell.git
synced 2025-02-18 04:42:51 +08:00
[muparser] Make some error handling in ParserBase explicit
Return ParserError instead of throwing exceptions
This commit is contained in:
parent
62bedde23d
commit
f3a9773849
|
@ -1079,7 +1079,6 @@ OptionalError ParserBase::CreateRPN() const {
|
|||
case cmARG_SEP:
|
||||
if (stArgCount.empty())
|
||||
return Error(ecUNEXPECTED_ARG_SEP, m_pTokenReader->GetPos());
|
||||
|
||||
++stArgCount.top();
|
||||
// fallthrough intentional (no break!)
|
||||
|
||||
|
|
|
@ -42,6 +42,10 @@
|
|||
#include "muParserDLL.h"
|
||||
#include "muParserInt.h"
|
||||
|
||||
static void throwIfError(mu::OptionalError oerr) {
|
||||
if (oerr.has_error()) throw oerr.error();
|
||||
}
|
||||
|
||||
#define MU_TRY try {
|
||||
#define MU_CATCH \
|
||||
} \
|
||||
|
@ -205,7 +209,7 @@ API_EXPORT(muFloat_t) mupEval(muParserHandle_t a_hParser) {
|
|||
API_EXPORT(void) mupSetExpr(muParserHandle_t a_hParser, const muChar_t* a_szExpr) {
|
||||
MU_TRY
|
||||
muParser_t* const p(AsParser(a_hParser));
|
||||
p->SetExpr(a_szExpr);
|
||||
throwIfError(p->SetExpr(a_szExpr));
|
||||
MU_CATCH
|
||||
}
|
||||
|
||||
|
@ -411,7 +415,8 @@ mupDefineOprt(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun2_t a_p
|
|||
muInt_t a_nPrec, muInt_t a_nOprtAsct, muBool_t a_bAllowOpt) {
|
||||
MU_TRY
|
||||
muParser_t* const p(AsParser(a_hParser));
|
||||
p->DefineOprt(a_szName, a_pFun, a_nPrec, (mu::EOprtAssociativity)a_nOprtAsct, a_bAllowOpt != 0);
|
||||
throwIfError(p->DefineOprt(a_szName, a_pFun, a_nPrec, (mu::EOprtAssociativity)a_nOprtAsct,
|
||||
a_bAllowOpt != 0));
|
||||
MU_CATCH
|
||||
}
|
||||
|
||||
|
@ -420,7 +425,7 @@ API_EXPORT(void)
|
|||
mupDefineVar(muParserHandle_t a_hParser, const muChar_t* a_szName, muFloat_t* a_pVar) {
|
||||
MU_TRY
|
||||
muParser_t* const p(AsParser(a_hParser));
|
||||
p->DefineVar(a_szName, a_pVar);
|
||||
throwIfError(p->DefineVar(a_szName, a_pVar));
|
||||
MU_CATCH
|
||||
}
|
||||
|
||||
|
@ -429,7 +434,7 @@ API_EXPORT(void)
|
|||
mupDefineBulkVar(muParserHandle_t a_hParser, const muChar_t* a_szName, muFloat_t* a_pVar) {
|
||||
MU_TRY
|
||||
muParser_t* const p(AsParser(a_hParser));
|
||||
p->DefineVar(a_szName, a_pVar);
|
||||
throwIfError(p->DefineVar(a_szName, a_pVar));
|
||||
MU_CATCH
|
||||
}
|
||||
|
||||
|
@ -438,7 +443,7 @@ API_EXPORT(void)
|
|||
mupDefineConst(muParserHandle_t a_hParser, const muChar_t* a_szName, muFloat_t a_fVal) {
|
||||
MU_TRY
|
||||
muParser_t* const p(AsParser(a_hParser));
|
||||
p->DefineConst(a_szName, a_fVal);
|
||||
throwIfError(p->DefineConst(a_szName, a_fVal));
|
||||
MU_CATCH
|
||||
}
|
||||
|
||||
|
@ -447,7 +452,7 @@ API_EXPORT(void)
|
|||
mupDefineStrConst(muParserHandle_t a_hParser, const muChar_t* a_szName, const muChar_t* a_szVal) {
|
||||
MU_TRY
|
||||
muParser_t* const p(AsParser(a_hParser));
|
||||
p->DefineStrConst(a_szName, a_szVal);
|
||||
throwIfError(p->DefineStrConst(a_szName, a_szVal));
|
||||
MU_CATCH
|
||||
}
|
||||
|
||||
|
|
|
@ -41,6 +41,12 @@ using namespace std;
|
|||
|
||||
namespace mu {
|
||||
namespace Test {
|
||||
|
||||
static value_type getOrThrow(mu::ValueOrError voerr) {
|
||||
if (voerr.has_error()) throw voerr.error();
|
||||
return *voerr;
|
||||
}
|
||||
|
||||
int ParserTester::c_iCount = 0;
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
|
@ -93,14 +99,14 @@ int ParserTester::TestInterface() {
|
|||
p.DefineVar(_T("b"), &afVal[1]);
|
||||
p.DefineVar(_T("c"), &afVal[2]);
|
||||
p.SetExpr(_T("a+b+c"));
|
||||
(void)p.Eval();
|
||||
getOrThrow(p.Eval());
|
||||
} catch (...) {
|
||||
iStat += 1; // this is not supposed to happen
|
||||
}
|
||||
|
||||
try {
|
||||
p.RemoveVar(_T("c"));
|
||||
(void)p.Eval();
|
||||
getOrThrow(p.Eval());
|
||||
iStat += 1; // not supposed to reach this, nonexisting variable "c" deleted...
|
||||
} catch (...) {
|
||||
// failure is expected...
|
||||
|
@ -323,12 +329,10 @@ int ParserTester::TestNames() {
|
|||
PARSER_THROWCHECK(Var, true, _T("a_min"), &a)
|
||||
PARSER_THROWCHECK(Var, true, _T("a_min0"), &a)
|
||||
PARSER_THROWCHECK(Var, true, _T("a_min9"), &a)
|
||||
PARSER_THROWCHECK(Var, false, _T("a_min9"), 0)
|
||||
// Postfix operators
|
||||
// fail
|
||||
PARSER_THROWCHECK(PostfixOprt, false, _T("(k"), f1of1)
|
||||
PARSER_THROWCHECK(PostfixOprt, false, _T("9+"), f1of1)
|
||||
PARSER_THROWCHECK(PostfixOprt, false, _T("+"), 0)
|
||||
// pass
|
||||
PARSER_THROWCHECK(PostfixOprt, true, _T("-a"), f1of1)
|
||||
PARSER_THROWCHECK(PostfixOprt, true, _T("?a"), f1of1)
|
||||
|
@ -977,7 +981,7 @@ int ParserTester::ThrowTest(const string_type &a_str, int a_iErrc, bool a_bFail)
|
|||
p.DefineFun(_T("strfun2"), StrFun2);
|
||||
p.DefineFun(_T("strfun3"), StrFun3);
|
||||
p.SetExpr(a_str);
|
||||
(void)p.Eval();
|
||||
getOrThrow(p.Eval());
|
||||
} catch (ParserError &e) {
|
||||
// output the formula in case of an failed test
|
||||
if (a_bFail == false || (a_bFail == true && a_iErrc != e.GetCode())) {
|
||||
|
@ -1021,10 +1025,10 @@ int ParserTester::EqnTestWithVarChange(const string_type &a_str, double a_fVar1,
|
|||
p.SetExpr(a_str);
|
||||
|
||||
var = a_fVar1;
|
||||
fVal[0] = *p.Eval();
|
||||
fVal[0] = getOrThrow(p.Eval());
|
||||
|
||||
var = a_fVar2;
|
||||
fVal[1] = *p.Eval();
|
||||
fVal[1] = getOrThrow(p.Eval());
|
||||
|
||||
if (fabs(a_fRes1 - fVal[0]) > 0.0000000001)
|
||||
throw std::runtime_error("incorrect result (first pass)");
|
||||
|
@ -1136,8 +1140,8 @@ int ParserTester::EqnTest(const string_type &a_str, double a_fRes, bool a_fPass)
|
|||
|
||||
// Test bytecode integrity
|
||||
// String parsing and bytecode parsing must yield the same result
|
||||
fVal[0] = *p1->Eval(); // result from stringparsing
|
||||
fVal[1] = *p1->Eval(); // result from bytecode
|
||||
fVal[0] = getOrThrow(p1->Eval()); // result from stringparsing
|
||||
fVal[1] = getOrThrow(p1->Eval()); // result from bytecode
|
||||
if (fVal[0] != fVal[1])
|
||||
throw Parser::exception_type(_T("Bytecode / string parsing mismatch."));
|
||||
|
||||
|
@ -1204,8 +1208,8 @@ int ParserTester::EqnTestInt(const string_type &a_str, double a_fRes, bool a_fPa
|
|||
p.DefineVar(_T("c"), &vVarVal[2]);
|
||||
|
||||
p.SetExpr(a_str);
|
||||
fVal[0] = *p.Eval(); // result from stringparsing
|
||||
fVal[1] = *p.Eval(); // result from bytecode
|
||||
fVal[0] = getOrThrow(p.Eval()); // result from stringparsing
|
||||
fVal[1] = getOrThrow(p.Eval()); // result from bytecode
|
||||
|
||||
if (fVal[0] != fVal[1]) throw Parser::exception_type(_T("Bytecode corrupt."));
|
||||
|
||||
|
|
|
@ -166,10 +166,13 @@ ParserTokenReader::token_type ParserTokenReader::ReadNextToken() {
|
|||
//
|
||||
string_type strTok;
|
||||
int iEnd = ExtractToken(m_pParser->ValidNameChars(), strTok, m_iPos);
|
||||
if (iEnd != m_iPos) Error(ecUNASSIGNABLE_TOKEN, m_iPos, strTok);
|
||||
if (iEnd != m_iPos) {
|
||||
Error(ecUNASSIGNABLE_TOKEN, m_iPos, strTok);
|
||||
return {};
|
||||
}
|
||||
|
||||
Error(ecUNASSIGNABLE_TOKEN, m_iPos, m_strFormula.substr(m_iPos));
|
||||
return token_type();
|
||||
return {};
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
@ -267,7 +270,7 @@ bool ParserTokenReader::IsBuiltIn(token_type &a_Tok) {
|
|||
|
||||
// The assignment operator need special treatment
|
||||
if (i == cmASSIGN && m_iSynFlags & noASSIGN)
|
||||
Error(ecUNEXPECTED_OPERATOR, m_iPos, pOprtDef[i]);
|
||||
return Error(ecUNEXPECTED_OPERATOR, m_iPos, pOprtDef[i]);
|
||||
|
||||
if (!m_pParser->HasBuiltInOprt()) continue;
|
||||
if (m_iSynFlags & noOPT) {
|
||||
|
@ -276,7 +279,7 @@ bool ParserTokenReader::IsBuiltIn(token_type &a_Tok) {
|
|||
// their identifiers
|
||||
if (IsInfixOpTok(a_Tok)) return true;
|
||||
|
||||
Error(ecUNEXPECTED_OPERATOR, m_iPos, pOprtDef[i]);
|
||||
return Error(ecUNEXPECTED_OPERATOR, m_iPos, pOprtDef[i]);
|
||||
}
|
||||
|
||||
m_iSynFlags =
|
||||
|
@ -284,7 +287,7 @@ bool ParserTokenReader::IsBuiltIn(token_type &a_Tok) {
|
|||
break;
|
||||
|
||||
case cmBO:
|
||||
if (m_iSynFlags & noBO) Error(ecUNEXPECTED_PARENS, m_iPos, pOprtDef[i]);
|
||||
if (m_iSynFlags & noBO) return Error(ecUNEXPECTED_PARENS, m_iPos, pOprtDef[i]);
|
||||
|
||||
if (m_lastTok.GetCode() == cmFUNC)
|
||||
m_iSynFlags =
|
||||
|
@ -297,21 +300,23 @@ bool ParserTokenReader::IsBuiltIn(token_type &a_Tok) {
|
|||
break;
|
||||
|
||||
case cmBC:
|
||||
if (m_iSynFlags & noBC) Error(ecUNEXPECTED_PARENS, m_iPos, pOprtDef[i]);
|
||||
if (m_iSynFlags & noBC) return Error(ecUNEXPECTED_PARENS, m_iPos, pOprtDef[i]);
|
||||
|
||||
m_iSynFlags = noBO | noVAR | noVAL | noFUN | noINFIXOP | noSTR | noASSIGN;
|
||||
|
||||
if (--m_iBrackets < 0) Error(ecUNEXPECTED_PARENS, m_iPos, pOprtDef[i]);
|
||||
if (--m_iBrackets < 0) return Error(ecUNEXPECTED_PARENS, m_iPos, pOprtDef[i]);
|
||||
break;
|
||||
|
||||
case cmELSE:
|
||||
if (m_iSynFlags & noELSE) Error(ecUNEXPECTED_CONDITIONAL, m_iPos, pOprtDef[i]);
|
||||
if (m_iSynFlags & noELSE)
|
||||
return Error(ecUNEXPECTED_CONDITIONAL, m_iPos, pOprtDef[i]);
|
||||
|
||||
m_iSynFlags = noBC | noPOSTOP | noEND | noOPT | noIF | noELSE;
|
||||
break;
|
||||
|
||||
case cmIF:
|
||||
if (m_iSynFlags & noIF) Error(ecUNEXPECTED_CONDITIONAL, m_iPos, pOprtDef[i]);
|
||||
if (m_iSynFlags & noIF)
|
||||
return Error(ecUNEXPECTED_CONDITIONAL, m_iPos, pOprtDef[i]);
|
||||
|
||||
m_iSynFlags = noBC | noPOSTOP | noEND | noOPT | noIF | noELSE;
|
||||
break;
|
||||
|
@ -340,7 +345,7 @@ bool ParserTokenReader::IsArgSep(token_type &a_Tok) {
|
|||
szSep[0] = m_cArgSep;
|
||||
szSep[1] = 0;
|
||||
|
||||
if (m_iSynFlags & noARG_SEP) Error(ecUNEXPECTED_ARG_SEP, m_iPos, szSep);
|
||||
if (m_iSynFlags & noARG_SEP) return Error(ecUNEXPECTED_ARG_SEP, m_iPos, szSep);
|
||||
|
||||
m_iSynFlags = noBC | noOPT | noEND | noARG_SEP | noPOSTOP | noASSIGN;
|
||||
m_iPos++;
|
||||
|
@ -363,9 +368,9 @@ bool ParserTokenReader::IsEOF(token_type &a_Tok) {
|
|||
|
||||
// check for EOF
|
||||
if (!szFormula[m_iPos] /*|| szFormula[m_iPos] == '\n'*/) {
|
||||
if (m_iSynFlags & noEND) Error(ecUNEXPECTED_EOF, m_iPos);
|
||||
if (m_iSynFlags & noEND) return Error(ecUNEXPECTED_EOF, m_iPos);
|
||||
|
||||
if (m_iBrackets > 0) Error(ecMISSING_PARENS, m_iPos, _T(")"));
|
||||
if (m_iBrackets > 0) return Error(ecMISSING_PARENS, m_iPos, _T(")"));
|
||||
|
||||
m_iSynFlags = 0;
|
||||
a_Tok.Set(cmEND);
|
||||
|
@ -392,7 +397,8 @@ bool ParserTokenReader::IsInfixOpTok(token_type &a_Tok) {
|
|||
a_Tok.Set(it->second, it->first);
|
||||
m_iPos += (int)it->first.length();
|
||||
|
||||
if (m_iSynFlags & noINFIXOP) Error(ecUNEXPECTED_OPERATOR, m_iPos, a_Tok.GetAsString());
|
||||
if (m_iSynFlags & noINFIXOP)
|
||||
return Error(ecUNEXPECTED_OPERATOR, m_iPos, a_Tok.GetAsString());
|
||||
|
||||
m_iSynFlags = noPOSTOP | noINFIXOP | noOPT | noBC | noSTR | noASSIGN;
|
||||
return true;
|
||||
|
@ -405,7 +411,7 @@ bool ParserTokenReader::IsInfixOpTok(token_type &a_Tok) {
|
|||
m_iPos = (int)iEnd;
|
||||
|
||||
if (m_iSynFlags & noINFIXOP)
|
||||
Error(ecUNEXPECTED_OPERATOR, m_iPos, a_Tok.GetAsString());
|
||||
return Error(ecUNEXPECTED_OPERATOR, m_iPos, a_Tok.GetAsString());
|
||||
|
||||
m_iSynFlags = noPOSTOP | noINFIXOP | noOPT | noBC | noSTR | noASSIGN;
|
||||
return true;
|
||||
|
@ -435,7 +441,8 @@ bool ParserTokenReader::IsFunTok(token_type &a_Tok) {
|
|||
|
||||
m_iPos = (int)iEnd;
|
||||
if (m_iSynFlags & noFUN)
|
||||
Error(ecUNEXPECTED_FUN, m_iPos - (int)a_Tok.GetAsString().length(), a_Tok.GetAsString());
|
||||
return Error(ecUNEXPECTED_FUN, m_iPos - (int)a_Tok.GetAsString().length(),
|
||||
a_Tok.GetAsString());
|
||||
|
||||
m_iSynFlags = noANY ^ noBO;
|
||||
return true;
|
||||
|
@ -483,7 +490,7 @@ bool ParserTokenReader::IsOprt(token_type &a_Tok) {
|
|||
else {
|
||||
// nope, no infix operator
|
||||
return false;
|
||||
// Error(ecUNEXPECTED_OPERATOR, m_iPos, a_Tok.GetAsString());
|
||||
// return Error(ecUNEXPECTED_OPERATOR, m_iPos, a_Tok.GetAsString());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -562,7 +569,8 @@ bool ParserTokenReader::IsValTok(token_type &a_Tok) {
|
|||
m_iPos = iEnd;
|
||||
a_Tok.SetVal(item->second, strTok);
|
||||
|
||||
if (m_iSynFlags & noVAL) Error(ecUNEXPECTED_VAL, m_iPos - (int)strTok.length(), strTok);
|
||||
if (m_iSynFlags & noVAL)
|
||||
return Error(ecUNEXPECTED_VAL, m_iPos - (int)strTok.length(), strTok);
|
||||
|
||||
m_iSynFlags = noVAL | noVAR | noFUN | noBO | noINFIXOP | noSTR | noASSIGN;
|
||||
return true;
|
||||
|
@ -578,7 +586,8 @@ bool ParserTokenReader::IsValTok(token_type &a_Tok) {
|
|||
// 2013-11-27 Issue 2: https://code.google.com/p/muparser/issues/detail?id=2
|
||||
strTok.assign(m_strFormula.c_str(), iStart, m_iPos - iStart);
|
||||
|
||||
if (m_iSynFlags & noVAL) Error(ecUNEXPECTED_VAL, m_iPos - (int)strTok.length(), strTok);
|
||||
if (m_iSynFlags & noVAL)
|
||||
return Error(ecUNEXPECTED_VAL, m_iPos - (int)strTok.length(), strTok);
|
||||
|
||||
a_Tok.SetVal(fVal, strTok);
|
||||
m_iSynFlags = noVAL | noVAR | noFUN | noBO | noINFIXOP | noSTR | noASSIGN;
|
||||
|
@ -604,7 +613,7 @@ bool ParserTokenReader::IsVarTok(token_type &a_Tok) {
|
|||
varmap_type::const_iterator item = m_pVarDef->find(strTok);
|
||||
if (item == m_pVarDef->end()) return false;
|
||||
|
||||
if (m_iSynFlags & noVAR) Error(ecUNEXPECTED_VAR, m_iPos, strTok);
|
||||
if (m_iSynFlags & noVAR) return Error(ecUNEXPECTED_VAR, m_iPos, strTok);
|
||||
|
||||
m_pParser->OnDetectVar(&m_strFormula, m_iPos, iEnd);
|
||||
|
||||
|
@ -630,7 +639,7 @@ bool ParserTokenReader::IsStrVarTok(token_type &a_Tok) {
|
|||
strmap_type::const_iterator item = m_pStrVarDef->find(strTok);
|
||||
if (item == m_pStrVarDef->end()) return false;
|
||||
|
||||
if (m_iSynFlags & noSTR) Error(ecUNEXPECTED_VAR, m_iPos, strTok);
|
||||
if (m_iSynFlags & noSTR) return Error(ecUNEXPECTED_VAR, m_iPos, strTok);
|
||||
|
||||
m_iPos = iEnd;
|
||||
if (!m_pParser->m_vStringVarBuf.size()) assert(0 && "muParser internal error");
|
||||
|
@ -658,7 +667,7 @@ bool ParserTokenReader::IsUndefVarTok(token_type &a_Tok) {
|
|||
// token identifier.
|
||||
// related bug report:
|
||||
// http://sourceforge.net/tracker/index.php?func=detail&aid=1578779&group_id=137191&atid=737979
|
||||
Error(ecUNEXPECTED_VAR, m_iPos - (int)a_Tok.GetAsString().length(), strTok);
|
||||
return Error(ecUNEXPECTED_VAR, m_iPos - (int)a_Tok.GetAsString().length(), strTok);
|
||||
}
|
||||
|
||||
// If a factory is available implicitely create new variables
|
||||
|
@ -706,11 +715,11 @@ bool ParserTokenReader::IsString(token_type &a_Tok) {
|
|||
iSkip++;
|
||||
}
|
||||
|
||||
if (iEnd == string_type::npos) Error(ecUNTERMINATED_STRING, m_iPos, _T("\""));
|
||||
if (iEnd == string_type::npos) return Error(ecUNTERMINATED_STRING, m_iPos, _T("\""));
|
||||
|
||||
string_type strTok(strBuf.begin(), strBuf.begin() + iEnd);
|
||||
|
||||
if (m_iSynFlags & noSTR) Error(ecUNEXPECTED_STR, m_iPos, strTok);
|
||||
if (m_iSynFlags & noSTR) return Error(ecUNEXPECTED_STR, m_iPos, strTok);
|
||||
|
||||
m_pParser->m_vStringBuf.push_back(strTok); // Store string in internal buffer
|
||||
a_Tok.SetString(strTok, m_pParser->m_vStringBuf.size());
|
||||
|
|
Loading…
Reference in New Issue
Block a user