1 #ifndef STAN__GM__PARSER__STATEMENT_GRAMMAR_DEF__HPP
2 #define STAN__GM__PARSER__STATEMENT_GRAMMAR_DEF__HPP
17 #include <boost/spirit/include/qi.hpp>
18 #include <boost/lexical_cast.hpp>
19 #include <boost/fusion/include/adapt_struct.hpp>
20 #include <boost/fusion/include/std_pair.hpp>
21 #include <boost/config/warning_disable.hpp>
22 #include <boost/spirit/include/qi_numeric.hpp>
23 #include <boost/spirit/include/phoenix_core.hpp>
24 #include <boost/spirit/include/phoenix_function.hpp>
25 #include <boost/spirit/include/phoenix_fusion.hpp>
26 #include <boost/spirit/include/phoenix_object.hpp>
27 #include <boost/spirit/include/phoenix_operator.hpp>
28 #include <boost/spirit/include/phoenix_stl.hpp>
29 #include <boost/spirit/include/support_multi_pass.hpp>
30 #include <boost/tuple/tuple.hpp>
31 #include <boost/variant/apply_visitor.hpp>
32 #include <boost/variant/recursive_variant.hpp>
34 #include <boost/spirit/include/version.hpp>
35 #include <boost/spirit/include/support_line_pos_iterator.hpp>
50 (std::vector<stan::gm::expression>, dims_) );
53 (std::string, family_)
54 (std::vector<stan::gm::expression>, args_) );
57 (std::string, variable_)
65 (std::vector<stan::gm::printable>, printables_) );
68 (std::vector<stan::gm::printable>, printables_) );
79 (std::vector<stan::gm::var_decl>, local_decl_)
80 (std::vector<stan::gm::statement>, statements_) );
87 template <
typename T1,
typename T2,
typename T3>
91 std::ostream& error_msgs)
const {
95 error_msgs <<
"Returns only allowed from function bodies." << std::endl;
105 template <
typename T1,
typename T2,
typename T3>
109 std::ostream& error_msgs)
const {
113 error_msgs <<
"Void returns only allowed from function bodies of void return type."
125 template <
typename T1,
typename T2,
typename T3,
typename T4>
131 std::ostream& error_msgs)
const {
136 error_msgs <<
"unknown variable in assignment"
145 && lhs_origin != origin_allowed) {
146 error_msgs <<
"attempt to assign variable in wrong block."
147 <<
" left-hand-side variable origin=";
149 error_msgs << std::endl;
160 error_msgs <<
"Illegal to assign to function argument variables."
162 <<
"Use local variables instead."
178 error_msgs <<
"too many indexes for variable "
179 <<
"; variable name = " << name
180 <<
"; num dimensions given = " << num_index_dims
181 <<
"; variable array dimensions = " << lhs_var_num_dims
189 bool types_compatible
190 = lhs_base_type == rhs_base_type
192 if (!types_compatible) {
193 error_msgs <<
"base type mismatch in assignment"
194 <<
"; variable name = "
198 error_msgs <<
"; right-hand side type=";
200 error_msgs << std::endl;
204 error_msgs <<
"dimension mismatch in assignment"
205 <<
"; variable name = "
207 <<
", num dimensions given = "
209 <<
"; right-hand side dimensions = "
220 template <
typename T1,
typename T2,
typename T3>
224 const std::vector<expr_type>& arg_types,
225 std::ostream& error_msgs)
const {
237 std::ostream& error_msgs)
const {
238 std::vector<expr_type> arg_types;
240 for (
size_t i = 0; i < s.
dist_.
args_.size(); ++i)
241 arg_types.push_back(s.
dist_.
args_[i].expression_type());
243 function_name +=
"_log";
245 error_msgs <<
"unknown distribution=" << s.
dist_.
family_ << std::endl;
249 if (function_name ==
"lkj_cov_log") {
250 error_msgs <<
"Warning: the lkj_cov_log() sampling distribution"
251 <<
" is deprecated. It will be removed in Stan 3."
253 <<
"Code LKJ covariance in terms of an lkj_corr()"
254 <<
" distribution on a correlation matrix"
255 <<
" and independent lognormals on the scales."
256 << std::endl << std::endl;
263 error_msgs <<
"Warning (non-fatal):"
264 <<
" Left-hand side of sampling statement (~) contains a non-linear"
265 <<
" transform of a parameter or local variable."
267 <<
" You must call increment_log_prob() with the log absolute determinant"
268 <<
" of the Jacobian of the transform."
270 <<
" Sampling Statement left-hand-side expression:"
275 error_msgs << function_name <<
"(...)";
276 error_msgs << std::endl;
281 error_msgs <<
"Outcomes in truncated distributions must be univariate."
283 <<
" Found outcome expression: ";
285 error_msgs << std::endl
286 <<
" with non-univariate type: "
291 for (
size_t i = 0; i < s.
dist_.
args_.size(); ++i)
293 error_msgs <<
"Parameters in truncated distributions must be univariate."
295 <<
" Found parameter expression: ";
297 error_msgs << std::endl
298 <<
" with non-univariate type: "
306 error_msgs <<
"Lower boundsin truncated distributions must be univariate."
308 <<
" Found lower bound expression: ";
310 error_msgs << std::endl
311 <<
" with non-univariate type: "
318 error_msgs <<
"Upper bounds in truncated distributions must be univariate."
320 <<
" Found upper bound expression: ";
322 error_msgs << std::endl
323 <<
" with non-univariate type: "
330 std::vector<expr_type> arg_types_trunc(arg_types);
333 function_name_cdf +=
"_cdf_log";
335 error_msgs <<
"lower truncation not defined for specified arguments to "
340 error_msgs <<
"lower bound in truncation type does not match"
341 <<
" sampled variate in distribution's type"
347 std::vector<expr_type> arg_types_trunc(arg_types);
350 function_name_cdf +=
"_cdf_log";
352 error_msgs <<
"upper truncation not defined for specified arguments to "
357 error_msgs <<
"upper bound in truncation type does not match"
358 <<
" sampled variate in distribution's type"
370 template <
typename T1,
typename T2,
typename T3>
374 std::stringstream& error_msgs)
const {
376 error_msgs <<
"Illegal statement beginning with non-void expression parsed as"
379 error_msgs << std::endl
380 <<
"Not a legal assignment, sampling, or function statement. Note that"
382 <<
" * Assignment statements only allow variables (with optional indexes) on the left;"
384 <<
" if you see an outer function logical_lt (<) with negated (-) second argument,"
386 <<
" it indicates an assignment statement A <- B with illegal left"
388 <<
" side A parsed as expression (A < (-B))."
390 <<
" * Sampling statements allow arbitrary value-denoting expressions on the left."
392 <<
" * Functions used as statements must be declared to have void returns"
393 << std::endl << std::endl;
403 template <
typename T1,
typename T2>
407 for (
size_t i = 0; i < var_decls.size(); ++i)
408 vm.
remove(var_decls[i].name());
414 template <
typename T1,
typename T2,
typename T3>
418 std::stringstream& error_msgs)
const {
420 error_msgs <<
"conditions in while statement must be primitive int or real;"
431 template <
typename T1,
typename T2>
441 template <
typename T1,
typename T2,
typename T3,
typename T4>
444 std::string& name_local,
446 std::stringstream& error_msgs)
const {
449 error_msgs <<
"ERROR: loop variable already declared."
450 <<
" variable name=\"" << name <<
"\"" << std::endl;
463 template <
typename T1,
typename T2>
473 template <
typename T1,
typename T2,
typename T3>
478 std::stringstream& error_msgs)
const {
480 error_msgs <<
"expression denoting integer required; found type="
492 template <
typename T1,
typename T2,
typename T3>
497 std::stringstream& error_msgs)
const {
499 error_msgs <<
"sampling only allowed in model."
511 template <
typename T1,
typename T2,
typename T3>
516 std::ostream& error_msgs)
const {
519 error_msgs <<
"attempt to increment log prob with void expression" << std::endl;
526 template <
typename Iterator>
528 std::stringstream& error_msgs)
531 error_msgs_(error_msgs),
532 expression_g(var_map,error_msgs),
533 var_decls_g(var_map,error_msgs),
534 statement_2_g(var_map,error_msgs,*this)
536 using boost::spirit::qi::_1;
537 using boost::spirit::qi::char_;
538 using boost::spirit::qi::eps;
539 using boost::spirit::qi::lexeme;
540 using boost::spirit::qi::lit;
541 using boost::spirit::qi::no_skip;
542 using boost::spirit::qi::_pass;
543 using boost::spirit::qi::_val;
545 using boost::spirit::qi::labels::_a;
546 using boost::spirit::qi::labels::_r1;
547 using boost::spirit::qi::labels::_r2;
548 using boost::spirit::qi::labels::_r3;
588 %= lit(
"increment_log_prob")
652 > no_skip[*char_(
"a-zA-Z0-9/~!@#$%^&*()`_+-={}|[]:;'<>?,./ ")]
657 %= (lexeme[char_(
"a-zA-Z")
658 >> *char_(
"a-zA-Z0-9_.")]);
660 range_r.name(
"range expression pair, colon");
678 var_lhs_r.name(
"variable and array dimensions");
683 opt_dims_r.name(
"array dimensions (optional)");
687 dims_r.name(
"array dimensions");
697 sample_r.name(
"distribution of expression");
752 using boost::spirit::qi::on_error;
753 using boost::spirit::qi::fail;
754 using boost::spirit::qi::rethrow;
755 using namespace boost::spirit::qi::labels;
void operator()(while_statement &ws, const statement &s) const
boost::phoenix::function< validate_assignment > validate_assignment_f
void generate_expression(const expression &e, std::ostream &o)
boost::spirit::qi::rule< Iterator, printable(var_origin), whitespace_grammar< Iterator > > printable_r
void operator()(const expression &e, bool &pass, std::ostream &error_msgs) const
void operator()(const bool &allow_sample, bool &pass, std::stringstream &error_msgs) const
std::vector< expression > dims_
base_expr_type base_type_
void operator()(const std::vector< var_decl > &var_decls, variable_map &vm) const
boost::spirit::qi::rule< Iterator, range(var_origin), whitespace_grammar< Iterator > > range_r
void add(const std::string &name, const base_var_decl &base_decl, const var_origin &vo)
static function_signatures & instance()
boost::spirit::qi::rule< Iterator, boost::spirit::qi::locals< std::string >, for_statement(bool, var_origin, bool), whitespace_grammar< Iterator > > for_statement_r
boost::phoenix::function< validate_allow_sample > validate_allow_sample_f
bool operator()(const sample &s, const variable_map &var_map, std::ostream &error_msgs) const
bool is_primitive_int() const
boost::spirit::qi::rule< Iterator, std::vector< var_decl >), whitespace_grammar< Iterator > > local_var_decls_r
boost::spirit::qi::rule< Iterator, std::string(), whitespace_grammar< Iterator > > identifier_r
bool is_primitive_double() const
void operator()(bool &pass, const stan::gm::expression &expr, std::stringstream &error_msgs) const
void print_var_origin(std::ostream &o, const var_origin &vo)
const int function_argument_origin
boost::spirit::qi::rule< Iterator, reject_statement(var_origin), whitespace_grammar< Iterator > > reject_statement_r
boost::phoenix::function< unscope_locals > unscope_locals_f
boost::spirit::qi::rule< Iterator, range(var_origin), whitespace_grammar< Iterator > > truncation_range_r
boost::spirit::qi::rule< Iterator, std::string(), whitespace_grammar< Iterator > > printable_string_r
bool operator()(while_statement &ws, const expression &e, std::stringstream &error_msgs) const
const int void_function_argument_origin_rng
statement_2_grammar< Iterator > statement_2_g
const int function_argument_origin_rng
boost::spirit::qi::rule< Iterator, statement(bool, var_origin, bool), whitespace_grammar< Iterator > > statement_r
base_expr_type base_type_
boost::spirit::qi::rule< Iterator, boost::spirit::qi::locals< std::vector< var_decl > >, statements(bool, var_origin, bool), whitespace_grammar< Iterator > > statement_seq_r
bool has_non_param_var(const expression &e, const variable_map &var_map)
std::stringstream & error_msgs_
static bool is_univariate(const expr_type &et)
boost::spirit::qi::rule< Iterator, print_statement(var_origin), whitespace_grammar< Iterator > > print_statement_r
std::vector< expression > dims_
const int void_function_argument_origin_lp
boost::spirit::qi::rule< Iterator, while_statement(bool, var_origin, bool), whitespace_grammar< Iterator > > while_statement_r
void operator()(var_origin origin, bool &pass, std::ostream &error_msgs) const
const int void_function_argument_origin
var_decls_grammar< Iterator > var_decls_g
expression_grammar< Iterator > expression_g
void operator()(const std::string &name, variable_map &vm) const
boost::spirit::qi::rule< Iterator, variable_dims(var_origin), whitespace_grammar< Iterator > > var_lhs_r
void operator()(var_origin origin, bool &pass, std::ostream &error_msgs) const
boost::spirit::qi::rule< Iterator, return_statement(var_origin), whitespace_grammar< Iterator > > void_return_statement_r
boost::spirit::qi::rule< Iterator, std::vector< expression >var_origin), whitespace_grammar< Iterator > > dims_r
boost::phoenix::function< add_while_condition > add_while_condition_f
boost::spirit::qi::rule< Iterator, no_op_statement(), whitespace_grammar< Iterator > > no_op_statement_r
double e()
Return the base of the natural logarithm.
bool operator()(const std::string &name, std::string &name_local, variable_map &vm, std::stringstream &error_msgs) const
bool is_ill_formed() const
void remove(const std::string &name)
void operator()(const expression &expr, bool &pass, std::stringstream &error_msgs) const
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, assignment(var_origin), whitespace_grammar< Iterator > > assignment_r
expr_type infer_type_indexing(const base_expr_type &expr_base_type, size_t num_expr_dims, size_t num_index_dims)
boost::phoenix::function< validate_int_expr2 > validate_int_expr2_f
boost::phoenix::function< validate_sample > validate_sample_f
const int function_argument_origin_lp
boost::spirit::qi::rule< Iterator, sample(bool, var_origin), whitespace_grammar< Iterator > > sample_r
boost::phoenix::function< validate_non_void_expression > validate_non_void_expression_f
bool operator()(assignment &a, const var_origin &origin_allowed, variable_map &vm, std::ostream &error_msgs) const
std::vector< expression > args_
boost::spirit::qi::rule< Iterator, std::vector< expression >var_origin), whitespace_grammar< Iterator > > opt_dims_r
boost::phoenix::function< add_while_body > add_while_body_f
BOOST_FUSION_ADAPT_STRUCT(stan::gm::assignment,(stan::gm::variable_dims, var_dims_)(stan::gm::expression, expr_))
expr_type get_result_type(const std::string &name, const std::vector< expr_type > &args, std::ostream &error_msgs)
boost::phoenix::function< remove_loop_identifier > remove_loop_identifier_f
boost::phoenix::function< validate_void_return_allowed > validate_void_return_allowed_f
bool exists(const std::string &name) const
std::ostream & write_base_expr_type(std::ostream &o, base_expr_type type)
expr_type expression_type() const
boost::phoenix::function< expression_as_statement > expression_as_statement_f
base_var_decl get(const std::string &name) const
boost::spirit::qi::rule< Iterator, distribution(var_origin), whitespace_grammar< Iterator > > distribution_r
boost::phoenix::function< add_loop_identifier > add_loop_identifier_f
bool is_double_return(const std::string &function_name, const std::vector< expr_type > &arg_types, std::ostream &error_msgs) const
bool is_primitive() const
boost::phoenix::function< validate_return_allowed > validate_return_allowed_f
var_origin get_origin(const std::string &name) const
boost::spirit::qi::rule< Iterator, return_statement(var_origin), whitespace_grammar< Iterator > > return_statement_r
statement_grammar(variable_map &var_map, std::stringstream &error_msgs)