mirror of
https://github.com/fish-shell/fish-shell
synced 2024-12-27 05:13:10 +00:00
[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:
parent
234808bc32
commit
3faccc8b3e
9 changed files with 1 additions and 409 deletions
|
@ -144,9 +144,7 @@ class ParserBase {
|
|||
void ClearOprt();
|
||||
|
||||
void RemoveVar(const string_type &a_strVarName);
|
||||
const varmap_type &GetUsedVar() const;
|
||||
const varmap_type &GetVar() const;
|
||||
const valmap_type &GetConst() const;
|
||||
const string_type &GetExpr() const;
|
||||
const funmap_type &GetFunDef() const;
|
||||
string_type GetVersion(EParserVersionInfo eInfo = pviFULL) const;
|
||||
|
|
|
@ -195,17 +195,9 @@ API_EXPORT(void) mupClearFun(muParserHandle_t a_hParser);
|
|||
|
||||
// Querying variables / expression variables / constants
|
||||
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)
|
||||
mupGetExprVar(muParserHandle_t a_hParser, unsigned a_iVar, const muChar_t **a_pszName,
|
||||
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) mupSetDecSep(muParserHandle_t a_hParser, const muChar_t cArgSep);
|
||||
API_EXPORT(void) mupSetThousandsSep(muParserHandle_t a_hParser, const muChar_t cArgSep);
|
||||
|
|
|
@ -167,7 +167,6 @@ class ParserTester // final
|
|||
int TestExpression();
|
||||
int TestInfixOprt();
|
||||
int TestBinOprt();
|
||||
int TestVarConst();
|
||||
int TestInterface();
|
||||
int TestException();
|
||||
int TestStrArg();
|
||||
|
|
|
@ -62,7 +62,6 @@ class ParserTokenReader final {
|
|||
|
||||
int GetPos() const;
|
||||
const string_type &GetExpr() const;
|
||||
varmap_type &GetUsedVar();
|
||||
char_type GetArgSep() const;
|
||||
|
||||
void IgnoreUndefVar(bool bIgnore);
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
@ -306,15 +251,6 @@ int CheckKeywords(const mu::char_type *a_szLine, mu::Parser &a_Parser) {
|
|||
|
||||
if (sLine == _T("quit")) {
|
||||
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")) {
|
||||
mu::console() << _T("Setting german locale: ArgSep=';' DecSep=',' ThousandsSep='.'\n");
|
||||
a_Parser.SetArgSep(';');
|
||||
|
|
|
@ -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.
|
||||
\return #m_FunDef
|
||||
|
@ -1510,8 +1480,7 @@ int ParserBase::GetNumResults() const { return m_nFinalResultIdx; }
|
|||
A note on const correctness:
|
||||
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
|
||||
m_UsedVar this is reset during string parsing and accessible from the outside. Instead of making
|
||||
Calc non const GetUsedVar is non const because it explicitly calls Eval() forcing this update.
|
||||
m_UsedVar this is reset during string parsing and accessible from the outside.
|
||||
|
||||
\pre A formula must be set.
|
||||
\pre Variables must have been set (if needed)
|
||||
|
|
|
@ -510,159 +510,6 @@ API_EXPORT(void) mupDefineInfixOprtChars(muParserHandle_t a_hParser, const muCha
|
|||
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) {
|
||||
MU_TRY
|
||||
|
@ -695,52 +542,6 @@ API_EXPORT(void) mupSetThousandsSep(muParserHandle_t a_hParser, const muChar_t c
|
|||
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.
|
||||
*/
|
||||
|
|
|
@ -49,7 +49,6 @@ ParserTester::ParserTester() : m_vTestFun() {
|
|||
AddTest(&ParserTester::TestSyntax);
|
||||
AddTest(&ParserTester::TestPostFix);
|
||||
AddTest(&ParserTester::TestInfixOprt);
|
||||
AddTest(&ParserTester::TestVarConst);
|
||||
AddTest(&ParserTester::TestMultiArg);
|
||||
AddTest(&ParserTester::TestExpression);
|
||||
AddTest(&ParserTester::TestIfThenElse);
|
||||
|
@ -427,103 +426,6 @@ int ParserTester::TestSyntax() {
|
|||
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 iStat = 0;
|
||||
|
|
|
@ -89,10 +89,6 @@ int ParserTokenReader::GetPos() const { return m_iPos; }
|
|||
*/
|
||||
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.
|
||||
|
||||
|
|
Loading…
Reference in a new issue