Stan  2.14.0
probability, sampling & optimization
statement_grammar_def.hpp
Go to the documentation of this file.
1 #ifndef STAN_LANG_GRAMMARS_STATEMENT_GRAMMAR_DEF_HPP
2 #define STAN_LANG_GRAMMARS_STATEMENT_GRAMMAR_DEF_HPP
3 
4 #include <stan/lang/ast.hpp>
12 #include <boost/spirit/include/qi.hpp>
13 #include <boost/phoenix/phoenix.hpp>
14 #include <sstream>
15 #include <string>
16 #include <vector>
17 
19  (stan::lang::variable, lhs_var_)
20  (std::vector<stan::lang::idx>, idxs_)
21  (stan::lang::expression, rhs_) )
22 
23 BOOST_FUSION_ADAPT_STRUCT(stan::lang::assignment,
24  (stan::lang::variable_dims, var_dims_)
25  (stan::lang::expression, expr_) )
26 
27 BOOST_FUSION_ADAPT_STRUCT(stan::lang::variable_dims,
28  (std::string, name_)
29  (std::vector<stan::lang::expression>, dims_) )
30 
31 BOOST_FUSION_ADAPT_STRUCT(stan::lang::distribution,
32  (std::string, family_)
33  (std::vector<stan::lang::expression>, args_) )
34 
35 BOOST_FUSION_ADAPT_STRUCT(stan::lang::for_statement,
36  (std::string, variable_)
37  (stan::lang::range, range_)
38  (stan::lang::statement, statement_) )
39 
40 BOOST_FUSION_ADAPT_STRUCT(stan::lang::return_statement,
41  (stan::lang::expression, return_value_) )
42 
43 BOOST_FUSION_ADAPT_STRUCT(stan::lang::break_continue_statement,
44  (std::string, generate_) )
45 
46 BOOST_FUSION_ADAPT_STRUCT(stan::lang::print_statement,
47  (std::vector<stan::lang::printable>, printables_) )
48 
49 BOOST_FUSION_ADAPT_STRUCT(stan::lang::reject_statement,
50  (std::vector<stan::lang::printable>, printables_) )
51 
52 BOOST_FUSION_ADAPT_STRUCT(stan::lang::increment_log_prob_statement,
53  (stan::lang::expression, log_prob_) )
54 
56  (stan::lang::expression, expr_)
57  (stan::lang::distribution, dist_)
58  (stan::lang::range, truncation_) )
59 
60 BOOST_FUSION_ADAPT_STRUCT(stan::lang::statements,
61  (std::vector<stan::lang::var_decl>, local_decl_)
62  (std::vector<stan::lang::statement>, statements_) )
63 
64 namespace stan {
65 
66  namespace lang {
67 
68  template <typename Iterator>
69  statement_grammar<Iterator>::statement_grammar(variable_map& var_map,
70  std::stringstream& error_msgs)
71  : statement_grammar::base_type(statement_r),
72  var_map_(var_map),
73  error_msgs_(error_msgs),
74  expression_g(var_map, error_msgs),
75  var_decls_g(var_map, error_msgs),
76  statement_2_g(var_map, error_msgs, *this),
77  indexes_g(var_map, error_msgs, expression_g) {
78  using boost::spirit::qi::_1;
79  using boost::spirit::qi::char_;
80  using boost::spirit::qi::eps;
81  using boost::spirit::qi::lexeme;
82  using boost::spirit::qi::lit;
83  using boost::spirit::qi::no_skip;
84  using boost::spirit::qi::string;
85  using boost::spirit::qi::_pass;
86  using boost::spirit::qi::_val;
87  using boost::spirit::qi::raw;
88 
89  using boost::spirit::qi::labels::_a;
90  using boost::spirit::qi::labels::_r1;
91  using boost::spirit::qi::labels::_r2;
92  using boost::spirit::qi::labels::_r3;
93  using boost::spirit::qi::labels::_r4;
94 
95  using boost::phoenix::begin;
96  using boost::phoenix::end;
97 
98  // inherited features
99  // _r1 true if sample_r allowed
100  // _r2 source of variables allowed for assignments
101  // _r3 true if return_r allowed
102  // _r4 true if in loop (allowing break/continue)
103 
104  // raw[ ] just to wrap to get line numbers
105  statement_r.name("statement");
107  = raw[statement_sub_r(_r1, _r2, _r3, _r4)[assign_lhs_f(_val, _1)]]
108  [add_line_number_f(_val, begin(_1), end(_1))];
109 
110  statement_sub_r.name("statement");
112  %= no_op_statement_r // key ";"
113  | statement_seq_r(_r1, _r2, _r3, _r4) // key "{"
114  | increment_log_prob_statement_r(_r1, _r2) // key "increment_log_prob"
115  | increment_target_statement_r(_r1, _r2) // key "target"
116  | for_statement_r(_r1, _r2, _r3) // key "for"
117  | while_statement_r(_r1, _r2, _r3) // key "while"
118  | break_continue_statement_r(_r4) // key "break", "continue"
119  | statement_2_g(_r1, _r2, _r3, _r4) // key "if"
120  | print_statement_r(_r2) // key "print"
121  | reject_statement_r(_r2) // key "reject"
122  | return_statement_r(_r2) // key "return"
123  | void_return_statement_r(_r2) // key "return"
124  | assignment_r(_r2) // lvalue "<-"
125  | assgn_r(_r2) // var[idxs] <- expr
126  | sample_r(_r1, _r2) // expression "~"
127  | expression_g(_r2) // expression
128  [expression_as_statement_f(_pass, _1,
129  boost::phoenix::ref(error_msgs_))];
130 
131  // _r1, _r2, _r3, _r4 same as statement_r
132  statement_seq_r.name("sequence of statements");
134  %= lit('{')
136  > *statement_r(_r1, _r2, _r3, _r4)
137  > lit('}')
138  > eps[unscope_locals_f(_a, boost::phoenix::ref(var_map_))];
139 
141  %= var_decls_g(false, local_origin); // - constants
142 
143  // inherited _r1 = true if samples allowed as statements
144  increment_log_prob_statement_r.name("increment log prob statement");
146  %= (lit("increment_log_prob") >> no_skip[!char_("a-zA-Z0-9_")])
147  > eps[deprecate_increment_log_prob_f(boost::phoenix::ref(error_msgs_))]
148  > eps[validate_allow_sample_f(_r1, _pass,
149  boost::phoenix::ref(error_msgs_))]
150  > lit('(')
151  > expression_g(_r2)
153  boost::phoenix::ref(error_msgs_))]
154  > lit(')')
155  > lit(';');
156 
157  // just variant syntax for increment_log_prob_r (see above)
158  increment_target_statement_r.name("increment target statement");
160  %= (lit("target") >> lit("+="))
161  > eps[validate_allow_sample_f(_r1, _pass,
162  boost::phoenix::ref(error_msgs_))]
163  > expression_g(_r2)
165  boost::phoenix::ref(error_msgs_))]
166  > lit(';');
167 
168  // _r1, _r2, _r3, same as statement_r
169  while_statement_r.name("while statement");
171  = (lit("while") >> no_skip[!char_("a-zA-Z0-9_")])
172  > lit('(')
173  > expression_g(_r2)
174  [add_while_condition_f(_val, _1, _pass,
175  boost::phoenix::ref(error_msgs_))]
176  > lit(')')
177  > statement_r(_r1, _r2, _r3, true)
178  [add_while_body_f(_val, _1)];
179 
180  // _r1 here == _r4 from statement_r
181  break_continue_statement_r.name("break or continue statement");
183  %= (string("break") | string("continue"))
184  > eps[validate_in_loop_f(_r1, _pass, boost::phoenix::ref(error_msgs_))]
185  > lit(';');
186 
187  // _r1, _r2, _r3 same as statement_r
188  for_statement_r.name("for statement");
190  %= (lit("for") >> no_skip[!char_("a-zA-Z0-9_")])
191  > lit('(')
192  > identifier_r[add_loop_identifier_f(_1, _a, _pass,
193  boost::phoenix::ref(var_map_),
194  boost::phoenix::ref(error_msgs_))]
195  > lit("in")
196  > range_r(_r2)
197  > lit(')')
198  > statement_r(_r1, _r2, _r3, true)
199  > eps
200  [remove_loop_identifier_f(_a, boost::phoenix::ref(var_map_))];
201 
202  print_statement_r.name("print statement");
204  %= (lit("print") >> no_skip[!char_("a-zA-Z0-9_")])
205  > lit('(')
206  > (printable_r(_r1) % ',')
207  > lit(')');
208 
209  // reject
210  reject_statement_r.name("reject statement");
212  %= (lit("reject") >> no_skip[!char_("a-zA-Z0-9_")])
213  > lit('(')
214  > (printable_r(_r1) % ',')
215  > lit(')');
216 
217  printable_r.name("printable");
220  | expression_g(_r1)
221  [non_void_expression_f(_1, _pass, boost::phoenix::ref(error_msgs_))];
222 
223  printable_string_r.name("printable quoted string");
225  %= lit('"')
226  > no_skip[*char_("a-zA-Z0-9/~!@#$%^&*()`_+-={}|[]:;'<>?,./ ")]
227  > lit('"');
228 
229  identifier_r.name("identifier");
231  %= (lexeme[char_("a-zA-Z")
232  >> *char_("a-zA-Z0-9_.")]);
233 
234  range_r.name("range expression pair, colon");
235  range_r
236  %= expression_g(_r1)
237  [validate_int_expr_f(_1, _pass,
238  boost::phoenix::ref(error_msgs_))]
239  >> lit(':')
240  >> expression_g(_r1)
241  [validate_int_expr_f(_1, _pass,
242  boost::phoenix::ref(error_msgs_))];
243 
244  // this one comes before assgn_r to deal with simple assignment
245  assignment_r.name("variable assignment by expression");
247  %= var_lhs_r(_r1)
249  > expression_rhs_r(_r1)
250  [validate_assignment_f(_val, _r1, _pass,
251  boost::phoenix::ref(var_map_),
252  boost::phoenix::ref(error_msgs_))]
253  > lit(';');
254 
255  assgn_r.name("indexed variable assginment statement");
256  assgn_r
257  %= var_r(_r1)
258  >> indexes_g(_r1)
260  >> (eps > expression_rhs_r(_r1))
261  [validate_assgn_f(_val, _pass, boost::phoenix::ref(error_msgs_))]
262  > lit(';');
263 
264  assignment_operator_r.name("assignment operator");
266  %= lit("<-")
267  [deprecate_old_assignment_op_f(boost::phoenix::ref(error_msgs_))]
268  | (lit("=") >> no_skip[!char_("=")]);
269 
270  var_r.name("variable for left-hand side of assignment");
271  var_r
272  = identifier_r
273  [identifier_to_var_f(_1, _r1, _val, _pass,
274  boost::phoenix::ref(var_map_),
275  boost::phoenix::ref(error_msgs_))];
276 
277  // separate rule for name on expectation failure
278  expression_rhs_r.name("expression assignable to left-hand side");
280  %= expression_g(_r1);
281 
282  var_lhs_r.name("variable and array dimensions");
283  var_lhs_r
284  %= identifier_r
285  >> opt_dims_r(_r1);
286 
287  opt_dims_r.name("array dimensions (optional)");
288  opt_dims_r
289  %= *dims_r(_r1);
290 
291  dims_r.name("array dimensions");
292  // uses silent test because errors will be reported in sliced rules
293  dims_r
294  %= lit('[')
295  >> (expression_g(_r1)[validate_int_expr_silent_f(_1, _pass)] % ',')
296  >> lit(']');
297 
298  // inherited _r1 = true if samples allowed as statements
299  sample_r.name("distribution of expression");
300  sample_r
301  %= (expression_g(_r2)
302  >> lit('~'))
303  > eps
304  [validate_allow_sample_f(_r1, _pass,
305  boost::phoenix::ref(error_msgs_))]
306  > distribution_r(_r2)
307  > -truncation_range_r(_r2)
308  > lit(';')
309  > eps
310  [validate_sample_f(_val, boost::phoenix::ref(var_map_),
311  _pass, boost::phoenix::ref(error_msgs_))];
312 
313  distribution_r.name("distribution and parameters");
315  %= (identifier_r
316  >> lit('(')
317  >> -(expression_g(_r1) % ','))
318  > lit(')');
319 
320  truncation_range_r.name("range pair");
322  %= lit('T')
323  > lit('[')
324  > -expression_g(_r1)
325  > lit(',')
326  > -expression_g(_r1)
327  > lit(']');
328 
329  // _r1 = allow sampling, _r2 = var origin
330  return_statement_r.name("return statement");
332  %= (lit("return") >> no_skip[!char_("a-zA-Z0-9_")])
333  >> expression_g(_r1)
334  >> lit(';') [validate_return_allowed_f(_r1, _pass,
335  boost::phoenix::ref(error_msgs_))];
336 
337  // _r1 = var origin
338  void_return_statement_r.name("void return statement");
340  = lit("return")[set_void_return_f(_val)] // = expression()]
341  >> lit(';')[validate_void_return_allowed_f(_r1, _pass,
342  boost::phoenix::ref(error_msgs_))];
343 
344  no_op_statement_r.name("no op statement");
346  %= lit(';')[set_no_op_f(_val)];
347  }
348 
349  }
350 }
351 #endif
boost::phoenix::function< validate_return_allowed > validate_return_allowed_f
boost::spirit::qi::rule< Iterator, increment_log_prob_statement(bool, var_origin), whitespace_grammar< Iterator > > increment_target_statement_r
boost::phoenix::function< add_while_body > add_while_body_f
boost::spirit::qi::rule< Iterator, std::vector< expression >var_origin), whitespace_grammar< Iterator > > dims_r
indexes_grammar< Iterator > indexes_g
boost::phoenix::function< validate_assgn > validate_assgn_f
AST node for assignment to variable with multi-indexing.
Definition: assgn.hpp:15
boost::spirit::qi::rule< Iterator, assignment(var_origin), whitespace_grammar< Iterator > > assignment_r
boost::spirit::qi::rule< Iterator, range(var_origin), whitespace_grammar< Iterator > > range_r
boost::spirit::qi::rule< Iterator, std::vector< var_decl >), whitespace_grammar< Iterator > > local_var_decls_r
void sample(stan::mcmc::base_mcmc *sampler, int num_warmup, int num_samples, int num_thin, int refresh, bool save, stan::services::sample::mcmc_writer< Model, SampleRecorder, DiagnosticRecorder, MessageRecorder > &mcmc_writer, stan::mcmc::sample &init_s, Model &model, RNG &base_rng, const std::string &prefix, const std::string &suffix, std::ostream &o, StartTransitionCallback &callback, interface_callbacks::writer::base_writer &info_writer, interface_callbacks::writer::base_writer &error_writer)
Definition: sample.hpp:17
boost::phoenix::function< set_no_op > set_no_op_f
Probability, optimization and sampling library.
boost::phoenix::function< deprecate_increment_log_prob > deprecate_increment_log_prob_f
Template specification of functions in std for Stan.
boost::spirit::qi::rule< Iterator, variable(var_origin), whitespace_grammar< Iterator > > var_r
boost::spirit::qi::rule< Iterator, printable(var_origin), whitespace_grammar< Iterator > > printable_r
boost::spirit::qi::rule< Iterator, boost::spirit::qi::unused_type, whitespace_grammar< Iterator > > assignment_operator_r
boost::phoenix::function< add_loop_identifier > add_loop_identifier_f
boost::spirit::qi::rule< Iterator, statement(bool, var_origin, bool, bool), whitespace_grammar< Iterator > > statement_r
expression_grammar< Iterator > expression_g
boost::phoenix::function< validate_void_return_allowed > validate_void_return_allowed_f
boost::spirit::qi::rule< Iterator, break_continue_statement(bool), whitespace_grammar< Iterator > > break_continue_statement_r
boost::phoenix::function< non_void_expression > non_void_expression_f
boost::spirit::qi::rule< Iterator, distribution(var_origin), whitespace_grammar< Iterator > > distribution_r
boost::phoenix::function< remove_loop_identifier > remove_loop_identifier_f
boost::spirit::qi::rule< Iterator, no_op_statement(), whitespace_grammar< Iterator > > no_op_statement_r
BOOST_FUSION_ADAPT_STRUCT(stan::lang::expr_type,(stan::lang::base_expr_type, base_type_)(size_t, num_dims_)) namespace stan
boost::phoenix::function< validate_int_expr > validate_int_expr_f
boost::spirit::qi::rule< Iterator, range(var_origin), whitespace_grammar< Iterator > > truncation_range_r
boost::phoenix::function< add_line_number > add_line_number_f
boost::spirit::qi::rule< Iterator, print_statement(var_origin), whitespace_grammar< Iterator > > print_statement_r
boost::phoenix::function< validate_int_expr_silent > validate_int_expr_silent_f
boost::spirit::qi::rule< Iterator, while_statement(bool, var_origin, bool), whitespace_grammar< Iterator > > while_statement_r
boost::phoenix::function< validate_allow_sample > validate_allow_sample_f
boost::phoenix::function< assign_lhs > assign_lhs_f
boost::phoenix::function< expression_as_statement > expression_as_statement_f
boost::spirit::qi::rule< Iterator, sample(bool, var_origin), whitespace_grammar< Iterator > > sample_r
boost::spirit::qi::rule< Iterator, assgn(var_origin), whitespace_grammar< Iterator > > assgn_r
boost::spirit::qi::rule< Iterator, return_statement(var_origin), whitespace_grammar< Iterator > > return_statement_r
boost::spirit::qi::rule< Iterator, boost::spirit::qi::locals< std::vector< var_decl > >, statements(bool, var_origin, bool, bool), whitespace_grammar< Iterator > > statement_seq_r
boost::spirit::qi::rule< Iterator, boost::spirit::qi::locals< std::string >, for_statement(bool, var_origin, bool), whitespace_grammar< Iterator > > for_statement_r
boost::spirit::qi::rule< Iterator, expression(var_origin), whitespace_grammar< Iterator > > expression_rhs_r
boost::spirit::qi::rule< Iterator, reject_statement(var_origin), whitespace_grammar< Iterator > > reject_statement_r
boost::phoenix::function< validate_sample > validate_sample_f
Structure to hold a variable.
Definition: variable.hpp:14
boost::spirit::qi::rule< Iterator, std::string(), whitespace_grammar< Iterator > > identifier_r
const int local_origin
The origin of the variable is as a local variable.
Definition: var_origin.hpp:47
boost::phoenix::function< unscope_locals > unscope_locals_f
boost::phoenix::function< identifier_to_var > identifier_to_var_f
boost::phoenix::function< validate_in_loop > validate_in_loop_f
boost::spirit::qi::rule< Iterator, std::vector< expression >var_origin), whitespace_grammar< Iterator > > opt_dims_r
boost::phoenix::function< add_while_condition > add_while_condition_f
boost::spirit::qi::rule< Iterator, std::string(), whitespace_grammar< Iterator > > printable_string_r
boost::phoenix::function< validate_assignment > validate_assignment_f
boost::spirit::qi::rule< Iterator, variable_dims(var_origin), whitespace_grammar< Iterator > > var_lhs_r
statement_2_grammar< Iterator > statement_2_g
boost::phoenix::function< set_void_return > set_void_return_f
var_decls_grammar< Iterator > var_decls_g
boost::spirit::qi::rule< Iterator, return_statement(var_origin), whitespace_grammar< Iterator > > void_return_statement_r
boost::phoenix::function< deprecate_old_assignment_op > deprecate_old_assignment_op_f
boost::spirit::qi::rule< Iterator, increment_log_prob_statement(bool, var_origin), whitespace_grammar< Iterator > > increment_log_prob_statement_r
boost::spirit::qi::rule< Iterator, statement(bool, var_origin, bool, bool), whitespace_grammar< Iterator > > statement_sub_r
boost::phoenix::function< validate_non_void_expression > validate_non_void_expression_f

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