muParser API -  1.35
muParserError.cpp
1 /*
2 
3  _____ __ _____________ _______ ______ ___________
4  / \| | \____ \__ \\_ __ \/ ___// __ \_ __ \
5  | Y Y \ | / |_> > __ \| | \/\___ \\ ___/| | \/
6  |__|_| /____/| __(____ /__| /____ >\___ >__|
7  \/ |__| \/ \/ \/
8  Copyright (C) 2004 - 2020 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) // What the fuck is the point of this warning?
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 
99  for (int i = 0; i < ecCOUNT; ++i)
100  {
101  if (!m_vErrMsg[i].length())
102  throw std::runtime_error("Error definitions are incomplete!");
103  }
104  }
105 
106  //---------------------------------------------------------------------------
107  //
108  // ParserError class
109  //
110  //---------------------------------------------------------------------------
111 
112  /** \brief Default constructor. */
113  ParserError::ParserError()
114  :m_strMsg()
115  , m_strFormula()
116  , m_strTok()
117  , m_iPos(-1)
118  , m_iErrc(ecUNDEFINED)
119  , m_ErrMsg(ParserErrorMsg::Instance())
120  {
121  }
122 
123  //------------------------------------------------------------------------------
124  /** \brief This Constructor is used for internal exceptions only.
125 
126  It does not contain any information but the error code.
127  */
129  :m_strMsg()
130  , m_strFormula()
131  , m_strTok()
132  , m_iPos(-1)
133  , m_iErrc(a_iErrc)
134  , m_ErrMsg(ParserErrorMsg::Instance())
135  {
136  m_strMsg = m_ErrMsg[m_iErrc];
137  stringstream_type stream;
138  stream << (int)m_iPos;
139  ReplaceSubString(m_strMsg, _T("$POS$"), stream.str());
140  ReplaceSubString(m_strMsg, _T("$TOK$"), m_strTok);
141  }
142 
143  //------------------------------------------------------------------------------
144  /** \brief Construct an error from a message text. */
146  :m_ErrMsg(ParserErrorMsg::Instance())
147  {
148  Reset();
149  m_strMsg = sMsg;
150  }
151 
152  //------------------------------------------------------------------------------
153  /** \brief Construct an error object.
154  \param [in] a_iErrc the error code.
155  \param [in] sTok The token string related to this error.
156  \param [in] sExpr The expression related to the error.
157  \param [in] a_iPos the position in the expression where the error occurred.
158  */
160  const string_type& sTok,
161  const string_type& sExpr,
162  int iPos)
163  :m_strMsg()
164  , m_strFormula(sExpr)
165  , m_strTok(sTok)
166  , m_iPos(iPos)
167  , m_iErrc(iErrc)
168  , m_ErrMsg(ParserErrorMsg::Instance())
169  {
170  m_strMsg = m_ErrMsg[m_iErrc];
171  stringstream_type stream;
172  stream << (int)m_iPos;
173  ReplaceSubString(m_strMsg, _T("$POS$"), stream.str());
174  ReplaceSubString(m_strMsg, _T("$TOK$"), m_strTok);
175  }
176 
177  //------------------------------------------------------------------------------
178  /** \brief Construct an error object.
179  \param [in] iErrc the error code.
180  \param [in] iPos the position in the expression where the error occurred.
181  \param [in] sTok The token string related to this error.
182  */
183  ParserError::ParserError(EErrorCodes iErrc, int iPos, const string_type& sTok)
184  :m_strMsg()
185  , m_strFormula()
186  , m_strTok(sTok)
187  , m_iPos(iPos)
188  , m_iErrc(iErrc)
189  , m_ErrMsg(ParserErrorMsg::Instance())
190  {
191  m_strMsg = m_ErrMsg[m_iErrc];
192  stringstream_type stream;
193  stream << (int)m_iPos;
194  ReplaceSubString(m_strMsg, _T("$POS$"), stream.str());
195  ReplaceSubString(m_strMsg, _T("$TOK$"), m_strTok);
196  }
197 
198  //------------------------------------------------------------------------------
199  /** \brief Construct an error object.
200  \param [in] szMsg The error message text.
201  \param [in] iPos the position related to the error.
202  \param [in] sTok The token string related to this error.
203  */
204  ParserError::ParserError(const char_type* szMsg, int iPos, const string_type& sTok)
205  :m_strMsg(szMsg)
206  , m_strFormula()
207  , m_strTok(sTok)
208  , m_iPos(iPos)
209  , m_iErrc(ecGENERIC)
210  , m_ErrMsg(ParserErrorMsg::Instance())
211  {
212  stringstream_type stream;
213  stream << (int)m_iPos;
214  ReplaceSubString(m_strMsg, _T("$POS$"), stream.str());
215  ReplaceSubString(m_strMsg, _T("$TOK$"), m_strTok);
216  }
217 
218  //------------------------------------------------------------------------------
219  /** \brief Copy constructor. */
221  :m_strMsg(a_Obj.m_strMsg)
222  , m_strFormula(a_Obj.m_strFormula)
223  , m_strTok(a_Obj.m_strTok)
224  , m_iPos(a_Obj.m_iPos)
225  , m_iErrc(a_Obj.m_iErrc)
226  , m_ErrMsg(ParserErrorMsg::Instance())
227  {
228  }
229 
230  //------------------------------------------------------------------------------
231  /** \brief Assignment operator. */
233  {
234  if (this == &a_Obj)
235  return *this;
236 
237  m_strMsg = a_Obj.m_strMsg;
238  m_strFormula = a_Obj.m_strFormula;
239  m_strTok = a_Obj.m_strTok;
240  m_iPos = a_Obj.m_iPos;
241  m_iErrc = a_Obj.m_iErrc;
242  return *this;
243  }
244 
245  //------------------------------------------------------------------------------
246  ParserError::~ParserError()
247  {}
248 
249  //------------------------------------------------------------------------------
250  /** \brief Replace all occurrences of a substring with another string.
251  \param strFind The string that shall be replaced.
252  \param strReplaceWith The string that should be inserted instead of strFind
253  */
254  void ParserError::ReplaceSubString(string_type& strSource,
255  const string_type& strFind,
256  const string_type& strReplaceWith)
257  {
258  string_type strResult;
259  string_type::size_type iPos(0), iNext(0);
260 
261  for (;;)
262  {
263  iNext = strSource.find(strFind, iPos);
264  strResult.append(strSource, iPos, iNext - iPos);
265 
266  if (iNext == string_type::npos)
267  break;
268 
269  strResult.append(strReplaceWith);
270  iPos = iNext + strFind.length();
271  }
272 
273  strSource.swap(strResult);
274  }
275 
276  //------------------------------------------------------------------------------
277  /** \brief Reset the error object. */
278  void ParserError::Reset()
279  {
280  m_strMsg = _T("");
281  m_strFormula = _T("");
282  m_strTok = _T("");
283  m_iPos = -1;
284  m_iErrc = ecUNDEFINED;
285  }
286 
287  //------------------------------------------------------------------------------
288  /** \brief Set the expression related to this error. */
289  void ParserError::SetFormula(const string_type& a_strFormula)
290  {
291  m_strFormula = a_strFormula;
292  }
293 
294  //------------------------------------------------------------------------------
295  /** \brief gets the expression related tp this error.*/
297  {
298  return m_strFormula;
299  }
300 
301  //------------------------------------------------------------------------------
302  /** \brief Returns the message string for this error. */
304  {
305  return m_strMsg;
306  }
307 
308  //------------------------------------------------------------------------------
309  /** \brief Return the formula position related to the error.
310 
311  If the error is not related to a distinct position this will return -1
312  */
314  {
315  return m_iPos;
316  }
317 
318  //------------------------------------------------------------------------------
319  /** \brief Return string related with this token (if available). */
321  {
322  return m_strTok;
323  }
324 
325  //------------------------------------------------------------------------------
326  /** \brief Return the error code. */
328  {
329  return m_iErrc;
330  }
331 } // namespace mu
332 
333 #if defined(_MSC_VER)
334  #pragma warning(pop)
335 #endif
A class that handles the error messages.
Definition: muParserError.h:47
#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:283
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:309
This is no error code, It just stores just the total number of error codes.
Definition: muParserDef.h:282
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:68
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:46
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:306
Thrown when an identifier with more then 255 characters is used.
Definition: muParserDef.h:272
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:300
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.