muParser API -  1.35
muParserError.cpp
1 /*
2 
3  _____ __ _____________ _______ ______ ___________
4  / \| | \____ \__ \\_ __ \/ ___// __ \_ __ \
5  | Y Y \ | / |_> > __ \| | \/\___ \\ ___/| | \/
6  |__|_| /____/| __(____ /__| /____ >\___ >__|
7  \/ |__| \/ \/ \/
8  Copyright (C) 2004 - 2022 Ingo Berg
9 
10  Redistribution and use in source and binary forms, with or without modification, are permitted
11  provided that the following conditions are met:
12 
13  * Redistributions of source code must retain the above copyright notice, this list of
14  conditions and the following disclaimer.
15  * Redistributions in binary form must reproduce the above copyright notice, this list of
16  conditions and the following disclaimer in the documentation and/or other materials provided
17  with the distribution.
18 
19  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
20  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
21  FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
22  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25  IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
26  OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28 
29 #include "muParserError.h"
30 #include <exception>
31 
32 #if defined(_MSC_VER)
33  #pragma warning(push)
34  #pragma warning(disable : 26812) // MSVC wants to force me te use enum classes or bother me with pointless warnings
35 #endif
36 
37 namespace mu
38 {
39  //------------------------------------------------------------------------------
40  const ParserErrorMsg& ParserErrorMsg::Instance()
41  {
42  static const ParserErrorMsg instance;
43  return instance;
44  }
45 
46  //------------------------------------------------------------------------------
47  string_type ParserErrorMsg::operator[](unsigned a_iIdx) const
48  {
49  return (a_iIdx < m_vErrMsg.size()) ? m_vErrMsg[a_iIdx] : string_type();
50  }
51 
52  //---------------------------------------------------------------------------
53  ParserErrorMsg::ParserErrorMsg()
54  :m_vErrMsg(0)
55  {
56  m_vErrMsg.resize(ecCOUNT);
57 
58  m_vErrMsg[ecUNASSIGNABLE_TOKEN] = _T("Unexpected token \"$TOK$\" found at position $POS$.");
59  m_vErrMsg[ecINTERNAL_ERROR] = _T("Internal error");
60  m_vErrMsg[ecINVALID_NAME] = _T("Invalid function-, variable- or constant name: \"$TOK$\".");
61  m_vErrMsg[ecINVALID_BINOP_IDENT] = _T("Invalid binary operator identifier: \"$TOK$\".");
62  m_vErrMsg[ecINVALID_INFIX_IDENT] = _T("Invalid infix operator identifier: \"$TOK$\".");
63  m_vErrMsg[ecINVALID_POSTFIX_IDENT] = _T("Invalid postfix operator identifier: \"$TOK$\".");
64  m_vErrMsg[ecINVALID_FUN_PTR] = _T("Invalid pointer to callback function.");
65  m_vErrMsg[ecEMPTY_EXPRESSION] = _T("Expression is empty.");
66  m_vErrMsg[ecINVALID_VAR_PTR] = _T("Invalid pointer to variable.");
67  m_vErrMsg[ecUNEXPECTED_OPERATOR] = _T("Unexpected operator \"$TOK$\" found at position $POS$");
68  m_vErrMsg[ecUNEXPECTED_EOF] = _T("Unexpected end of expression at position $POS$");
69  m_vErrMsg[ecUNEXPECTED_ARG_SEP] = _T("Unexpected argument separator at position $POS$");
70  m_vErrMsg[ecUNEXPECTED_PARENS] = _T("Unexpected parenthesis \"$TOK$\" at position $POS$");
71  m_vErrMsg[ecUNEXPECTED_FUN] = _T("Unexpected function \"$TOK$\" at position $POS$");
72  m_vErrMsg[ecUNEXPECTED_VAL] = _T("Unexpected value \"$TOK$\" found at position $POS$");
73  m_vErrMsg[ecUNEXPECTED_VAR] = _T("Unexpected variable \"$TOK$\" found at position $POS$");
74  m_vErrMsg[ecUNEXPECTED_ARG] = _T("Function arguments used without a function (position: $POS$)");
75  m_vErrMsg[ecMISSING_PARENS] = _T("Missing parenthesis");
76  m_vErrMsg[ecTOO_MANY_PARAMS] = _T("Too many parameters for function \"$TOK$\" at expression position $POS$");
77  m_vErrMsg[ecTOO_FEW_PARAMS] = _T("Too few parameters for function \"$TOK$\" at expression position $POS$");
78  m_vErrMsg[ecDIV_BY_ZERO] = _T("Divide by zero");
79  m_vErrMsg[ecDOMAIN_ERROR] = _T("Domain error");
80  m_vErrMsg[ecNAME_CONFLICT] = _T("Name conflict");
81  m_vErrMsg[ecOPT_PRI] = _T("Invalid value for operator priority (must be greater or equal to zero).");
82  m_vErrMsg[ecBUILTIN_OVERLOAD] = _T("user defined binary operator \"$TOK$\" conflicts with a built in operator.");
83  m_vErrMsg[ecUNEXPECTED_STR] = _T("Unexpected string token found at position $POS$.");
84  m_vErrMsg[ecUNTERMINATED_STRING] = _T("Unterminated string starting at position $POS$.");
85  m_vErrMsg[ecSTRING_EXPECTED] = _T("String function called with a non string type of argument.");
86  m_vErrMsg[ecVAL_EXPECTED] = _T("String value used where a numerical argument is expected.");
87  m_vErrMsg[ecOPRT_TYPE_CONFLICT] = _T("No suitable overload for operator \"$TOK$\" at position $POS$.");
88  m_vErrMsg[ecSTR_RESULT] = _T("Strings must only be used as function arguments!");
89  m_vErrMsg[ecGENERIC] = _T("Parser error.");
90  m_vErrMsg[ecLOCALE] = _T("Decimal separator is identic to function argument separator.");
91  m_vErrMsg[ecUNEXPECTED_CONDITIONAL] = _T("The \"$TOK$\" operator must be preceded by a closing bracket.");
92  m_vErrMsg[ecMISSING_ELSE_CLAUSE] = _T("If-then-else operator is missing an else clause");
93  m_vErrMsg[ecMISPLACED_COLON] = _T("Misplaced colon at position $POS$");
94  m_vErrMsg[ecUNREASONABLE_NUMBER_OF_COMPUTATIONS] = _T("Number of computations to small for bulk mode. (Vectorisation overhead too costly)");
95  m_vErrMsg[ecIDENTIFIER_TOO_LONG] = _T("Identifier too long.");
96  m_vErrMsg[ecEXPRESSION_TOO_LONG] = _T("Expression too long.");
97  m_vErrMsg[ecINVALID_CHARACTERS_FOUND] = _T("Invalid non printable characters found in expression/identifer!");
98  m_vErrMsg[ecBYTECODE_IMPORT_EXPORT_DISABLED] = _T("Bytecode cannot be imported or exported when parser is using a variable factory!");
99 
100  for (int i = 0; i < ecCOUNT; ++i)
101  {
102  if (!m_vErrMsg[i].length())
103  throw std::runtime_error("Error definitions are incomplete!");
104  }
105  }
106 
107  //---------------------------------------------------------------------------
108  //
109  // ParserError class
110  //
111  //---------------------------------------------------------------------------
112 
113  /** \brief Default constructor. */
114  ParserError::ParserError()
115  :m_strMsg()
116  , m_strFormula()
117  , m_strTok()
118  , m_iPos(-1)
119  , m_iErrc(ecUNDEFINED)
120  , m_ErrMsg(ParserErrorMsg::Instance())
121  {
122  }
123 
124  //------------------------------------------------------------------------------
125  /** \brief This Constructor is used for internal exceptions only.
126 
127  It does not contain any information but the error code.
128  */
130  :m_strMsg()
131  , m_strFormula()
132  , m_strTok()
133  , m_iPos(-1)
134  , m_iErrc(a_iErrc)
135  , m_ErrMsg(ParserErrorMsg::Instance())
136  {
137  m_strMsg = m_ErrMsg[m_iErrc];
138  stringstream_type stream;
139  stream << (int)m_iPos;
140  ReplaceSubString(m_strMsg, _T("$POS$"), stream.str());
141  ReplaceSubString(m_strMsg, _T("$TOK$"), m_strTok);
142  }
143 
144  //------------------------------------------------------------------------------
145  /** \brief Construct an error from a message text. */
147  :m_ErrMsg(ParserErrorMsg::Instance())
148  {
149  Reset();
150  m_strMsg = sMsg;
151  }
152 
153  //------------------------------------------------------------------------------
154  /** \brief Construct an error object.
155  \param [in] a_iErrc the error code.
156  \param [in] sTok The token string related to this error.
157  \param [in] sExpr The expression related to the error.
158  \param [in] a_iPos the position in the expression where the error occurred.
159  */
161  const string_type& sTok,
162  const string_type& sExpr,
163  int iPos)
164  :m_strMsg()
165  , m_strFormula(sExpr)
166  , m_strTok(sTok)
167  , m_iPos(iPos)
168  , m_iErrc(iErrc)
169  , m_ErrMsg(ParserErrorMsg::Instance())
170  {
171  m_strMsg = m_ErrMsg[m_iErrc];
172  stringstream_type stream;
173  stream << (int)m_iPos;
174  ReplaceSubString(m_strMsg, _T("$POS$"), stream.str());
175  ReplaceSubString(m_strMsg, _T("$TOK$"), m_strTok);
176  }
177 
178  //------------------------------------------------------------------------------
179  /** \brief Construct an error object.
180  \param [in] iErrc the error code.
181  \param [in] iPos the position in the expression where the error occurred.
182  \param [in] sTok The token string related to this error.
183  */
184  ParserError::ParserError(EErrorCodes iErrc, int iPos, const string_type& sTok)
185  :m_strMsg()
186  , m_strFormula()
187  , m_strTok(sTok)
188  , m_iPos(iPos)
189  , m_iErrc(iErrc)
190  , m_ErrMsg(ParserErrorMsg::Instance())
191  {
192  m_strMsg = m_ErrMsg[m_iErrc];
193  stringstream_type stream;
194  stream << (int)m_iPos;
195  ReplaceSubString(m_strMsg, _T("$POS$"), stream.str());
196  ReplaceSubString(m_strMsg, _T("$TOK$"), m_strTok);
197  }
198 
199  //------------------------------------------------------------------------------
200  /** \brief Construct an error object.
201  \param [in] szMsg The error message text.
202  \param [in] iPos the position related to the error.
203  \param [in] sTok The token string related to this error.
204  */
205  ParserError::ParserError(const char_type* szMsg, int iPos, const string_type& sTok)
206  :m_strMsg(szMsg)
207  , m_strFormula()
208  , m_strTok(sTok)
209  , m_iPos(iPos)
210  , m_iErrc(ecGENERIC)
211  , m_ErrMsg(ParserErrorMsg::Instance())
212  {
213  stringstream_type stream;
214  stream << (int)m_iPos;
215  ReplaceSubString(m_strMsg, _T("$POS$"), stream.str());
216  ReplaceSubString(m_strMsg, _T("$TOK$"), m_strTok);
217  }
218 
219  //------------------------------------------------------------------------------
220  /** \brief Copy constructor. */
222  :m_strMsg(a_Obj.m_strMsg)
223  , m_strFormula(a_Obj.m_strFormula)
224  , m_strTok(a_Obj.m_strTok)
225  , m_iPos(a_Obj.m_iPos)
226  , m_iErrc(a_Obj.m_iErrc)
227  , m_ErrMsg(ParserErrorMsg::Instance())
228  {
229  }
230 
231  //------------------------------------------------------------------------------
232  /** \brief Assignment operator. */
234  {
235  if (this == &a_Obj)
236  return *this;
237 
238  m_strMsg = a_Obj.m_strMsg;
239  m_strFormula = a_Obj.m_strFormula;
240  m_strTok = a_Obj.m_strTok;
241  m_iPos = a_Obj.m_iPos;
242  m_iErrc = a_Obj.m_iErrc;
243  return *this;
244  }
245 
246  //------------------------------------------------------------------------------
247  ParserError::~ParserError()
248  {}
249 
250  //------------------------------------------------------------------------------
251  /** \brief Replace all occurrences of a substring with another string.
252  \param strFind The string that shall be replaced.
253  \param strReplaceWith The string that should be inserted instead of strFind
254  */
255  void ParserError::ReplaceSubString(string_type& strSource,
256  const string_type& strFind,
257  const string_type& strReplaceWith)
258  {
259  string_type strResult;
260  string_type::size_type iPos(0), iNext(0);
261 
262  for (;;)
263  {
264  iNext = strSource.find(strFind, iPos);
265  strResult.append(strSource, iPos, iNext - iPos);
266 
267  if (iNext == string_type::npos)
268  break;
269 
270  strResult.append(strReplaceWith);
271  iPos = iNext + strFind.length();
272  }
273 
274  strSource.swap(strResult);
275  }
276 
277  //------------------------------------------------------------------------------
278  /** \brief Reset the error object. */
279  void ParserError::Reset()
280  {
281  m_strMsg = _T("");
282  m_strFormula = _T("");
283  m_strTok = _T("");
284  m_iPos = -1;
285  m_iErrc = ecUNDEFINED;
286  }
287 
288  //------------------------------------------------------------------------------
289  /** \brief Set the expression related to this error. */
290  void ParserError::SetFormula(const string_type& a_strFormula)
291  {
292  m_strFormula = a_strFormula;
293  }
294 
295  //------------------------------------------------------------------------------
296  /** \brief gets the expression related tp this error.*/
298  {
299  return m_strFormula;
300  }
301 
302  //------------------------------------------------------------------------------
303  /** \brief Returns the message string for this error. */
305  {
306  return m_strMsg;
307  }
308 
309  //------------------------------------------------------------------------------
310  /** \brief Return the formula position related to the error.
311 
312  If the error is not related to a distinct position this will return -1
313  */
315  {
316  return m_iPos;
317  }
318 
319  //------------------------------------------------------------------------------
320  /** \brief Return string related with this token (if available). */
322  {
323  return m_strTok;
324  }
325 
326  //------------------------------------------------------------------------------
327  /** \brief Return the error code. */
329  {
330  return m_iErrc;
331  }
332 } // namespace mu
333 
334 #if defined(_MSC_VER)
335  #pragma warning(pop)
336 #endif
A class that handles the error messages.
Definition: muParserError.h:53
#define _T(x)
Activate this option in order to compile with OpenMP support.
Definition: muParserDef.h:69
const string_type & GetExpr() const
gets the expression related tp this error.
binary operators may only be applied to value items of the same type
Definition: muParserDef.h:245
An unexpected comma has been found. (Example: "1,23")
Definition: muParserDef.h:232
Token can't be identified.
Definition: muParserDef.h:230
result is a string
Definition: muParserDef.h:246
An unexpected argument has been found.
Definition: muParserDef.h:233
Division by zero (currently unused)
Definition: muParserDef.h:262
Throw an exception if the expression has more than 10000 characters. (an arbitrary limit) ...
Definition: muParserDef.h:274
Name conflict.
Definition: muParserDef.h:258
Internal error of any kind.
Definition: muParserDef.h:279
unterminated string constant. (Example: "3*valueof("hello)")
Definition: muParserDef.h:242
Trying to overload builtin operator.
Definition: muParserDef.h:254
Undefined message, placeholder to detect unassigned error messages.
Definition: muParserDef.h:285
Unexpected function found. (Example: "sin(8)cos(9)")
Definition: muParserDef.h:241
std::basic_stringstream< char_type, std::char_traits< char_type >, std::allocator< char_type > > stringstream_type
Typedef for easily using stringstream that respect the parser stringtype.
Definition: muParserDef.h:311
This is no error code, It just stores just the total number of error codes.
Definition: muParserDef.h:284
An unexpected value token has been found.
Definition: muParserDef.h:234
Conflict with current locale.
Definition: muParserDef.h:264
catch division by zero, sqrt(-1), log(0) (currently unused)
Definition: muParserDef.h:261
An unexpected variable token has been found.
Definition: muParserDef.h:235
Invalid variable pointer.
Definition: muParserDef.h:256
Invalid function, variable or constant name.
Definition: muParserDef.h:249
void SetFormula(const string_type &a_strFormula)
Set the expression related to this error.
Error class of the parser.
Definition: muParserError.h:74
The Expression is empty.
Definition: muParserDef.h:257
Too many function parameters.
Definition: muParserDef.h:243
A numerical function has been called with a non value type of argument.
Definition: muParserDef.h:239
Namespace for mathematical applications.
Definition: muParser.cpp:48
Unexpected end of formula. (Example: "2+sin(")
Definition: muParserDef.h:231
Too few function parameters. (Example: "ite(1<2,2)")
Definition: muParserDef.h:244
A string function has been called with a different type of argument.
Definition: muParserDef.h:238
EErrorCodes GetCode() const
Return the error code.
ParserError()
Default constructor.
string_type::value_type char_type
The character type used by the parser.
Definition: muParserDef.h:308
Thrown when an identifier with more then 255 characters is used.
Definition: muParserDef.h:272
Bytecode cannot be exported.
Definition: muParserDef.h:281
int GetPos() const
Return the formula position related to the error.
Unexpected binary operator found.
Definition: muParserDef.h:229
MUP_STRING_TYPE string_type
The stringtype used by the parser.
Definition: muParserDef.h:302
Invalid operator priority.
Definition: muParserDef.h:259
Unexpected Parenthesis, opening or closing.
Definition: muParserDef.h:236
Invalid function, variable or constant name.
Definition: muParserDef.h:252
Invalid callback function pointer.
Definition: muParserDef.h:255
The expression or identifier contains invalid non printable characters.
Definition: muParserDef.h:276
EErrorCodes
Error codes.
Definition: muParserDef.h:226
Generic error.
Definition: muParserDef.h:263
const string_type & GetToken() const
Return string related with this token (if available).
Missing parens. (Example: "3*sin(3")
Definition: muParserDef.h:240
const string_type & GetMsg() const
Returns the message string for this error.
A string has been found at an inapropriate position.
Definition: muParserDef.h:237
Invalid function, variable or constant name.
Definition: muParserDef.h:251
ParserError & operator=(const ParserError &a_Obj)
Assignment operator.
Invalid binary operator identifier.
Definition: muParserDef.h:250
This file defines the error class used by the parser.