[muparser] Remove querying variables and constants

fish does not need to query variables and constants from muparser.
This simplifies the code.
This commit is contained in:
ridiculousfish 2017-11-24 18:49:00 -08:00
parent 234808bc32
commit 3faccc8b3e
9 changed files with 1 additions and 409 deletions

View file

@ -144,9 +144,7 @@ class ParserBase {
void ClearOprt(); void ClearOprt();
void RemoveVar(const string_type &a_strVarName); void RemoveVar(const string_type &a_strVarName);
const varmap_type &GetUsedVar() const;
const varmap_type &GetVar() const; const varmap_type &GetVar() const;
const valmap_type &GetConst() const;
const string_type &GetExpr() const; const string_type &GetExpr() const;
const funmap_type &GetFunDef() const; const funmap_type &GetFunDef() const;
string_type GetVersion(EParserVersionInfo eInfo = pviFULL) const; string_type GetVersion(EParserVersionInfo eInfo = pviFULL) const;

View file

@ -195,17 +195,9 @@ API_EXPORT(void) mupClearFun(muParserHandle_t a_hParser);
// Querying variables / expression variables / constants // Querying variables / expression variables / constants
API_EXPORT(int) mupGetExprVarNum(muParserHandle_t a_hParser); API_EXPORT(int) mupGetExprVarNum(muParserHandle_t a_hParser);
API_EXPORT(int) mupGetVarNum(muParserHandle_t a_hParser);
API_EXPORT(int) mupGetConstNum(muParserHandle_t a_hParser);
API_EXPORT(void) API_EXPORT(void)
mupGetExprVar(muParserHandle_t a_hParser, unsigned a_iVar, const muChar_t **a_pszName, mupGetExprVar(muParserHandle_t a_hParser, unsigned a_iVar, const muChar_t **a_pszName,
muFloat_t **a_pVar); muFloat_t **a_pVar);
API_EXPORT(void)
mupGetVar(muParserHandle_t a_hParser, unsigned a_iVar, const muChar_t **a_pszName,
muFloat_t **a_pVar);
API_EXPORT(void)
mupGetConst(muParserHandle_t a_hParser, unsigned a_iVar, const muChar_t **a_pszName,
muFloat_t *a_pVar);
API_EXPORT(void) mupSetArgSep(muParserHandle_t a_hParser, const muChar_t cArgSep); API_EXPORT(void) mupSetArgSep(muParserHandle_t a_hParser, const muChar_t cArgSep);
API_EXPORT(void) mupSetDecSep(muParserHandle_t a_hParser, const muChar_t cArgSep); API_EXPORT(void) mupSetDecSep(muParserHandle_t a_hParser, const muChar_t cArgSep);
API_EXPORT(void) mupSetThousandsSep(muParserHandle_t a_hParser, const muChar_t cArgSep); API_EXPORT(void) mupSetThousandsSep(muParserHandle_t a_hParser, const muChar_t cArgSep);

View file

@ -167,7 +167,6 @@ class ParserTester // final
int TestExpression(); int TestExpression();
int TestInfixOprt(); int TestInfixOprt();
int TestBinOprt(); int TestBinOprt();
int TestVarConst();
int TestInterface(); int TestInterface();
int TestException(); int TestException();
int TestStrArg(); int TestStrArg();

View file

@ -62,7 +62,6 @@ class ParserTokenReader final {
int GetPos() const; int GetPos() const;
const string_type &GetExpr() const; const string_type &GetExpr() const;
varmap_type &GetUsedVar();
char_type GetArgSep() const; char_type GetArgSep() const;
void IgnoreUndefVar(bool bIgnore); void IgnoreUndefVar(bool bIgnore);

View file

@ -243,61 +243,6 @@ void CheckDiff()
} }
*/ */
//---------------------------------------------------------------------------
void ListVar(const mu::ParserBase &parser) {
// Query the used variables (must be done after calc)
mu::varmap_type variables = parser.GetVar();
if (!variables.size()) return;
cout << "\nParser variables:\n";
cout << "-----------------\n";
cout << "Number: " << (int)variables.size() << "\n";
varmap_type::const_iterator item = variables.begin();
for (; item != variables.end(); ++item)
mu::console() << _T("Name: ") << item->first << _T(" Address: [0x") << item->second
<< _T("]\n");
}
//---------------------------------------------------------------------------
void ListConst(const mu::ParserBase &parser) {
mu::console() << _T("\nParser constants:\n");
mu::console() << _T("-----------------\n");
mu::valmap_type cmap = parser.GetConst();
if (!cmap.size()) {
mu::console() << _T("Expression does not contain constants\n");
} else {
valmap_type::const_iterator item = cmap.begin();
for (; item != cmap.end(); ++item)
mu::console() << _T(" ") << item->first << _T(" = ") << item->second << _T("\n");
}
}
//---------------------------------------------------------------------------
void ListExprVar(const mu::ParserBase &parser) {
string_type sExpr = parser.GetExpr();
if (sExpr.length() == 0) {
cout << _T("Expression string is empty\n");
return;
}
// Query the used variables (must be done after calc)
mu::console() << _T("\nExpression variables:\n");
mu::console() << _T("---------------------\n");
mu::console() << _T("Expression: ") << parser.GetExpr() << _T("\n");
varmap_type variables = parser.GetUsedVar();
if (!variables.size()) {
mu::console() << _T("Expression does not contain variables\n");
} else {
mu::console() << _T("Number: ") << (int)variables.size() << _T("\n");
mu::varmap_type::const_iterator item = variables.begin();
for (; item != variables.end(); ++item)
mu::console() << _T("Name: ") << item->first << _T(" Address: [0x") << item->second
<< _T("]\n");
}
}
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
/** \brief Check for external keywords. /** \brief Check for external keywords.
*/ */
@ -306,15 +251,6 @@ int CheckKeywords(const mu::char_type *a_szLine, mu::Parser &a_Parser) {
if (sLine == _T("quit")) { if (sLine == _T("quit")) {
return -1; return -1;
} else if (sLine == _T("list var")) {
ListVar(a_Parser);
return 1;
} else if (sLine == _T("list const")) {
ListConst(a_Parser);
return 1;
} else if (sLine == _T("list exprvar")) {
ListExprVar(a_Parser);
return 1;
} else if (sLine == _T("locale de")) { } else if (sLine == _T("locale de")) {
mu::console() << _T("Setting german locale: ArgSep=';' DecSep=',' ThousandsSep='.'\n"); mu::console() << _T("Setting german locale: ArgSep=';' DecSep=',' ThousandsSep='.'\n");
a_Parser.SetArgSep(';'); a_Parser.SetArgSep(';');

View file

@ -533,36 +533,6 @@ EOprtAssociativity ParserBase::GetOprtAssociativity(const token_type &a_Tok) con
} }
} }
//---------------------------------------------------------------------------
/** \brief Return a map containing the used variables only. */
const varmap_type &ParserBase::GetUsedVar() const {
try {
m_pTokenReader->IgnoreUndefVar(true);
// Try to create bytecode, but don't use it for any further calculations since it may
// contain references to nonexisting variables.
OptionalError oerr = CreateRPN();
if (oerr.has_error()) throw oerr.error();
m_pParseFormula = &ParserBase::ParseString;
m_pTokenReader->IgnoreUndefVar(false);
} catch (exception_type & /*e*/) {
// Make sure to stay in string parse mode, dont call ReInit()
// because it deletes the array with the used variables
m_pParseFormula = &ParserBase::ParseString;
m_pTokenReader->IgnoreUndefVar(false);
throw;
}
return m_pTokenReader->GetUsedVar();
}
//---------------------------------------------------------------------------
/** \brief Return a map containing the used variables only. */
const varmap_type &ParserBase::GetVar() const { return m_VarDef; }
//---------------------------------------------------------------------------
/** \brief Return a map containing all parser constants. */
const valmap_type &ParserBase::GetConst() const { return m_ConstDef; }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
/** \brief Return prototypes of all parser functions. /** \brief Return prototypes of all parser functions.
\return #m_FunDef \return #m_FunDef
@ -1510,8 +1480,7 @@ int ParserBase::GetNumResults() const { return m_nFinalResultIdx; }
A note on const correctness: A note on const correctness:
I consider it important that Calc is a const function. I consider it important that Calc is a const function.
Due to caching operations Calc changes only the state of internal variables with one exception Due to caching operations Calc changes only the state of internal variables with one exception
m_UsedVar this is reset during string parsing and accessible from the outside. Instead of making m_UsedVar this is reset during string parsing and accessible from the outside.
Calc non const GetUsedVar is non const because it explicitly calls Eval() forcing this update.
\pre A formula must be set. \pre A formula must be set.
\pre Variables must have been set (if needed) \pre Variables must have been set (if needed)

View file

@ -510,159 +510,6 @@ API_EXPORT(void) mupDefineInfixOprtChars(muParserHandle_t a_hParser, const muCha
p->DefineInfixOprtChars(a_szCharset); p->DefineInfixOprtChars(a_szCharset);
} }
//---------------------------------------------------------------------------
/** \brief Get the number of variables defined in the parser.
\param a_hParser [in] Must be a valid parser handle.
\return The number of used variables.
\sa mupGetExprVar
*/
API_EXPORT(int) mupGetVarNum(muParserHandle_t a_hParser) {
MU_TRY
muParser_t* const p(AsParser(a_hParser));
const mu::varmap_type VarMap = p->GetVar();
return (int)VarMap.size();
MU_CATCH
return 0; // never reached
}
//---------------------------------------------------------------------------
/** \brief Return a variable that is used in an expression.
\param a_hParser [in] A valid parser handle.
\param a_iVar [in] The index of the variable to return.
\param a_szName [out] Pointer to the variable name.
\param a_pVar [out] Pointer to the variable.
Prior to calling this function call mupGetExprVarNum in order to get the
number of variables in the expression. If the parameter a_iVar is greater
than the number of variables both a_szName and a_pVar will be set to zero.
As a side effect this function will trigger an internal calculation of the
expression undefined variables will be set to zero during this calculation.
During the calculation user defined callback functions present in the expression
will be called, this is unavoidable.
*/
API_EXPORT(void)
mupGetVar(muParserHandle_t a_hParser, unsigned a_iVar, const muChar_t** a_szName,
muFloat_t** a_pVar) {
// A static buffer is needed for the name since i cant return the
// pointer from the map.
static muChar_t szName[1024];
MU_TRY
muParser_t* const p(AsParser(a_hParser));
const mu::varmap_type VarMap = p->GetVar();
if (a_iVar >= VarMap.size()) {
*a_szName = 0;
*a_pVar = 0;
return;
}
mu::varmap_type::const_iterator item;
item = VarMap.begin();
for (unsigned i = 0; i < a_iVar; ++i) ++item;
#ifndef _UNICODE
strncpy(szName, item->first.c_str(), sizeof(szName));
#else
wcsncpy(szName, item->first.c_str(), sizeof(szName));
#endif
szName[sizeof(szName) - 1] = 0;
*a_szName = &szName[0];
*a_pVar = item->second;
return;
MU_CATCH
*a_szName = 0;
*a_pVar = 0;
}
//---------------------------------------------------------------------------
/** \brief Get the number of variables used in the expression currently set in the parser.
\param a_hParser [in] Must be a valid parser handle.
\return The number of used variables.
\sa mupGetExprVar
*/
API_EXPORT(int) mupGetExprVarNum(muParserHandle_t a_hParser) {
MU_TRY
muParser_t* const p(AsParser(a_hParser));
const mu::varmap_type VarMap = p->GetUsedVar();
return (int)VarMap.size();
MU_CATCH
return 0; // never reached
}
//---------------------------------------------------------------------------
/** \brief Return a variable that is used in an expression.
Prior to calling this function call mupGetExprVarNum in order to get the
number of variables in the expression. If the parameter a_iVar is greater
than the number of variables both a_szName and a_pVar will be set to zero.
As a side effect this function will trigger an internal calculation of the
expression undefined variables will be set to zero during this calculation.
During the calculation user defined callback functions present in the expression
will be called, this is unavoidable.
\param a_hParser [in] A valid parser handle.
\param a_iVar [in] The index of the variable to return.
\param a_szName [out] Pointer to the variable name.
\param a_pVar [out] Pointer to the variable.
*/
API_EXPORT(void)
mupGetExprVar(muParserHandle_t a_hParser, unsigned a_iVar, const muChar_t** a_szName,
muFloat_t** a_pVar) {
// A static buffer is needed for the name since i cant return the
// pointer from the map.
static muChar_t szName[1024];
MU_TRY
muParser_t* const p(AsParser(a_hParser));
const mu::varmap_type VarMap = p->GetUsedVar();
if (a_iVar >= VarMap.size()) {
*a_szName = 0;
*a_pVar = 0;
return;
}
mu::varmap_type::const_iterator item;
item = VarMap.begin();
for (unsigned i = 0; i < a_iVar; ++i) ++item;
#ifndef _UNICODE
strncpy(szName, item->first.c_str(), sizeof(szName));
#else
wcsncpy(szName, item->first.c_str(), sizeof(szName));
#endif
szName[sizeof(szName) - 1] = 0;
*a_szName = &szName[0];
*a_pVar = item->second;
return;
MU_CATCH
*a_szName = 0;
*a_pVar = 0;
}
//---------------------------------------------------------------------------
/** \brief Return the number of constants defined in a parser. */
API_EXPORT(int) mupGetConstNum(muParserHandle_t a_hParser) {
MU_TRY
muParser_t* const p(AsParser(a_hParser));
const mu::valmap_type ValMap = p->GetConst();
return (int)ValMap.size();
MU_CATCH
return 0; // never reached
}
//----------------------------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------------------------
API_EXPORT(void) mupSetArgSep(muParserHandle_t a_hParser, const muChar_t cArgSep) { API_EXPORT(void) mupSetArgSep(muParserHandle_t a_hParser, const muChar_t cArgSep) {
MU_TRY MU_TRY
@ -695,52 +542,6 @@ API_EXPORT(void) mupSetThousandsSep(muParserHandle_t a_hParser, const muChar_t c
MU_CATCH MU_CATCH
} }
//---------------------------------------------------------------------------
/** \brief Retrieve name and value of a single parser constant.
\param a_hParser [in] a valid parser handle
\param a_iVar [in] Index of the constant to query
\param a_pszName [out] pointer to a null terminated string with the constant name
\param [out] The constant value
*/
API_EXPORT(void)
mupGetConst(muParserHandle_t a_hParser, unsigned a_iVar, const muChar_t** a_pszName,
muFloat_t* a_fVal) {
// A static buffer is needed for the name since i cant return the
// pointer from the map.
static muChar_t szName[1024];
MU_TRY
muParser_t* const p(AsParser(a_hParser));
const mu::valmap_type ValMap = p->GetConst();
if (a_iVar >= ValMap.size()) {
*a_pszName = 0;
*a_fVal = 0;
return;
}
mu::valmap_type::const_iterator item;
item = ValMap.begin();
for (unsigned i = 0; i < a_iVar; ++i) ++item;
#ifndef _UNICODE
strncpy(szName, item->first.c_str(), sizeof(szName));
#else
wcsncpy(szName, item->first.c_str(), sizeof(szName));
#endif
szName[sizeof(szName) - 1] = 0;
*a_pszName = &szName[0];
*a_fVal = item->second;
return;
MU_CATCH
*a_pszName = 0;
*a_fVal = 0;
}
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
/** \brief Add a custom value recognition function. /** \brief Add a custom value recognition function.
*/ */

View file

@ -49,7 +49,6 @@ ParserTester::ParserTester() : m_vTestFun() {
AddTest(&ParserTester::TestSyntax); AddTest(&ParserTester::TestSyntax);
AddTest(&ParserTester::TestPostFix); AddTest(&ParserTester::TestPostFix);
AddTest(&ParserTester::TestInfixOprt); AddTest(&ParserTester::TestInfixOprt);
AddTest(&ParserTester::TestVarConst);
AddTest(&ParserTester::TestMultiArg); AddTest(&ParserTester::TestMultiArg);
AddTest(&ParserTester::TestExpression); AddTest(&ParserTester::TestExpression);
AddTest(&ParserTester::TestIfThenElse); AddTest(&ParserTester::TestIfThenElse);
@ -427,103 +426,6 @@ int ParserTester::TestSyntax() {
return iStat; return iStat;
} }
//---------------------------------------------------------------------------
int ParserTester::TestVarConst() {
int iStat = 0;
mu::console() << _T("testing variable/constant detection...");
// Test if the result changes when a variable changes
iStat += EqnTestWithVarChange(_T("a"), 1, 1, 2, 2);
iStat += EqnTestWithVarChange(_T("2*a"), 2, 4, 3, 6);
// distinguish constants with same basename
iStat += EqnTest(_T("const"), 1, true);
iStat += EqnTest(_T("const1"), 2, true);
iStat += EqnTest(_T("const2"), 3, true);
iStat += EqnTest(_T("2*const"), 2, true);
iStat += EqnTest(_T("2*const1"), 4, true);
iStat += EqnTest(_T("2*const2"), 6, true);
iStat += EqnTest(_T("2*const+1"), 3, true);
iStat += EqnTest(_T("2*const1+1"), 5, true);
iStat += EqnTest(_T("2*const2+1"), 7, true);
iStat += EqnTest(_T("const"), 0, false);
iStat += EqnTest(_T("const1"), 0, false);
iStat += EqnTest(_T("const2"), 0, false);
// distinguish variables with same basename
iStat += EqnTest(_T("a"), 1, true);
iStat += EqnTest(_T("aa"), 2, true);
iStat += EqnTest(_T("2*a"), 2, true);
iStat += EqnTest(_T("2*aa"), 4, true);
iStat += EqnTest(_T("2*a-1"), 1, true);
iStat += EqnTest(_T("2*aa-1"), 3, true);
// custom value recognition
iStat += EqnTest(_T("0xff"), 255, true);
iStat += EqnTest(_T("0x97 + 0xff"), 406, true);
// Finally test querying of used variables
try {
int idx;
mu::Parser p;
mu::value_type vVarVal[] = {1, 2, 3, 4, 5};
p.DefineVar(_T("a"), &vVarVal[0]);
p.DefineVar(_T("b"), &vVarVal[1]);
p.DefineVar(_T("c"), &vVarVal[2]);
p.DefineVar(_T("d"), &vVarVal[3]);
p.DefineVar(_T("e"), &vVarVal[4]);
// Test lookup of defined variables
// 4 used variables
p.SetExpr(_T("a+b+c+d"));
mu::varmap_type UsedVar = p.GetUsedVar();
int iCount = (int)UsedVar.size();
if (iCount != 4) throw false;
// the next check will fail if the parser
// erroneously creates new variables internally
if (p.GetVar().size() != 5) 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(_T("undef1+undef2+undef3"));
UsedVar = p.GetUsedVar();
iCount = (int)UsedVar.size();
if (iCount != 3) throw false;
// the next check will fail if the parser
// erroneously creates new variables internally
if (p.GetVar().size() != 5) 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(_T("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)
mu::console() << _T("passed") << endl;
else
mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl;
return iStat;
}
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
int ParserTester::TestMultiArg() { int ParserTester::TestMultiArg() {
int iStat = 0; int iStat = 0;

View file

@ -89,10 +89,6 @@ int ParserTokenReader::GetPos() const { return m_iPos; }
*/ */
const string_type &ParserTokenReader::GetExpr() const { return m_strFormula; } const string_type &ParserTokenReader::GetExpr() const { return m_strFormula; }
//---------------------------------------------------------------------------
/** \brief Return a map containing the used variables only. */
varmap_type &ParserTokenReader::GetUsedVar() { return m_UsedVar; }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
/** \brief Initialize the token Reader. /** \brief Initialize the token Reader.