OpcUaCanOpen
CANopen OPC-UA server
muParserInt.cpp
Go to the documentation of this file.
1 /*
2  __________
3  _____ __ __\______ \_____ _______ ______ ____ _______
4  / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \
5  | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/
6  |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__|
7  \/ \/ \/ \/
8  Copyright (C) 2011 Ingo Berg
9 
10  Permission is hereby granted, free of charge, to any person obtaining a copy of this
11  software and associated documentation files (the "Software"), to deal in the Software
12  without restriction, including without limitation the rights to use, copy, modify,
13  merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
14  permit persons to whom the Software is furnished to do so, subject to the following conditions:
15 
16  The above copyright notice and this permission notice shall be included in all copies or
17  substantial portions of the Software.
18 
19  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
20  NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
22  DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 */
25 
26 #include "muParserInt.h"
27 
28 #include <cmath>
29 #include <algorithm>
30 #include <numeric>
31 
32 using namespace std;
33 
39 namespace mu
40 {
41 value_type ParserInt::Abs(value_type v) { return (value_type)Round(fabs((double)v)); }
42 value_type ParserInt::Sign(value_type v) { return (Round(v)<0) ? -1 : (Round(v)>0) ? 1 : 0; }
43 value_type ParserInt::Ite(value_type v1,
44  value_type v2,
45  value_type v3) { return (Round(v1)==1) ? Round(v2) : Round(v3); }
46 value_type ParserInt::Add(value_type v1, value_type v2) { return Round(v1) + Round(v2); }
47 value_type ParserInt::Sub(value_type v1, value_type v2) { return Round(v1) - Round(v2); }
48 value_type ParserInt::Mul(value_type v1, value_type v2) { return Round(v1) * Round(v2); }
49 value_type ParserInt::Div(value_type v1, value_type v2) { return Round(v1) / Round(v2); }
50 value_type ParserInt::Mod(value_type v1, value_type v2) { return Round(v1) % Round(v2); }
51 value_type ParserInt::Shr(value_type v1, value_type v2) { return Round(v1) >> Round(v2); }
52 value_type ParserInt::Shl(value_type v1, value_type v2) { return Round(v1) << Round(v2); }
53 value_type ParserInt::LogAnd(value_type v1, value_type v2) { return Round(v1) & Round(v2); }
54 value_type ParserInt::LogOr(value_type v1, value_type v2) { return Round(v1) | Round(v2); }
55 value_type ParserInt::And(value_type v1, value_type v2) { return Round(v1) && Round(v2); }
56 value_type ParserInt::Or(value_type v1, value_type v2) { return Round(v1) || Round(v2); }
57 value_type ParserInt::Less(value_type v1, value_type v2) { return Round(v1) < Round(v2); }
58 value_type ParserInt::Greater(value_type v1, value_type v2) { return Round(v1) > Round(v2); }
59 value_type ParserInt::LessEq(value_type v1, value_type v2) { return Round(v1) <= Round(v2); }
60 value_type ParserInt::GreaterEq(value_type v1, value_type v2) { return Round(v1) >= Round(v2); }
61 value_type ParserInt::Equal(value_type v1, value_type v2) { return Round(v1) == Round(v2); }
62 value_type ParserInt::NotEqual(value_type v1, value_type v2) { return Round(v1) != Round(v2); }
63 value_type ParserInt::Not(value_type v) { return !Round(v); }
64 
65 value_type ParserInt::Pow(value_type v1, value_type v2)
66 {
67  return std::pow((double)Round(v1), (double)Round(v2));
68 }
69 
70 //---------------------------------------------------------------------------
71 // Unary operator Callbacks: Infix operators
72 value_type ParserInt::UnaryMinus(value_type v)
73 {
74  return -Round(v);
75 }
76 
77 //---------------------------------------------------------------------------
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 //---------------------------------------------------------------------------
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 //---------------------------------------------------------------------------
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 //---------------------------------------------------------------------------
117 // Default value recognition callback
118 int ParserInt::IsVal(const char_type *a_szExpr, int *a_iPos, value_type *a_fVal)
119 {
120  string_type buf(a_szExpr);
121  std::size_t pos = buf.find_first_not_of(_T("0123456789"));
122 
123  if (pos==std::string::npos)
124  return 0;
125 
126  stringstream_type stream( buf.substr(0, pos ) );
127  int iVal(0);
128 
129  stream >> iVal;
130  if (stream.fail())
131  return 0;
132 
133  stringstream_type::pos_type iEnd = stream.tellg(); // Position after reading
134  if (stream.fail())
135  iEnd = stream.str().length();
136 
137  if (iEnd==(stringstream_type::pos_type)-1)
138  return 0;
139 
140  *a_iPos += (int)iEnd;
141  *a_fVal = (value_type)iVal;
142  return 1;
143 }
144 
145 //---------------------------------------------------------------------------
155 int ParserInt::IsHexVal(const char_type *a_szExpr, int *a_iPos, value_type *a_fVal)
156 {
157  if (a_szExpr[1]==0 || (a_szExpr[0]!='0' || a_szExpr[1]!='x') )
158  return 0;
159 
160  unsigned iVal(0);
161 
162  // New code based on streams for UNICODE compliance:
163  stringstream_type::pos_type nPos(0);
164  stringstream_type ss(a_szExpr + 2);
165  ss >> std::hex >> iVal;
166  nPos = ss.tellg();
167 
168  if (nPos==(stringstream_type::pos_type)0)
169  return 1;
170 
171  *a_iPos += (int)(2 + nPos);
172  *a_fVal = (value_type)iVal;
173  return 1;
174 }
175 
176 //---------------------------------------------------------------------------
177 int ParserInt::IsBinVal(const char_type *a_szExpr, int *a_iPos, value_type *a_fVal)
178 {
179  if (a_szExpr[0]!='#')
180  return 0;
181 
182  unsigned iVal(0),
183  iBits(sizeof(iVal)*8),
184  i(0);
185 
186  for (i=0; (a_szExpr[i+1]=='0' || a_szExpr[i+1]=='1') && i<iBits; ++i)
187  iVal |= (int)(a_szExpr[i+1]=='1') << ((iBits-1)-i);
188 
189  if (i==0)
190  return 0;
191 
192  if (i==iBits)
193  throw exception_type(_T("Binary to integer conversion error (overflow)."));
194 
195  *a_fVal = (unsigned)(iVal >> (iBits-i) );
196  *a_iPos += i+1;
197 
198  return 1;
199 }
200 
201 //---------------------------------------------------------------------------
206 ParserInt::ParserInt()
207  :ParserBase()
208 {
209  AddValIdent(IsVal); // lowest priority
211  AddValIdent(IsHexVal); // highest priority
212 
213  InitCharSets();
214  InitFun();
215  InitOprt();
216 }
217 
218 //---------------------------------------------------------------------------
220 {
221 }
222 
223 //---------------------------------------------------------------------------
225 {
226  DefineNameChars( _T("0123456789_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") );
227  DefineOprtChars( _T("+-*^/?<>=!%&|~'_") );
228  DefineInfixOprtChars( _T("/+-*^?<>=!%&|~'_") );
229 }
230 
231 //---------------------------------------------------------------------------
234 {
235  DefineFun( _T("sign"), Sign);
236  DefineFun( _T("abs"), Abs);
237  DefineFun( _T("if"), Ite);
238  DefineFun( _T("sum"), Sum);
239  DefineFun( _T("min"), Min);
240  DefineFun( _T("max"), Max);
241 }
242 
243 //---------------------------------------------------------------------------
246 {
247  // disable all built in operators, not all of them useful for integer numbers
248  // (they don't do rounding of values)
249  EnableBuiltInOprt(false);
250 
251  // Disable all built in operators, they won't work with integer numbers
252  // since they are designed for floating point numbers
253  DefineInfixOprt( _T("-"), UnaryMinus);
254  DefineInfixOprt( _T("!"), Not);
255 
256  DefineOprt( _T("&"), LogAnd, prLOGIC);
257  DefineOprt( _T("|"), LogOr, prLOGIC);
258  DefineOprt( _T("&&"), And, prLOGIC);
259  DefineOprt( _T("||"), Or, prLOGIC);
260 
261  DefineOprt( _T("<"), Less, prCMP);
262  DefineOprt( _T(">"), Greater, prCMP);
263  DefineOprt( _T("<="), LessEq, prCMP);
264  DefineOprt( _T(">="), GreaterEq, prCMP);
265  DefineOprt( _T("=="), Equal, prCMP);
266  DefineOprt( _T("!="), NotEqual, prCMP);
267 
268  DefineOprt( _T("+"), Add, prADD_SUB);
269  DefineOprt( _T("-"), Sub, prADD_SUB);
270 
271  DefineOprt( _T("*"), Mul, prMUL_DIV);
272  DefineOprt( _T("/"), Div, prMUL_DIV);
273  DefineOprt( _T("%"), Mod, prMUL_DIV);
274 
275  DefineOprt( _T("^"), Pow, prPOW, oaRIGHT);
276  DefineOprt( _T(">>"), Shr, prMUL_DIV+1);
277  DefineOprt( _T("<<"), Shl, prMUL_DIV+1);
278 }
279 
280 } // namespace mu