40 #pragma warning(disable : 26812)
72 ParserTokenReader& ParserTokenReader::operator=(
const ParserTokenReader& a_Reader)
74 if (&a_Reader !=
this)
86 void ParserTokenReader::Assign(
const ParserTokenReader& a_Reader)
88 m_pParser = a_Reader.m_pParser;
89 m_strFormula = a_Reader.m_strFormula;
90 m_iPos = a_Reader.m_iPos;
91 m_iSynFlags = a_Reader.m_iSynFlags;
93 m_UsedVar = a_Reader.m_UsedVar;
94 m_pFunDef = a_Reader.m_pFunDef;
95 m_pConstDef = a_Reader.m_pConstDef;
96 m_pVarDef = a_Reader.m_pVarDef;
97 m_pStrVarDef = a_Reader.m_pStrVarDef;
98 m_pPostOprtDef = a_Reader.m_pPostOprtDef;
99 m_pInfixOprtDef = a_Reader.m_pInfixOprtDef;
100 m_pOprtDef = a_Reader.m_pOprtDef;
101 m_bIgnoreUndefVar = a_Reader.m_bIgnoreUndefVar;
102 m_vIdentFun = a_Reader.m_vIdentFun;
103 m_pFactory = a_Reader.m_pFactory;
104 m_pFactoryData = a_Reader.m_pFactoryData;
105 m_bracketStack = a_Reader.m_bracketStack;
106 m_cArgSep = a_Reader.m_cArgSep;
107 m_fZero = a_Reader.m_fZero;
108 m_lastTok = a_Reader.m_lastTok;
121 :m_pParser(a_pParent)
125 , m_bIgnoreUndefVar(false)
127 , m_pPostOprtDef(nullptr)
128 , m_pInfixOprtDef(nullptr)
129 , m_pOprtDef(nullptr)
130 , m_pConstDef(nullptr)
131 , m_pStrVarDef(nullptr)
133 , m_pFactory(nullptr)
134 , m_pFactoryData(nullptr)
143 SetParent(m_pParser);
158 ptr->SetParent(a_pParent);
159 return ptr.release();
170 void ParserTokenReader::AddValIdent(
identfun_type a_pCallback)
178 m_vIdentFun.push_front(a_pCallback);
182 void ParserTokenReader::SetVarCreator(
facfun_type a_pFactory,
void* pUserData)
184 m_pFactory = a_pFactory;
185 m_pFactoryData = pUserData;
225 m_strFormula = a_strFormula;
240 m_bIgnoreUndefVar = bIgnore;
255 m_iSynFlags = sfSTART_OF_LINE;
256 m_bracketStack = std::stack<int>();
267 const char_type* szExpr = m_strFormula.c_str();
271 while (szExpr[m_iPos] > 0 && szExpr[m_iPos] <= 0x20)
275 if (szExpr[m_iPos] >= 14 && szExpr[m_iPos] <= 31)
283 return SaveBeforeReturn(tok);
287 return SaveBeforeReturn(tok);
291 return SaveBeforeReturn(tok);
295 return SaveBeforeReturn(tok);
299 return SaveBeforeReturn(tok);
303 return SaveBeforeReturn(tok);
307 return SaveBeforeReturn(tok);
310 if (IsStrVarTok(tok))
311 return SaveBeforeReturn(tok);
315 return SaveBeforeReturn(tok);
318 if (IsInfixOpTok(tok))
319 return SaveBeforeReturn(tok);
322 if (IsPostOpTok(tok))
323 return SaveBeforeReturn(tok);
332 if ((m_bIgnoreUndefVar || m_pFactory) && IsUndefVarTok(tok))
333 return SaveBeforeReturn(tok);
340 auto iEnd = ExtractToken(m_pParser->
ValidNameChars(), strTok, (std::size_t)m_iPos);
349 void ParserTokenReader::SetParent(
ParserBase* a_pParent)
351 m_pParser = a_pParent;
352 m_pFunDef = &a_pParent->m_FunDef;
353 m_pOprtDef = &a_pParent->m_OprtDef;
354 m_pInfixOprtDef = &a_pParent->m_InfixOprtDef;
355 m_pPostOprtDef = &a_pParent->m_PostOprtDef;
356 m_pVarDef = &a_pParent->m_VarDef;
357 m_pStrVarDef = &a_pParent->m_StrVarDef;
358 m_pConstDef = &a_pParent->m_ConstDef;
370 int ParserTokenReader::ExtractToken(
const char_type* a_szCharSet,
string_type& a_sTok, std::size_t a_iPos)
const
372 auto iEnd = m_strFormula.find_first_not_of(a_szCharSet, a_iPos);
374 if (iEnd == string_type::npos)
375 iEnd = m_strFormula.length();
379 a_sTok =
string_type(m_strFormula.begin() + a_iPos, m_strFormula.begin() + iEnd);
381 return static_cast<int>(iEnd);
392 int ParserTokenReader::ExtractOperatorToken(
string_type& a_sTok, std::size_t a_iPos)
const
395 auto iEnd = m_strFormula.find_first_not_of(m_pParser->
ValidOprtChars(), a_iPos);
396 if (iEnd == string_type::npos)
397 iEnd = m_strFormula.length();
402 a_sTok =
string_type(m_strFormula.begin() + a_iPos, m_strFormula.begin() + iEnd);
403 return static_cast<int>(iEnd);
409 return ExtractToken(
_T(
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"), a_sTok, (std::size_t)a_iPos);
418 bool ParserTokenReader::IsBuiltIn(token_type& a_Tok)
421 *
const szFormula = m_strFormula.c_str();
425 for (
int i = 0; pOprtDef[i]; i++)
427 std::size_t len(std::char_traits<char_type>::length(pOprtDef[i]));
447 if (i ==
cmASSIGN && m_iSynFlags & noASSIGN)
451 if (m_iSynFlags & noOPT)
456 if (IsInfixOpTok(a_Tok))
462 m_iSynFlags = noBC | noOPT | noARG_SEP | noPOSTOP | noASSIGN | noIF | noELSE | noEND;
466 if (m_iSynFlags & noBO)
470 m_iSynFlags = noOPT | noEND | noARG_SEP | noPOSTOP | noASSIGN | noIF | noELSE;
472 m_iSynFlags = noBC | noOPT | noEND | noARG_SEP | noPOSTOP | noASSIGN | noIF | noELSE;
474 m_bracketStack.push(
cmBO);
478 if (m_iSynFlags & noBC)
481 m_iSynFlags = noBO | noVAR | noVAL | noFUN | noINFIXOP | noSTR | noASSIGN;
483 if (!m_bracketStack.empty())
484 m_bracketStack.pop();
490 if (m_iSynFlags & noELSE)
491 Error(ecUNEXPECTED_CONDITIONAL, m_iPos, pOprtDef[i]);
493 m_iSynFlags = noBC | noPOSTOP | noEND | noOPT | noIF | noELSE | noSTR;
497 if (m_iSynFlags & noIF)
498 Error(ecUNEXPECTED_CONDITIONAL, m_iPos, pOprtDef[i]);
500 m_iSynFlags = noBC | noPOSTOP | noEND | noOPT | noIF | noELSE | noSTR;
508 a_Tok.Set((
ECmdCode)i, pOprtDef[i]);
517 bool ParserTokenReader::IsArgSep(token_type& a_Tok)
519 const char_type* szFormula = m_strFormula.c_str();
521 if (szFormula[m_iPos] == m_cArgSep)
525 szSep[0] = m_cArgSep;
528 if (m_iSynFlags & noARG_SEP)
531 m_iSynFlags = noBC | noOPT | noEND | noARG_SEP | noPOSTOP | noASSIGN;
548 bool ParserTokenReader::IsEOF(token_type& a_Tok)
550 const char_type* szFormula = m_strFormula.c_str();
553 if (!szFormula[m_iPos] )
555 if (m_iSynFlags & noEND)
558 if (!m_bracketStack.empty())
573 bool ParserTokenReader::IsInfixOpTok(token_type& a_Tok)
581 funmap_type::const_reverse_iterator it = m_pInfixOprtDef->rbegin();
582 for (; it != m_pInfixOprtDef->rend(); ++it)
584 if (sTok.find(it->first) != 0)
587 a_Tok.Set(it->second, it->first);
588 m_iPos += (int)it->first.length();
590 if (m_iSynFlags & noINFIXOP)
593 m_iSynFlags = noPOSTOP | noINFIXOP | noOPT | noBC | noSTR | noASSIGN | noARG_SEP;
618 bool ParserTokenReader::IsFunTok(token_type& a_Tok)
621 auto iEnd = ExtractToken(m_pParser->
ValidNameChars(), strTok, (std::size_t)m_iPos);
625 funmap_type::const_iterator item = m_pFunDef->find(strTok);
626 if (item == m_pFunDef->end())
630 const char_type* szFormula = m_strFormula.c_str();
631 if (szFormula[iEnd] !=
'(')
634 a_Tok.Set(item->second, strTok);
637 if (m_iSynFlags & noFUN)
638 Error(
ecUNEXPECTED_FUN, m_iPos - (
int)a_Tok.GetAsString().length(), a_Tok.GetAsString());
640 m_iSynFlags = noANY ^ noBO;
649 bool ParserTokenReader::IsOprt(token_type& a_Tok)
651 const char_type*
const szExpr = m_strFormula.c_str();
654 auto iEnd = ExtractOperatorToken(strTok, (std::size_t)m_iPos);
672 funmap_type::const_reverse_iterator it = m_pOprtDef->rbegin();
673 for (; it != m_pOprtDef->rend(); ++it)
676 if (sID ==
string_type(szExpr + m_iPos, szExpr + m_iPos + sID.length()))
678 a_Tok.Set(it->second, strTok);
681 if (m_iSynFlags & noOPT)
687 if (IsInfixOpTok(a_Tok))
698 m_iPos += (int)sID.length();
699 m_iSynFlags = noBC | noOPT | noARG_SEP | noPOSTOP | noEND | noASSIGN;
709 bool ParserTokenReader::IsPostOpTok(token_type& a_Tok)
718 if (m_iSynFlags & noPOSTOP)
732 auto iEnd = ExtractToken(m_pParser->
ValidOprtChars(), sTok, (std::size_t)m_iPos);
737 funmap_type::const_reverse_iterator it = m_pPostOprtDef->rbegin();
738 for (; it != m_pPostOprtDef->rend(); ++it)
740 if (sTok.find(it->first) != 0)
743 a_Tok.Set(it->second, sTok);
744 m_iPos += (int)it->first.length();
746 m_iSynFlags = noVAL | noVAR | noFUN | noBO | noPOSTOP | noSTR | noASSIGN;
761 bool ParserTokenReader::IsValTok(token_type& a_Tok)
771 auto iEnd = ExtractToken(m_pParser->
ValidNameChars(), strTok, (std::size_t)m_iPos);
774 valmap_type::const_iterator item = m_pConstDef->find(strTok);
775 if (item != m_pConstDef->end())
778 a_Tok.SetVal(item->second, strTok);
780 if (m_iSynFlags & noVAL)
783 m_iSynFlags = noVAL | noVAR | noFUN | noBO | noINFIXOP | noSTR | noASSIGN;
790 std::list<identfun_type>::const_iterator item = m_vIdentFun.begin();
791 for (item = m_vIdentFun.begin(); item != m_vIdentFun.end(); ++item)
794 if ((*item)(m_strFormula.c_str() + m_iPos, &m_iPos, &fVal) == 1)
797 strTok.assign(m_strFormula.c_str(), iStart, (std::size_t)m_iPos - iStart);
799 if (m_iSynFlags & noVAL)
802 a_Tok.SetVal(fVal, strTok);
803 m_iSynFlags = noVAL | noVAR | noFUN | noBO | noINFIXOP | noSTR | noASSIGN;
816 bool ParserTokenReader::IsVarTok(token_type& a_Tok)
818 if (m_pVarDef->empty())
822 auto iEnd = ExtractToken(m_pParser->
ValidNameChars(), strTok, (std::size_t)m_iPos);
826 varmap_type::const_iterator item = m_pVarDef->find(strTok);
827 if (item == m_pVarDef->end())
830 if (m_iSynFlags & noVAR)
833 m_pParser->OnDetectVar(&m_strFormula, m_iPos, iEnd);
836 a_Tok.SetVar(item->second, strTok);
837 m_UsedVar[item->first] = item->second;
839 m_iSynFlags = noVAL | noVAR | noFUN | noBO | noINFIXOP | noSTR;
847 bool ParserTokenReader::IsStrVarTok(token_type& a_Tok)
849 if (!m_pStrVarDef || m_pStrVarDef->empty())
853 auto iEnd = ExtractToken(m_pParser->
ValidNameChars(), strTok, (std::size_t)m_iPos);
857 strmap_type::const_iterator item = m_pStrVarDef->find(strTok);
858 if (item == m_pStrVarDef->end())
861 if (m_iSynFlags & noSTR)
865 if (!m_pParser->m_vStringVarBuf.size())
868 a_Tok.SetString(m_pParser->m_vStringVarBuf[item->second], m_pParser->m_vStringVarBuf.size());
870 m_iSynFlags = noANY ^ (noBC | noOPT | noEND | noARG_SEP);
882 bool ParserTokenReader::IsUndefVarTok(token_type& a_Tok)
885 auto iEnd(ExtractToken(m_pParser->
ValidNameChars(), strTok, (std::size_t)m_iPos));
889 if (m_iSynFlags & noVAR)
895 Error(
ecUNEXPECTED_VAR, m_iPos - (
int)a_Tok.GetAsString().length(), strTok);
901 value_type* fVar = m_pFactory(strTok.c_str(), m_pFactoryData);
902 a_Tok.SetVar(fVar, strTok);
910 (*m_pVarDef)[strTok] = fVar;
911 m_UsedVar[strTok] = fVar;
916 m_UsedVar[strTok] = 0;
922 m_iSynFlags = noVAL | noVAR | noFUN | noBO | noPOSTOP | noINFIXOP | noSTR;
934 bool ParserTokenReader::IsString(token_type& a_Tok)
936 if (m_strFormula[m_iPos] !=
'"')
939 string_type strBuf(&m_strFormula[(std::size_t)m_iPos + 1]);
940 std::size_t iEnd(0), iSkip(0);
943 for (iEnd = (
int)strBuf.find(
_T(
'\"')); iEnd != 0 && iEnd != string_type::npos; iEnd = (int)strBuf.find(
_T(
'\"'), iEnd))
945 if (strBuf[iEnd - 1] !=
'\\')
break;
946 strBuf.replace(iEnd - 1, 2,
_T(
"\""));
950 if (iEnd == string_type::npos)
953 string_type strTok(strBuf.begin(), strBuf.begin() + iEnd);
955 if (m_iSynFlags & noSTR)
958 m_pParser->m_vStringBuf.push_back(strTok);
959 a_Tok.SetString(strTok, m_pParser->m_vStringBuf.size());
961 m_iPos += (int)strTok.length() + 2 + (int)iSkip;
962 m_iSynFlags = noANY ^ (noARG_SEP | noBC | noOPT | noEND);
979 m_pParser->
Error(a_iErrc, a_iPos, a_sTok);
983 void ParserTokenReader::SetArgSep(
char_type cArgSep)
989 char_type ParserTokenReader::GetArgSep()
const
995 #if defined(_MSC_VER)
Operator item: closing bracket.
void IgnoreUndefVar(bool bIgnore)
Set Flag that controls behaviour in case of undefined variables being found.
#define _T(x)
Activate this option in order to compile with OpenMP support.
value_type *(* facfun_type)(const char_type *, void *)
Callback used for variable creation factory functions.
An unexpected comma has been found. (Example: "1,23")
Token can't be identified.
std::map< string_type, value_type * > varmap_type
Type used for storing variables.
function argument separator
Operator item: y to the power of ...
Internal error of any kind.
unterminated string constant. (Example: "3*valueof("hello)")
Operator item: not equal.
For use in the ternary if-then-else operator.
const char_type * ValidInfixOprtChars() const
Virtual function that defines the characters allowed in infix operator definitions.
const char_type * ValidOprtChars() const
Virtual function that defines the characters allowed in operator definitions.
varmap_type & GetUsedVar()
Return a map containing the used variables only.
int GetPos() const
Return the current position of the token reader in the formula string.
Unexpected function found. (Example: "sin(8)cos(9)")
ParserTokenReader(ParserBase *a_pParent)
Constructor.
bool HasBuiltInOprt() const
Query status of built in variables.
Code for a generic function item.
const char_type * ValidNameChars() const
Virtual function that defines the characters allowed in name identifiers.
An unexpected value token has been found.
This file contains the parser token reader definition.
For use in the ternary if-then-else operator.
An unexpected variable token has been found.
token_type ReadNextToken()
Read the next token from the string.
This file contains the class definition of the muparser engine.
void ReInit()
Reset the token reader to the start of the formula.
#define MUP_ASSERT(COND)
An assertion that does not kill the program.
MUP_BASETYPE value_type
The numeric datatype used by the parser.
void SetFormula(const string_type &a_strFormula)
Initialize the token Reader.
ECmdCode GetCode() const
Return the token type.
Namespace for mathematical applications.
Unexpected end of formula. (Example: "2+sin(")
Operator item: less than.
int(* identfun_type)(const char_type *sExpr, int *nPos, value_type *fVal)
Callback used for functions that identify values in a string.
Operator item: greater than.
const char_type ** GetOprtDef() const
Get the default symbols used for the built in operators.
string_type::value_type char_type
The character type used by the parser.
Token reader for the ParserBase class.
ParserTokenReader * Clone(ParserBase *a_pParent) const
Create instance of a ParserTokenReader identical with this and return its pointer.
Operator item: Assignment operator.
Unexpected binary operator found.
MUP_STRING_TYPE string_type
The stringtype used by the parser.
Operator item: less or equal.
Unexpected Parenthesis, opening or closing.
Operator item: greater or equal.
The expression or identifier contains invalid non printable characters.
void Error(EErrorCodes a_iErrc, int a_iPos=static_cast< int >(mu::string_type::npos), const string_type &a_strTok=string_type()) const
Create an error containing the parse error position.
Missing parens. (Example: "3*sin(3")
const string_type & GetExpr() const
Return a reference to the formula.
A string has been found at an inapropriate position.
Mathematical expressions parser (base parser engine).
Operator item: opening bracket.