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

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