Stan  1.0
probability, sampling & optimization
 All Classes Namespaces Files Functions Variables Typedefs Enumerator Friends Macros Pages
expression_grammar_def.hpp
Go to the documentation of this file.
1 #ifndef __STAN__GM__PARSER__EXPRESSION_GRAMMAR_DEF__HPP__
2 #define __STAN__GM__PARSER__EXPRESSION_GRAMMAR_DEF__HPP__
3 
4 #include <cstddef>
5 #include <iomanip>
6 #include <iostream>
7 #include <istream>
8 #include <map>
9 #include <set>
10 #include <sstream>
11 #include <string>
12 #include <utility>
13 #include <vector>
14 #include <stdexcept>
15 
16 #include <boost/spirit/include/qi.hpp>
17 // FIXME: get rid of unused include
18 #include <boost/spirit/include/phoenix_core.hpp>
19 #include <boost/spirit/include/phoenix_function.hpp>
20 #include <boost/spirit/include/phoenix_fusion.hpp>
21 #include <boost/spirit/include/phoenix_object.hpp>
22 #include <boost/spirit/include/phoenix_operator.hpp>
23 #include <boost/spirit/include/phoenix_stl.hpp>
24 
25 #include <boost/lexical_cast.hpp>
26 #include <boost/fusion/include/adapt_struct.hpp>
27 #include <boost/fusion/include/std_pair.hpp>
28 #include <boost/config/warning_disable.hpp>
29 #include <boost/spirit/include/qi.hpp>
30 #include <boost/spirit/include/qi_numeric.hpp>
31 #include <boost/spirit/include/classic_position_iterator.hpp>
32 #include <boost/spirit/include/phoenix_core.hpp>
33 #include <boost/spirit/include/phoenix_function.hpp>
34 #include <boost/spirit/include/phoenix_fusion.hpp>
35 #include <boost/spirit/include/phoenix_object.hpp>
36 #include <boost/spirit/include/phoenix_operator.hpp>
37 #include <boost/spirit/include/phoenix_stl.hpp>
38 #include <boost/spirit/include/support_multi_pass.hpp>
39 #include <boost/tuple/tuple.hpp>
40 #include <boost/variant/apply_visitor.hpp>
41 #include <boost/variant/recursive_variant.hpp>
42 
43 #include <stan/gm/ast.hpp>
46 
48  (stan::gm::expression, expr_)
49  (std::vector<std::vector<stan::gm::expression> >,
50  dimss_) )
51 
52 BOOST_FUSION_ADAPT_STRUCT(stan::gm::fun,
53  (std::string, name_)
54  (std::vector<stan::gm::expression>, args_) )
55 
56 BOOST_FUSION_ADAPT_STRUCT(stan::gm::int_literal,
57  (int,val_)
58  (stan::gm::expr_type,type_))
59 
60 BOOST_FUSION_ADAPT_STRUCT(stan::gm::double_literal,
61  (double,val_)
62  (stan::gm::expr_type,type_) )
63 
64 namespace stan {
65 
66  namespace gm {
67 
68  struct set_fun_type {
69  template <typename T1, typename T2>
70  struct result { typedef fun type; };
71 
72  fun operator()(fun& fun,
73  std::ostream& error_msgs) const {
74  std::vector<expr_type> arg_types;
75  for (size_t i = 0; i < fun.args_.size(); ++i)
76  arg_types.push_back(fun.args_[i].expression_type());
77  fun.type_ = function_signatures::instance().get_result_type(fun.name_,
78  arg_types,
79  error_msgs);
80  return fun;
81  }
82  };
83  boost::phoenix::function<set_fun_type> set_fun_type_f;
84 
85 
86  struct addition_expr {
87  template <typename T1, typename T2, typename T3>
88  struct result { typedef expression type; };
89 
90  expression operator()(expression& expr1,
91  const expression& expr2,
92  std::ostream& error_msgs) const {
93  if (expr1.expression_type().is_primitive()
94  && expr2.expression_type().is_primitive()) {
95  return expr1 += expr2;
96  }
97  std::vector<expression> args;
98  args.push_back(expr1);
99  args.push_back(expr2);
100  set_fun_type sft;
101  fun f("add",args);
102  sft(f,error_msgs);
103  return expression(f);
104  return expr1 += expr2;
105  }
106  };
107  boost::phoenix::function<addition_expr> addition;
108 
109 
110  struct subtraction_expr {
111  template <typename T1, typename T2, typename T3>
112  struct result { typedef expression type; };
113 
114  expression operator()(expression& expr1,
115  const expression& expr2,
116  std::ostream& error_msgs) const {
117  if (expr1.expression_type().is_primitive()
118  && expr2.expression_type().is_primitive()) {
119  return expr1 -= expr2;
120  }
121  std::vector<expression> args;
122  args.push_back(expr1);
123  args.push_back(expr2);
124  set_fun_type sft;
125  fun f("subtract",args);
126  sft(f,error_msgs);
127  return expression(f);
128  }
129  };
130  boost::phoenix::function<subtraction_expr> subtraction;
131 
132  struct multiplication_expr {
133  template <typename T1, typename T2, typename T3>
134  struct result { typedef expression type; };
135 
136  expression operator()(expression& expr1,
137  const expression& expr2,
138  std::ostream& error_msgs) const {
139 
140  if (expr1.expression_type().is_primitive()
141  && expr2.expression_type().is_primitive()) {
142  return expr1 *= expr2;
143  }
144  std::vector<expression> args;
145  args.push_back(expr1);
146  args.push_back(expr2);
147  set_fun_type sft;
148  fun f("multiply",args);
149  sft(f,error_msgs);
150  return expression(f);
151  }
152  };
153  boost::phoenix::function<multiplication_expr> multiplication;
154 
155  void generate_expression(const expression& e, std::ostream& o);
156 
157  struct division_expr {
158  template <typename T1, typename T2, typename T3>
159  struct result { typedef expression type; };
160 
161  expression operator()(expression& expr1,
162  const expression& expr2,
163  std::ostream& error_msgs) const {
164  if (expr1.expression_type().is_primitive_int()
165  && expr2.expression_type().is_primitive_int()) {
166  // getting here, but not printing? only print error if problems?
167  error_msgs << "Warning: integer division implicitly rounds to integer."
168  << " Found int division: ";
169  generate_expression(expr1.expr_,error_msgs);
170  error_msgs << " / ";
171  generate_expression(expr2.expr_,error_msgs);
172  error_msgs << std::endl
173  << " Positive values rounded down, negative values rounded up or down"
174  << " in platform-dependent way."
175  << std::endl;
176  }
177 
178  if (expr1.expression_type().is_primitive()
179  && expr2.expression_type().is_primitive()) {
180  return expr1 /= expr2;
181  }
182  std::vector<expression> args;
183  args.push_back(expr1);
184  args.push_back(expr2);
185  set_fun_type sft;
186  if ((expr1.expression_type().type() == MATRIX_T
187  || expr1.expression_type().type() == ROW_VECTOR_T)
188  && expr2.expression_type().type() == MATRIX_T) {
189  fun f("mdivide_right",args);
190  sft(f,error_msgs);
191  return expression(f);
192  }
193 
194  fun f("divide",args);
195  sft(f,error_msgs);
196  return expression(f);
197  }
198  };
199  boost::phoenix::function<division_expr> division;
200 
201  struct left_division_expr {
202  template <typename T1, typename T2, typename T3>
203  struct result { typedef expression type; };
204 
205  expression operator()(expression& expr1,
206  const expression& expr2,
207  std::ostream& error_msgs) const {
208  if (expr1.expression_type().is_primitive()
209  && expr2.expression_type().is_primitive()) {
210  return expr1 /= expr2;
211  }
212  std::vector<expression> args;
213  args.push_back(expr1);
214  args.push_back(expr2);
215  set_fun_type sft;
216  if (expr1.expression_type().type() == MATRIX_T
217  && (expr2.expression_type().type() == VECTOR_T
218  || expr2.expression_type().type() == MATRIX_T)) {
219  fun f("mdivide_left",args);
220  sft(f,error_msgs);
221  return expression(f);
222  }
223  fun f("divide_left",args);
224  sft(f,error_msgs);
225  return expression(f);
226  }
227  };
228  boost::phoenix::function<left_division_expr> left_division;
229 
230  struct elt_multiplication_expr {
231  template <typename T1, typename T2, typename T3>
232  struct result { typedef expression type; };
233 
234  expression operator()(expression& expr1,
235  const expression& expr2,
236  std::ostream& error_msgs) const {
237 
238  if (expr1.expression_type().is_primitive()
239  && expr2.expression_type().is_primitive()) {
240  return expr1 *= expr2;
241  }
242  std::vector<expression> args;
243  args.push_back(expr1);
244  args.push_back(expr2);
245  set_fun_type sft;
246  fun f("elt_multiply",args);
247  sft(f,error_msgs);
248  return expression(f);
249  return expr1 += expr2;
250  }
251  };
252  boost::phoenix::function<elt_multiplication_expr> elt_multiplication;
253 
254  struct elt_division_expr {
255  template <typename T1, typename T2, typename T3>
256  struct result { typedef expression type; };
257 
258  expression operator()(expression& expr1,
259  const expression& expr2,
260  std::ostream& error_msgs) const {
261 
262  if (expr1.expression_type().is_primitive()
263  && expr2.expression_type().is_primitive()) {
264  return expr1 /= expr2;
265  }
266  std::vector<expression> args;
267  args.push_back(expr1);
268  args.push_back(expr2);
269  set_fun_type sft;
270  fun f("elt_divide",args);
271  sft(f,error_msgs);
272  return expression(f);
273  return expr1 += expr2;
274  }
275  };
276  boost::phoenix::function<elt_division_expr> elt_division;
277 
278  // Cut-and-Paste from Spirit examples, including comment: We
279  // should be using expression::operator-. There's a bug in phoenix
280  // type deduction mechanism that prevents us from doing
281  // so. Phoenix will be switching to BOOST_TYPEOF. In the meantime,
282  // we will use a phoenix::function below:
283  struct negate_expr {
284  template <typename T1, typename T2>
285  struct result { typedef expression type; };
286 
287  expression operator()(const expression& expr,
288  std::ostream& error_msgs) const {
289  if (expr.expression_type().is_primitive()) {
290  return expression(unary_op('-', expr));
291  }
292  std::vector<expression> args;
293  args.push_back(expr);
294  set_fun_type sft;
295  fun f("minus",args);
296  sft(f,error_msgs);
297  return expression(f);
298  }
299  };
300  boost::phoenix::function<negate_expr> negate_expr_f;
301 
302  struct transpose_expr {
303  template <typename T1, typename T2>
304  struct result { typedef expression type; };
305 
306  expression operator()(const expression& expr,
307  std::ostream& error_msgs) const {
308  if (expr.expression_type().is_primitive()) {
309  return expr; // transpose of basic is self?
310  }
311  std::vector<expression> args;
312  args.push_back(expr);
313  set_fun_type sft;
314  fun f("transpose",args);
315  sft(f,error_msgs);
316  return expression(f);
317  }
318  };
319  boost::phoenix::function<transpose_expr> transpose_f;
320 
321  struct add_expression_dimss {
322  template <typename T1, typename T2, typename T3, typename T4>
323  struct result { typedef T1 type; };
324  expression operator()(expression& expression,
325  std::vector<std::vector<stan::gm::expression> >& dimss,
326  bool& pass,
327  std::ostream& error_msgs) const {
328  index_op iop(expression,dimss);
329  iop.infer_type();
330  if (iop.type_.is_ill_formed()) {
331  error_msgs << "indexes inappropriate for expression." << std::endl;
332  pass = false;
333  } else {
334  pass = true;
335  }
336  return iop;
337  }
338  };
339  boost::phoenix::function<add_expression_dimss> add_expression_dimss_f;
340 
341  struct set_var_type {
342  template <typename T1, typename T2, typename T3, typename T4>
343  struct result { typedef variable type; };
344  variable operator()(variable& var_expr,
345  variable_map& vm,
346  std::ostream& error_msgs,
347  bool& pass) const {
348  std::string name = var_expr.name_;
349  if (!vm.exists(name)) {
350  pass = false;
351  error_msgs << "variable \"" << name << '"' << " does not exist."
352  << std::endl;
353  return var_expr;
354  }
355  pass = true;
356  var_expr.set_type(vm.get_base_type(name),vm.get_num_dims(name));
357  return var_expr;
358  }
359  };
360  boost::phoenix::function<set_var_type> set_var_type_f;
361 
362  struct validate_int_expr3 {
363  template <typename T1, typename T2>
364  struct result { typedef bool type; };
365 
366  bool operator()(const expression& expr,
367  std::stringstream& error_msgs) const {
368  if (!expr.expression_type().is_primitive_int()) {
369  error_msgs << "expression denoting integer required; found type="
370  << expr.expression_type() << std::endl;
371  return false;
372  }
373  return true;
374  }
375  };
376  boost::phoenix::function<validate_int_expr3> validate_int_expr3_f;
377 
378 
379  struct validate_expr_type {
380  template <typename T1, typename T2>
381  struct result { typedef bool type; };
382 
383  bool operator()(const expression& expr,
384  std::ostream& error_msgs) const {
385  if (expr.expression_type().is_ill_formed()) {
386  error_msgs << "expression is ill formed" << std::endl;
387  return false;
388  }
389  return true;
390  }
391  };
392  boost::phoenix::function<validate_expr_type> validate_expr_type_f;
393 
394 
395 
396 
397 
398  template <typename Iterator>
399  expression_grammar<Iterator>::expression_grammar(variable_map& var_map,
400  std::stringstream& error_msgs)
401  : expression_grammar::base_type(expression_r),
402  var_map_(var_map),
403  error_msgs_(error_msgs)
404  {
405  using boost::spirit::qi::_1;
406  using boost::spirit::qi::char_;
407  using boost::spirit::qi::double_;
408  using boost::spirit::qi::eps;
409  using boost::spirit::qi::int_;
410  using boost::spirit::qi::lexeme;
411  using boost::spirit::qi::lit;
412  using boost::spirit::qi::_pass;
413  using boost::spirit::qi::_val;
414 
415  expression_r.name("expression");
416  expression_r
417  %= term_r [_val = _1]
418  >> *( (lit('+') > term_r [_val = addition(_val,_1,boost::phoenix::ref(error_msgs))])
419  | (lit('-') > term_r [_val = subtraction(_val,_1,boost::phoenix::ref(error_msgs))])
420  )
421  > eps[_pass = validate_expr_type_f(_val,boost::phoenix::ref(error_msgs_))]
422  ;
423 
424  term_r.name("term");
425  term_r
426  %= ( negated_factor_r [_val = _1]
427  >> *( (lit('*') > negated_factor_r
428  [_val = multiplication(_val,_1,boost::phoenix::ref(error_msgs_))])
429  | (lit('/') > negated_factor_r
430  [_val = division(_val,_1,boost::phoenix::ref(error_msgs_))])
431  | (lit('\\') > negated_factor_r [_val = left_division(_val,_1,boost::phoenix::ref(error_msgs_))])
432  | (lit(".*") > negated_factor_r
433  [_val = elt_multiplication(_val,_1,boost::phoenix::ref(error_msgs_))])
434  | (lit("./") > negated_factor_r
435  [_val = elt_division(_val,_1,boost::phoenix::ref(error_msgs_))])
436  )
437  )
438  ;
439 
440  negated_factor_r
441  %= lit('-') >> indexed_factor_r [_val = negate_expr_f(_1,boost::phoenix::ref(error_msgs_))]
442  | lit('+') >> indexed_factor_r [_val = _1]
443  | indexed_factor_r [_val = _1];
444 
445 
446  indexed_factor_r.name("(optionally) indexed factor [sub]");
447  indexed_factor_r
448  = factor_r [_val = _1]
449  > * (
450  (+dims_r)
451  [_val = add_expression_dimss_f(_val, _1, _pass,
452  boost::phoenix::ref(error_msgs_))]
453  |
454  lit("'")
455  [_val = transpose_f(_val, boost::phoenix::ref(error_msgs_))]
456  )
457  ;
458 
459  factor_r.name("factor");
460  factor_r
461  %= int_literal_r [_val = _1]
462  | double_literal_r [_val = _1]
463  | fun_r [_val = set_fun_type_f(_1,boost::phoenix::ref(error_msgs_))]
464  | variable_r
465  [_val = set_var_type_f(_1,boost::phoenix::ref(var_map_),
466  boost::phoenix::ref(error_msgs_),
467  _pass)]
468  | ( lit('(')
469  > expression_r [_val = _1]
470  > lit(')') )
471  ;
472 
473  int_literal_r.name("integer literal");
474  int_literal_r
475  %= int_
476  >> !( lit('.')
477  | lit('e')
478  | lit('E') );
479 
480  double_literal_r.name("real literal");
481  double_literal_r
482  %= double_;
483 
484  fun_r.name("function and argument expressions");
485  fun_r
486  %= identifier_r
487  >> args_r;
488 
489  identifier_r.name("identifier");
490  identifier_r
491  %= (lexeme[char_("a-zA-Z")
492  >> *char_("a-zA-Z0-9_.")]);
493 
494  args_r.name("function argument expressions");
495  args_r
496  %= (lit('(') >> lit(')'))
497  | ( lit('(')
498  >> (expression_r % ',')
499  > lit(')') )
500  ;
501 
502  dims_r.name("array dimensions");
503  dims_r
504  %= lit('[')
505  > (expression_r
506  [_pass = validate_int_expr3_f(_1,boost::phoenix::ref(error_msgs_))]
507  % ',')
508  > lit(']')
509  ;
510 
511  variable_r.name("variable expression");
512  variable_r
513  %= identifier_r;
514 
515  }
516  }
517 }
518 
519 #endif

     [ Stan Home Page ] © 2011–2012, Stan Development Team.