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 "muParserInt.h"
30 
31 #include <cmath>
32 #include <algorithm>
33 #include <numeric>
34 
35 using namespace std;
36 
37 /** \file
38 	\brief Implementation of a parser using integer value.
39 */
40 
41 /** \brief Namespace for mathematical applications. */
42 namespace mu
43 {
Abs(value_type v)44 	value_type ParserInt::Abs(value_type v) { return (value_type)Round(fabs((double)v)); }
Sign(value_type v)45 	value_type ParserInt::Sign(value_type v) { return (Round(v) < 0) ? -1 : (Round(v) > 0) ? 1 : 0; }
Ite(value_type v1,value_type v2,value_type v3)46 	value_type ParserInt::Ite(value_type v1, value_type v2,	value_type v3) { return (Round(v1) == 1) ? Round(v2) : Round(v3); }
Add(value_type v1,value_type v2)47 	value_type ParserInt::Add(value_type v1, value_type v2) { return Round(v1) + Round(v2); }
Sub(value_type v1,value_type v2)48 	value_type ParserInt::Sub(value_type v1, value_type v2) { return Round(v1) - Round(v2); }
Mul(value_type v1,value_type v2)49 	value_type ParserInt::Mul(value_type v1, value_type v2) { return Round(v1) * Round(v2); }
Div(value_type v1,value_type v2)50 	value_type ParserInt::Div(value_type v1, value_type v2) { return Round(v1) / Round(v2); }
Mod(value_type v1,value_type v2)51 	value_type ParserInt::Mod(value_type v1, value_type v2) { return Round(v1) % Round(v2); }
Shr(value_type v1,value_type v2)52 	value_type ParserInt::Shr(value_type v1, value_type v2) { return Round(v1) >> Round(v2); }
Shl(value_type v1,value_type v2)53 	value_type ParserInt::Shl(value_type v1, value_type v2) { return Round(v1) << Round(v2); }
LogAnd(value_type v1,value_type v2)54 	value_type ParserInt::LogAnd(value_type v1, value_type v2) { return Round(v1) & Round(v2); }
LogOr(value_type v1,value_type v2)55 	value_type ParserInt::LogOr(value_type v1, value_type v2) { return Round(v1) | Round(v2); }
And(value_type v1,value_type v2)56 	value_type ParserInt::And(value_type v1, value_type v2) { return Round(v1) && Round(v2); }
Or(value_type v1,value_type v2)57 	value_type ParserInt::Or(value_type v1, value_type v2) { return Round(v1) || Round(v2); }
Less(value_type v1,value_type v2)58 	value_type ParserInt::Less(value_type v1, value_type v2) { return Round(v1) < Round(v2); }
Greater(value_type v1,value_type v2)59 	value_type ParserInt::Greater(value_type v1, value_type v2) { return Round(v1) > Round(v2); }
LessEq(value_type v1,value_type v2)60 	value_type ParserInt::LessEq(value_type v1, value_type v2) { return Round(v1) <= Round(v2); }
GreaterEq(value_type v1,value_type v2)61 	value_type ParserInt::GreaterEq(value_type v1, value_type v2) { return Round(v1) >= Round(v2); }
Equal(value_type v1,value_type v2)62 	value_type ParserInt::Equal(value_type v1, value_type v2) { return Round(v1) == Round(v2); }
NotEqual(value_type v1,value_type v2)63 	value_type ParserInt::NotEqual(value_type v1, value_type v2) { return Round(v1) != Round(v2); }
Not(value_type v)64 	value_type ParserInt::Not(value_type v) { return !Round(v); }
65 
Pow(value_type v1,value_type v2)66 	value_type ParserInt::Pow(value_type v1, value_type v2)
67 	{
68 		return std::pow((double)Round(v1), (double)Round(v2));
69 	}
70 
71 
UnaryMinus(value_type v)72 	value_type ParserInt::UnaryMinus(value_type v)
73 	{
74 		return -Round(v);
75 	}
76 
77 
Sum(const value_type * a_afArg,int a_iArgc)78 	value_type ParserInt::Sum(const value_type* a_afArg, int a_iArgc)
79 	{
80 		if (!a_iArgc)
81 			throw ParserError(_T("too few arguments for function sum."));
82 
83 		value_type fRes = 0;
84 		for (int i = 0; i < a_iArgc; ++i)
85 			fRes += a_afArg[i];
86 
87 		return fRes;
88 	}
89 
90 
Min(const value_type * a_afArg,int a_iArgc)91 	value_type ParserInt::Min(const value_type* a_afArg, int a_iArgc)
92 	{
93 		if (!a_iArgc)
94 			throw ParserError(_T("too few arguments for function min."));
95 
96 		value_type fRes = a_afArg[0];
97 		for (int i = 0; i < a_iArgc; ++i)
98 			fRes = std::min(fRes, a_afArg[i]);
99 
100 		return fRes;
101 	}
102 
103 
Max(const value_type * a_afArg,int a_iArgc)104 	value_type ParserInt::Max(const value_type* a_afArg, int a_iArgc)
105 	{
106 		if (!a_iArgc)
107 			throw ParserError(_T("too few arguments for function min."));
108 
109 		value_type fRes = a_afArg[0];
110 		for (int i = 0; i < a_iArgc; ++i)
111 			fRes = std::max(fRes, a_afArg[i]);
112 
113 		return fRes;
114 	}
115 
116 
IsVal(const char_type * a_szExpr,int * a_iPos,value_type * a_fVal)117 	int ParserInt::IsVal(const char_type* a_szExpr, int* a_iPos, value_type* a_fVal)
118 	{
119 		string_type buf(a_szExpr);
120 		std::size_t pos = buf.find_first_not_of(_T("0123456789"));
121 
122 		if (pos == std::string::npos)
123 			return 0;
124 
125 		stringstream_type stream(buf.substr(0, pos));
126 		int iVal(0);
127 
128 		stream >> iVal;
129 		if (stream.fail())
130 			return 0;
131 
132 		stringstream_type::pos_type iEnd = stream.tellg();   // Position after reading
133 		if (stream.fail())
134 			iEnd = stream.str().length();
135 
136 		if (iEnd == (stringstream_type::pos_type) - 1)
137 			return 0;
138 
139 		*a_iPos += (int)iEnd;
140 		*a_fVal = (value_type)iVal;
141 		return 1;
142 	}
143 
144 
145 	/** \brief Check a given position in the expression for the presence of
146 			   a hex value.
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.
151 
152 	  Hey values must be prefixed with "0x" in order to be detected properly.
153 	*/
IsHexVal(const char_type * a_szExpr,int * a_iPos,value_type * a_fVal)154 	int ParserInt::IsHexVal(const char_type* a_szExpr, int* a_iPos, value_type* a_fVal)
155 	{
156 		if (a_szExpr[1] == 0 || (a_szExpr[0] != '0' || a_szExpr[1] != 'x'))
157 			return 0;
158 
159 		unsigned iVal(0);
160 
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;
165 		nPos = ss.tellg();
166 
167 		if (nPos == (stringstream_type::pos_type)0)
168 			return 1;
169 
170 		*a_iPos += (int)(2 + nPos);
171 		*a_fVal = (value_type)iVal;
172 		return 1;
173 	}
174 
175 
IsBinVal(const char_type * a_szExpr,int * a_iPos,value_type * a_fVal)176 	int ParserInt::IsBinVal(const char_type* a_szExpr, int* a_iPos, value_type* a_fVal)
177 	{
178 		if (a_szExpr[0] != '#')
179 			return 0;
180 
181 		unsigned iVal(0),
182 			iBits(sizeof(iVal) * 8),
183 			i(0);
184 
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);
187 
188 		if (i == 0)
189 			return 0;
190 
191 		if (i == iBits)
192 			throw exception_type(_T("Binary to integer conversion error (overflow)."));
193 
194 		*a_fVal = (unsigned)(iVal >> (iBits - i));
195 		*a_iPos += i + 1;
196 
197 		return 1;
198 	}
199 
200 
201 	/** \brief Constructor.
202 
203 		Call ParserBase class constructor and trigger Function, Operator and Constant initialization.
204 	*/
ParserInt()205 	ParserInt::ParserInt()
206 		:ParserBase()
207 	{
208 		AddValIdent(IsVal);    // lowest priority
209 		AddValIdent(IsBinVal);
210 		AddValIdent(IsHexVal); // highest priority
211 
212 		InitCharSets();
213 		InitFun();
214 		InitOprt();
215 	}
216 
217 
InitConst()218 	void ParserInt::InitConst()
219 	{
220 	}
221 
222 
InitCharSets()223 	void ParserInt::InitCharSets()
224 	{
225 		DefineNameChars(_T("0123456789_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"));
226 		DefineOprtChars(_T("+-*^/?<>=!%&|~'_"));
227 		DefineInfixOprtChars(_T("/+-*^?<>=!%&|~'_"));
228 	}
229 
230 
231 	/** \brief Initialize the default functions. */
InitFun()232 	void ParserInt::InitFun()
233 	{
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);
240 	}
241 
242 
243 	/** \brief Initialize operators. */
InitOprt()244 	void ParserInt::InitOprt()
245 	{
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);
249 
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);
254 
255 		DefineOprt(_T("&"), LogAnd, prLOGIC);
256 		DefineOprt(_T("|"), LogOr, prLOGIC);
257 		DefineOprt(_T("&&"), And, prLOGIC);
258 		DefineOprt(_T("||"), Or, prLOGIC);
259 
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);
266 
267 		DefineOprt(_T("+"), Add, prADD_SUB);
268 		DefineOprt(_T("-"), Sub, prADD_SUB);
269 
270 		DefineOprt(_T("*"), Mul, prMUL_DIV);
271 		DefineOprt(_T("/"), Div, prMUL_DIV);
272 		DefineOprt(_T("%"), Mod, prMUL_DIV);
273 
274 		DefineOprt(_T("^"), Pow, prPOW, oaRIGHT);
275 		DefineOprt(_T(">>"), Shr, prMUL_DIV + 1);
276 		DefineOprt(_T("<<"), Shl, prMUL_DIV + 1);
277 	}
278 
279 } // namespace mu
280