OpcUaCanOpen
CANopen OPC-UA server
CompileMathExpression.h
Go to the documentation of this file.
1 #ifndef _MathExpression
2 #define _MathExpression
3 
4 #include <boost/config/warning_disable.hpp>
5 #include <boost/spirit/include/qi.hpp>
6 #include <boost/spirit/include/lex_lexertl.hpp>
7 #include <boost/spirit/include/phoenix_operator.hpp>
8 #include <boost/spirit/include/phoenix_core.hpp>
9 #include <boost/spirit/include/phoenix_fusion.hpp>
10 #include <boost/spirit/include/phoenix_stl.hpp>
11 #include <boost/fusion/include/adapt_struct.hpp>
12 #include <boost/bind/bind.hpp>
13 #include "TMath.h"
14 
15 #include <iostream>
16 #include <ostream>
17 #include <fstream>
18 #include <string>
19 #include <vector>
20 
21 using namespace boost::spirit;
22 using boost::phoenix::val;
23 
24  typedef std::string::iterator base_iterator_type;
25  typedef lex::lexertl::token<base_iterator_type, boost::mpl::vector<int,double,std::string> > lex_token_type;
26  typedef lex::lexertl::lexer<lex_token_type> lexer_type;
27 
28  class variableSet
29  {
30  public:
31  variableSet(std::string name_input) {
32  item = name_input;
33  std::cout << item << " Enter->";
34  std::cin >> value;
35  };
36  variableSet(): item() {}
37  virtual double getValue() {
38  return value;
39  };
40 
41  std::string item;
42  double value;
43  };
44 
45 
46  inline std::ostream& operator << ( std::ostream &out, const funcTable &op)
47  {
48  out << " [ " << op.name << " " << op.iden << " " << op.num_param << " ] ";
49  return out;
50  };
51 
53  funcTable,
54  (unsigned int,iden)
55  (std::string, name)
56  (int,num_param)
57  (ptr_func,p_func)
58  );
59 
60  typedef boost::variant<struct funcTable,int,double, std::string> operand_type;
61 
62  typedef std::vector<operand_type> operands_type_set;
63 
64  template <typename Lexer>
65  struct OpcUa_Formula_Tokens : lex::lexer<Lexer>
66  {
68  {
69  item = "[a-zA-Z_][a-zA-Z0-9_]*(\\.[a-zA-Z0-9_]+)*";
70  func = "[a-zA-Z_][a-zA-Z0-9_]*\\(";
71  regvar = "\\$[a-zA-Z_][a-zA-Z0-9_]*";
72  constant_float = "[0-9]*\\.[0-9]*([eE][-\\+]?[0-9]+)?";
73  constant_int = "[0-9]+";
74  plus = "\\+";
75  mul = "\\*";
76  div = "\\/";
77  minus = "\\-";
78  exp = "\\^";
79  lor = "\\|";
80  land = "&";
81  gt = ">";
82  lt = "<";
83  lnot = "!";
84  leq = "\\=";
85  lif = "\\?";
86  lthen = "\\:";
87  lbr = "\\(";
88  rbr = "\\)";
89  comma = "\\,";
90  ws = "\\s+";
91 
92  this->self = mul | div | exp | minus | plus | lif;
93  this->self += func | item | constant_int | constant_float | regvar ;
94  this->self += lbr | rbr | comma | lthen ;
95  this->self += leq | lnot | lt | gt | land | lor;
96 
97  // define the whitespace to ignore (spaces, tabs, newlines
98  // and add those to another lexer state (here: "WS")
99 
100  this->self("WS") = ws;
101  }
102 
103  lex::token_def<lex::omit> ws;
104  lex::token_def<std::string> item , func, regvar;
105  lex::token_def<>plus,minus,div,exp,mul,lbr,rbr,comma;
106  lex::token_def<>land,lor,lnot,leq,gt,lt,lif,lthen;
107  lex::token_def<int>constant_int;
108  lex::token_def<double>constant_float;
109 
110  };
111 
112  template <typename Iterator,typename Skipper>
113  struct OpcUa_Formula_Grammar_type : qi::grammar<Iterator,Skipper >
114  {
115  template <typename TokenDef>
116  OpcUa_Formula_Grammar_type(TokenDef const& tok, operands_type_set &opts ,bool logical) :
117  OpcUa_Formula_Grammar_type::base_type(logical ? expressionL : expressionA)
118  {
119  using boost::phoenix::ref;
120  using boost::phoenix::push_back;
121  using boost::spirit::qi::_1;
122  std::string tmpstr;
123 
124 // start = expressionA | expressionL;
125 
126  expressionA =
127 // expressionL >> tok.lif >> expressionA >> tok.lthen >> expressionA
128 // |
129  term >> *(term_minus | term_plus);
130 
131  factor_expression = tok.lbr >> expressionA >> tok.rbr;
132 
133  term_minus = tok.minus >> term
134  [
135  push_back(boost::phoenix::ref(opts),boost::phoenix::bind(TMath::getFuncTable,SMINUS) )
136  ] ;
137 
138  term_plus = tok.plus >> term
139  [
140  push_back(boost::phoenix::ref(opts),boost::phoenix::bind(TMath::getFuncTable,SPLUS ))
141  ] ;
142 
143 // term = factor_exp >> *( factor_mul | factor_div );
144 
145  term = factor_p_m >> *(factor_mul | factor_div);
146 
147  factor_mul = tok.mul >> factor_exp
148  [
149  push_back(boost::phoenix::ref(opts),boost::phoenix::bind(TMath::getFuncTable,SMUL))
150  ] ;
151 
152  factor_div = tok.div >> factor_exp
153  [
154  push_back(boost::phoenix::ref(opts),boost::phoenix::bind(TMath::getFuncTable,SDIV))
155  ] ;
156 
157  factor_exp = factor_p_m >> *(factor_exp2 );
158 
159  factor_exp2 = tok.exp >> factor_p_m
160  [
161  push_back(boost::phoenix::ref(opts),boost::phoenix::bind(TMath::getFuncTable,SEXP ) )
162  ] ;
163 
164  factor = factor_expression | factor_int | factor_float | factor_func | factor_item | factor_regvar;
165 
166  factor_p_m = factor_minus | factor_plus | factor;
167 
168  factor_int = tok.constant_int
169  [
170  push_back(boost::phoenix::ref(opts), _1)
171  ];
172  factor_float = tok.constant_float
173  [
174  push_back(boost::phoenix::ref(opts), _1)
175  ];
176 
177  factor_func = tok.func [_a = _1] >> factor_arg
178  [
179  push_back(boost::phoenix::ref(opts),boost::phoenix::bind(TMath::getFuncTableStr,_a) )
180  ] ;
181 
182  factor_arg = (expressionA % tok.comma ) >> tok.rbr;
183 
184  factor_item = tok.item
185  [
186  push_back(boost::phoenix::ref(opts), _1)
187  ];
188 
189 
190 
191  factor_minus = tok.minus >> factor
192  [
193  push_back(boost::phoenix::ref(opts),boost::phoenix::bind(TMath::getFuncTable,SMIN) )
194  ] ;
195 
196  factor_plus = tok.plus >> factor ;
197 
198  factor_regvar = tok.regvar
199  [
200  push_back(boost::phoenix::ref(opts), _1)
201  ];
202 
203 
204  expressionL = lterm >> *(logic_or);
205 
206  lfactor_expression = tok.lbr >> expressionL >> tok.rbr;
207 
208  lterm = lfactor >> *(logic_and);
209 
210  logic_or = tok.lor >> tok.lor >> lterm
211  [
212  push_back(boost::phoenix::ref(opts),boost::phoenix::bind(TMath::getFuncTable,SOR) )
213  ] ;
214 
215  logic_and = tok.land >> tok.land >> lfactor
216  [
217  push_back(boost::phoenix::ref(opts),boost::phoenix::bind(TMath::getFuncTable,SAND) )
218  ] ;
219 
220 // logic_exp = lfactor | *(logic_exp2);
221 
222  lfactor = logic_exp | lfactor_expression | lfactor2;
223 
224  logic_exp = tok.lnot >> lfactor
225  [
226  push_back(boost::phoenix::ref(opts),boost::phoenix::bind(TMath::getFuncTable,SNOT) )
227  ] ;
228 
229 
230  lfactor2 = expressionA >> -(ltermlt | ltermgt | ltermle | ltermge | ltermlne | ltermleq) ;
231 
232  ltermleq = tok.leq >> expressionA
233  [
234  push_back(boost::phoenix::ref(opts), boost::phoenix::bind(TMath::getFuncTable, SEQ))
235  ];
236  ltermge = tok.gt >> tok.leq >> expressionA
237  [
238  push_back(boost::phoenix::ref(opts),boost::phoenix::bind(TMath::getFuncTable,SGE) )
239  ] ;
240 
241  ltermlne = tok.lnot >> tok.leq >> expressionA
242  [
243  push_back(boost::phoenix::ref(opts),boost::phoenix::bind(TMath::getFuncTable,SNE) )
244  ] ;
245 
246  ltermgt = tok.gt >> expressionA
247  [
248  push_back(boost::phoenix::ref(opts),boost::phoenix::bind(TMath::getFuncTable,SGT) )
249  ] ;
250 
251  ltermlt = tok.lt >> expressionA
252  [
253  push_back(boost::phoenix::ref(opts),boost::phoenix::bind(TMath::getFuncTable,SLT) )
254  ] ;
255 
256  ltermle = tok.lt >> tok.leq >> expressionA
257  [
258  push_back(boost::phoenix::ref(opts),boost::phoenix::bind(TMath::getFuncTable,SLE) )
259  ] ;
260 
261 
262 
263 
264 #ifdef BOOST_SPIRIT_DEBUG
265 
266  expressionL.name("expressionL");
267  qi::debug(expressionL);
268  expressionA.name("expressionA");
269  qi::debug(expressionA);
270  term.name("term");
271  qi::debug(term);
272  term_minus.name("term_minus");
273  qi::debug(term_minus);
274  term_plus.name("term_plus");
275  qi::debug(term_plus);
276  lterm.name("lterm");
277  qi::debug(lterm);
278  lfactor.name("lfactor");
279  qi::debug(lfactor);
280  logic_or.name("logic_or");
281  qi::debug(logic_or);
282  logic_and.name("logic_and");
283  qi::debug(logic_and);
284  ltermge.name("ltermge");
285  qi::debug(ltermge);
286  ltermgt.name("ltermgt");
287  qi::debug(ltermgt);
288  ltermlt.name("ltermlt");
289  qi::debug(ltermlt);
290  ltermle.name("ltermle");
291  qi::debug(ltermle);
292  ltermlne.name("ltermlne");
293  qi::debug(ltermlne);
294  ltermleq.name("ltermleq");
295  qi::debug(ltermleq);
296  lfactor_expression.name("lfactor_expression");
297  qi::debug(lfactor_expression);
298  factor.name("factor");
299  qi::debug(factor);
300  factor_p_m.name("factor_p_m");
301  qi::debug(factor_p_m);
302  factor_div.name("factor_div");
303  qi::debug(factor_div);
304  factor_mul.name("factor_mul");
305  qi::debug(factor_mul);
306  factor_exp.name("factor_exp");
307  qi::debug(factor_exp);
308  factor_exp2.name("factor_exp");
309  qi::debug(factor_exp2);
310  factor_item.name("factor_item");
311  qi::debug(factor_item);
312  factor_minus.name("factor_minus");
313  qi::debug(factor_minus);
314  factor_plus.name("factor_plus");
315  qi::debug(factor_plus);
316  factor_int.name("factor_int");
317  qi::debug(factor_int);
318  factor_float.name("factor_float");
319  qi::debug(factor_float);
320  factor_arg.name("factor_arg");
321  qi::debug(factor_arg);
322  factor_func.name("factor_func");
323  qi::debug(factor_func);
324  factor_regvar.name("factor_regvar");
325  qi::debug(factor_regvar);
326 
327 
328 #endif
329 
330 
331  }
332 
333  qi::rule< Iterator,qi::locals<std::string>,Skipper > factor_func;
334  qi::rule< Iterator,Skipper > term,factor_exp,factor_exp2,factor_mul,factor_div, term_minus,term_plus,factor_regvar,factor_p_m;
335  qi::rule< Iterator,Skipper > factor_int,factor_float,factor_item, factor_minus,factor_expression,factor_plus,factor_arg;
336  qi::rule< Iterator, Skipper > logic_or, logic_and, lfactor, ltermgt, ltermlt, lterm, ltermge, ltermle, ltermleq, ltermlne, lfactor_expression;
337  qi::rule< Iterator,Skipper > logic_exp,logic_exp2,lfactor2;
338  qi::rule< Iterator,Skipper > expressionL,expressionA,start;
339  qi::rule< Iterator,Skipper > factor;
340 
341 
342 
343  };
344 
345  struct OpcUaFormula {
346 
348 
349  std::vector<std::string> sVariables;
350 
351  OpcUaFormula() : opt(), sVariables() { TMath::init(); }
352  bool Compile(std::string formul, bool logical);
353  bool hasVariables() { return !sVariables.empty(); }
354  double GetValue(std::string ind) {
355  std::cout << ind << "Enter->";
356  double ret;
357  std::cin >> ret;
358  return ret;
359  };
360  // boost::function<double(int)> getValueFromItem;
361  boost::function<double(std::string)> getValueFromItem;
362 // template <typename T> void eval(T&);
363  double eval();
364  bool evalCondition();
365 
366  private:
367  bool isCmdFunction(unsigned int idn) {
368  return (idn == SGE) | (idn == SGT) | (idn == SLT) | (idn == SLE) | (idn == SNE) | (idn == SEQ);
369  }
370 
371  double _eval( operands_type_set::reverse_iterator &in);
372  bool _evalCondition(operands_type_set::reverse_iterator &in);
373 
374  int m_iIndex;
375  };
376 
377 #endif