Build internal muparser more simply
[alexxy/gromacs.git] / src / external / muparser / src / 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         */
128         ParserError::ParserError(EErrorCodes a_iErrc)
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. */
145         ParserError::ParserError(const string_type& sMsg)
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         */
159         ParserError::ParserError(EErrorCodes iErrc,
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. */
220         ParserError::ParserError(const ParserError& a_Obj)
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. */
232         ParserError& ParserError::operator=(const ParserError& a_Obj)
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.*/
296         const string_type& ParserError::GetExpr() const
297         {
298                 return m_strFormula;
299         }
300
301         //------------------------------------------------------------------------------
302         /** \brief Returns the message string for this error. */
303         const string_type& ParserError::GetMsg() const
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         */
313         int ParserError::GetPos() const
314         {
315                 return m_iPos;
316         }
317
318         //------------------------------------------------------------------------------
319         /** \brief Return string related with this token (if available). */
320         const string_type& ParserError::GetToken() const
321         {
322                 return m_strTok;
323         }
324
325         //------------------------------------------------------------------------------
326         /** \brief Return the error code. */
327         EErrorCodes ParserError::GetCode() const
328         {
329                 return m_iErrc;
330         }
331 } // namespace mu
332
333 #if defined(_MSC_VER)
334         #pragma warning(pop)
335 #endif