3 _____ __ _____________ _______ ______ ___________
4 / \| | \____ \__ \\_ __ \/ ___// __ \_ __ \
5 | Y Y \ | / |_> > __ \| | \/\___ \\ ___/| | \/
6 |__|_| /____/| __(____ /__| /____ >\___ >__|
8 Copyright (C) 2004 - 2020 Ingo Berg
10 Redistribution and use in source and binary forms, with or without modification, are permitted
11 provided that the following conditions are met:
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.
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.
29 #include "muParserInt.h"
38 \brief Implementation of a parser using integer value.
41 /** \brief Namespace for mathematical applications. */
44 value_type ParserInt::Abs(value_type v) { return (value_type)Round(fabs((double)v)); }
45 value_type ParserInt::Sign(value_type v) { return (Round(v) < 0) ? -1 : (Round(v) > 0) ? 1 : 0; }
46 value_type ParserInt::Ite(value_type v1, value_type v2, value_type v3) { return (Round(v1) == 1) ? Round(v2) : Round(v3); }
47 value_type ParserInt::Add(value_type v1, value_type v2) { return Round(v1) + Round(v2); }
48 value_type ParserInt::Sub(value_type v1, value_type v2) { return Round(v1) - Round(v2); }
49 value_type ParserInt::Mul(value_type v1, value_type v2) { return Round(v1) * Round(v2); }
50 value_type ParserInt::Div(value_type v1, value_type v2) { return Round(v1) / Round(v2); }
51 value_type ParserInt::Mod(value_type v1, value_type v2) { return Round(v1) % Round(v2); }
52 value_type ParserInt::Shr(value_type v1, value_type v2) { return Round(v1) >> Round(v2); }
53 value_type ParserInt::Shl(value_type v1, value_type v2) { return Round(v1) << Round(v2); }
54 value_type ParserInt::LogAnd(value_type v1, value_type v2) { return Round(v1) & Round(v2); }
55 value_type ParserInt::LogOr(value_type v1, value_type v2) { return Round(v1) | Round(v2); }
56 value_type ParserInt::And(value_type v1, value_type v2) { return Round(v1) && Round(v2); }
57 value_type ParserInt::Or(value_type v1, value_type v2) { return Round(v1) || Round(v2); }
58 value_type ParserInt::Less(value_type v1, value_type v2) { return Round(v1) < Round(v2); }
59 value_type ParserInt::Greater(value_type v1, value_type v2) { return Round(v1) > Round(v2); }
60 value_type ParserInt::LessEq(value_type v1, value_type v2) { return Round(v1) <= Round(v2); }
61 value_type ParserInt::GreaterEq(value_type v1, value_type v2) { return Round(v1) >= Round(v2); }
62 value_type ParserInt::Equal(value_type v1, value_type v2) { return Round(v1) == Round(v2); }
63 value_type ParserInt::NotEqual(value_type v1, value_type v2) { return Round(v1) != Round(v2); }
64 value_type ParserInt::Not(value_type v) { return !Round(v); }
66 value_type ParserInt::Pow(value_type v1, value_type v2)
68 return std::pow((double)Round(v1), (double)Round(v2));
72 value_type ParserInt::UnaryMinus(value_type v)
78 value_type ParserInt::Sum(const value_type* a_afArg, int a_iArgc)
81 throw ParserError(_T("too few arguments for function sum."));
84 for (int i = 0; i < a_iArgc; ++i)
91 value_type ParserInt::Min(const value_type* a_afArg, int a_iArgc)
94 throw ParserError(_T("too few arguments for function min."));
96 value_type fRes = a_afArg[0];
97 for (int i = 0; i < a_iArgc; ++i)
98 fRes = std::min(fRes, a_afArg[i]);
104 value_type ParserInt::Max(const value_type* a_afArg, int a_iArgc)
107 throw ParserError(_T("too few arguments for function min."));
109 value_type fRes = a_afArg[0];
110 for (int i = 0; i < a_iArgc; ++i)
111 fRes = std::max(fRes, a_afArg[i]);
117 int ParserInt::IsVal(const char_type* a_szExpr, int* a_iPos, value_type* a_fVal)
119 string_type buf(a_szExpr);
120 std::size_t pos = buf.find_first_not_of(_T("0123456789"));
122 if (pos == std::string::npos)
125 stringstream_type stream(buf.substr(0, pos));
132 stringstream_type::pos_type iEnd = stream.tellg(); // Position after reading
134 iEnd = stream.str().length();
136 if (iEnd == (stringstream_type::pos_type) - 1)
139 *a_iPos += (int)iEnd;
140 *a_fVal = (value_type)iVal;
145 /** \brief Check a given position in the expression for the presence of
147 \param a_szExpr Pointer to the expression string
148 \param [in/out] a_iPos Pointer to an integer value holding the current parsing
149 position in the expression.
150 \param [out] a_fVal Pointer to the position where the detected value shall be stored.
152 Hey values must be prefixed with "0x" in order to be detected properly.
154 int ParserInt::IsHexVal(const char_type* a_szExpr, int* a_iPos, value_type* a_fVal)
156 if (a_szExpr[1] == 0 || (a_szExpr[0] != '0' || a_szExpr[1] != 'x'))
161 // New code based on streams for UNICODE compliance:
162 stringstream_type::pos_type nPos(0);
163 stringstream_type ss(a_szExpr + 2);
164 ss >> std::hex >> iVal;
167 if (nPos == (stringstream_type::pos_type)0)
170 *a_iPos += (int)(2 + nPos);
171 *a_fVal = (value_type)iVal;
176 int ParserInt::IsBinVal(const char_type* a_szExpr, int* a_iPos, value_type* a_fVal)
178 if (a_szExpr[0] != '#')
182 iBits(sizeof(iVal) * 8),
185 for (i = 0; (a_szExpr[i + 1] == '0' || a_szExpr[i + 1] == '1') && i < iBits; ++i)
186 iVal |= (int)(a_szExpr[i + 1] == '1') << ((iBits - 1) - i);
192 throw exception_type(_T("Binary to integer conversion error (overflow)."));
194 *a_fVal = (unsigned)(iVal >> (iBits - i));
201 /** \brief Constructor.
203 Call ParserBase class constructor and trigger Function, Operator and Constant initialization.
205 ParserInt::ParserInt()
208 AddValIdent(IsVal); // lowest priority
209 AddValIdent(IsBinVal);
210 AddValIdent(IsHexVal); // highest priority
218 void ParserInt::InitConst()
223 void ParserInt::InitCharSets()
225 DefineNameChars(_T("0123456789_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"));
226 DefineOprtChars(_T("+-*^/?<>=!%&|~'_"));
227 DefineInfixOprtChars(_T("/+-*^?<>=!%&|~'_"));
231 /** \brief Initialize the default functions. */
232 void ParserInt::InitFun()
234 DefineFun(_T("sign"), Sign);
235 DefineFun(_T("abs"), Abs);
236 DefineFun(_T("if"), Ite);
237 DefineFun(_T("sum"), Sum);
238 DefineFun(_T("min"), Min);
239 DefineFun(_T("max"), Max);
243 /** \brief Initialize operators. */
244 void ParserInt::InitOprt()
246 // disable all built in operators, not all of them useful for integer numbers
247 // (they don't do rounding of values)
248 EnableBuiltInOprt(false);
250 // Disable all built in operators, they won't work with integer numbers
251 // since they are designed for floating point numbers
252 DefineInfixOprt(_T("-"), UnaryMinus);
253 DefineInfixOprt(_T("!"), Not);
255 DefineOprt(_T("&"), LogAnd, prLOGIC);
256 DefineOprt(_T("|"), LogOr, prLOGIC);
257 DefineOprt(_T("&&"), And, prLOGIC);
258 DefineOprt(_T("||"), Or, prLOGIC);
260 DefineOprt(_T("<"), Less, prCMP);
261 DefineOprt(_T(">"), Greater, prCMP);
262 DefineOprt(_T("<="), LessEq, prCMP);
263 DefineOprt(_T(">="), GreaterEq, prCMP);
264 DefineOprt(_T("=="), Equal, prCMP);
265 DefineOprt(_T("!="), NotEqual, prCMP);
267 DefineOprt(_T("+"), Add, prADD_SUB);
268 DefineOprt(_T("-"), Sub, prADD_SUB);
270 DefineOprt(_T("*"), Mul, prMUL_DIV);
271 DefineOprt(_T("/"), Div, prMUL_DIV);
272 DefineOprt(_T("%"), Mod, prMUL_DIV);
274 DefineOprt(_T("^"), Pow, prPOW, oaRIGHT);
275 DefineOprt(_T(">>"), Shr, prMUL_DIV + 1);
276 DefineOprt(_T("<<"), Shl, prMUL_DIV + 1);