OpcUaCanOpen
CANopen OPC-UA server
CompileMathExpression.cpp
Go to the documentation of this file.
2 #include "TMath.h"
3 #include "UaCanTrace.h"
4 
5 std::vector<struct funcTable> TMath::functionSet(100);
6 
7 /*
8 double OpcUaFormula::_eval(operands_type_set::reverse_iterator &in , double (*getValueFromItem)(std::string))
9 {
10  int nType = in->which();
11  double tmp;
12  switch (nType) {
13  case 0:
14  {
15  funcTable ft = boost::get<funcTable>(*in);
16  switch (ft.num_param)
17  {
18  case 0: tmp = ft.p_func.ptr0Func();
19  break;
20  case 1: tmp = ft.p_func.ptr1Func(_eval(++in,getValueFromItem));
21  break;
22  case 2: tmp = ft.p_func.ptr2Func(_eval(++in,getValueFromItem),_eval(++in,getValueFromItem));
23  break;
24  case 3: tmp = ft.p_func.ptr3Func(_eval(++in,getValueFromItem),_eval(++in,getValueFromItem),_eval(++in,getValueFromItem));
25  break;
26  };
27  return tmp;
28 
29  }
30  case 1: return boost::get<int>((*in));
31  case 2: return boost::get<double>((*in));
32  case 3:
33  {
34  return (*getValueFromItem)(boost::get<std::string>((*in)));
35  }
36  }
37  return 0.0;
38 };
39 */
40 
41 double OpcUaFormula::_eval(operands_type_set::reverse_iterator &in )
42 {
43  int nType = in->which();
44  double tmp = 0.0, par1 = 0.0, par2 = 0.0, par3 = 0.0;
45 
46  switch (nType) {
47  case 0:
48  {
49  funcTable ft = boost::get<funcTable>(*in);
50 
51  switch (ft.num_param)
52  {
53  case 0:
54  tmp = ft.p_func.ptr0Func();
55  break;
56  case 1:
57  in++;
58  par1 = _eval(in);
59  tmp = ft.p_func.ptr1Func(par1);
60  break;
61  case 2:
62  in++;
63  par1 = _eval(in);
64  in++;
65  par2 = _eval(in);
66  tmp = ft.p_func.ptr2Func(par2,par1);
67  break;
68  case 3:
69  in++;
70  par1 = _eval(in);
71  in++;
72  par2 = _eval(in);
73  in++;
74  par3 = _eval(in);
75  tmp = ft.p_func.ptr3Func(par3,par2,par1);
76  break;
77  };
78  break;
79 
80  }
81  case 1:
82  tmp = boost::get<int>((*in));
83  break;
84  case 2:
85  tmp = boost::get<double>((*in));
86  break;
87  case 3:
88  tmp = getValueFromItem(boost::get<std::string>((*in)));
89  break;
90  }
91  return tmp;
92 };
93 
94 bool OpcUaFormula::_evalCondition(operands_type_set::reverse_iterator &in )
95 {
96  int nType = in->which();
97  unsigned int idn;
98  bool tmpbool = true,parl1 = true,parl2 = true ;
99 
100  if (nType == 0) {
101  funcTable ft = boost::get<funcTable>(*in);
102  idn = ft.iden;
103  if ( isCmdFunction(idn) ) {
104  in++;
105  double par1 = 0.0,par2 = 0.0;
106  par1 = _eval(in);
107  in++;
108  par2 = _eval(in);
109  tmpbool = ft.p_func.ptr2LDFunc(par2,par1);
110  }
111  else
112  switch (ft.num_param)
113  {
114  case 0:
115  tmpbool = ft.p_func.ptr0LFunc();
116  break;
117  case 1:
118  in++;
119  parl1 = _evalCondition(in);
120  tmpbool = ft.p_func.ptr1LFunc(parl1);
121  break;
122  case 2:
123  in++;
124  parl1 = _evalCondition(in);
125  in++;
126  parl2 = _evalCondition(in);
127  tmpbool = ft.p_func.ptr2LFunc(parl2,parl1);
128  break;
129  }
130  }
131  return tmpbool;
132 };
133 
135 {
136  double val = 0.0;
137  operands_type_set::reverse_iterator op = opt.rbegin();
138 
139  val = _eval(op);
140 
141  return val;
142 };
143 
145 {
146  operands_type_set::reverse_iterator op = opt.rbegin();
147 
148  bool val = true;
149  try {
150  val = _evalCondition(op);
151  }
152  catch (...)
153  {
154  LOG(Log::INF) << "Evaluation fault!";
155  std::cout << "Evaluation fault!" << std::endl;
156  return false;
157  }
158  return val;
159 };
160 
161 bool OpcUaFormula::Compile(std::string formul,bool logical)
162 {
163 // typedef std::string::iterator Iterator;
164 
165 // typedef lex::lexertl::token<Iterator, lex::omit, boost::mpl::true_> token_type;
166 
167 // typedef lex::lexertl::lexer<token_type> lexer_type;
168 
169  typedef OpcUa_Formula_Tokens<lexer_type> OpcUaFormulaTokens;
170  typedef qi::in_state_skipper<OpcUaFormulaTokens::lexer_def> skipper_type;
171  typedef OpcUaFormulaTokens::iterator_type iterator_type;
172 
173 
174  typedef OpcUa_Formula_Grammar_type< iterator_type,skipper_type> OpcUa_Formula_Grammar;
175 
176  OpcUaFormulaTokens OpcUa_Formula_lexer;
177 
178  OpcUa_Formula_Grammar OpcUa_Formula_parser( OpcUa_Formula_lexer, opt,logical);
179  // At this point we generate the iterator pair used to expose the
180  // tokenized input stream.
181  std::string::iterator iter = formul.begin();
182  std::string::iterator end = formul.end();
183 
184  // Parsing is done based on the the token stream, not the character
185  // stream read from the input.
186  // Note how we use the lexer defined above as the skip parser. It must
187  // be explicitly wrapped inside a state directive, switching the lexer
188  // state for the duration of skipping whitespace.
189  std::string ws("WS");
190  bool r = tokenize_and_phrase_parse(iter, end, OpcUa_Formula_lexer,OpcUa_Formula_parser, qi::in_state(ws)[OpcUa_Formula_lexer.self]);
191 // bool r = qi::phrase_parse(iter, end, OpcUa_Formula_parser, qi::in_state(ws)[OpcUa_Formula_lexer.self]);
192 
193  if (r && (iter == end ) )
194  {
195  /*
196  std::cout << "Exit " << r << std::endl;
197  for (std::string::iterator itt = iter; itt != end; itt++)
198  {
199  std::cout << *itt << std::endl;
200  }
201 */
202  for ( operands_type_set::iterator itt = opt.begin(); itt != opt.end(); itt++)
203  {
204  if (itt->which() == 3) {
205  std::string a = boost::get<std::string>((*itt));
206  if (a[0] == '$')
207  sVariables.push_back(a);
208  }
209 // std::cout << *itt << std::endl;
210  }
211 
212  return true;
213  }
214  LOG(Log::INF) << "Parsing failed " << formul;
215 
216  std::cout << "-------------------------" << std::endl;
217  std::cout << "Parsing failed " << formul << std::endl;
218  std::cout << "-------------------------" << std::endl;
219 
220  for ( std::string::iterator itt = iter; itt != end; itt++)
221  {
222  LOG(Log::INF) << *itt;
223  }
224 
225  return false;
226 };