Stan  2.5.0
probability, sampling & optimization
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
program_grammar_def.hpp
Go to the documentation of this file.
1 #ifndef STAN__GM__PARSER__PROGRAM_GRAMMAR_DEF__HPP
2 #define STAN__GM__PARSER__PROGRAM_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/format.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>
33 
34 #include <boost/spirit/include/version.hpp>
35 #include <boost/spirit/home/support/iterators/line_pos_iterator.hpp>
36 
37 #include <stan/gm/ast.hpp>
44 
45 namespace {
46  // hack to pass pair into macro below to adapt; in namespace to hide
47  struct DUMMY_STRUCT {
48  typedef std::pair<std::vector<stan::gm::var_decl>,
49  std::vector<stan::gm::statement> > type;
50  };
51 }
52 
53 
55  (std::vector<stan::gm::function_decl_def>, function_decl_defs_)
56  (std::vector<stan::gm::var_decl>, data_decl_)
57  (DUMMY_STRUCT::type, derived_data_decl_)
58  (std::vector<stan::gm::var_decl>, parameter_decl_)
59  (DUMMY_STRUCT::type, derived_decl_)
60  (stan::gm::statement, statement_)
61  (DUMMY_STRUCT::type, generated_decl_) )
62 
63 
64 namespace stan {
65 
66  namespace gm {
67 
68  struct add_lp_var {
69  template <typename T>
70  struct result { typedef void type; };
71  void operator()(variable_map& vm) const {
72  vm.add("lp__",
73  base_var_decl("lp__",std::vector<expression>(),DOUBLE_T),
74  local_origin); // lp acts as a local where defined
75  }
76  };
77  boost::phoenix::function<add_lp_var> add_lp_var_f;
78 
79  struct remove_lp_var {
80  template <typename T>
81  struct result { typedef void type; };
82  void operator()(variable_map& vm) const {
83  vm.remove("lp__");
84  }
85  };
86  boost::phoenix::function<remove_lp_var> remove_lp_var_f;
87 
88  struct program_error {
89  template <typename T1, typename T2, typename ,
90  typename T4, typename T5, typename T6, typename T7>
91  struct result { typedef void type; };
92 
93  template <class Iterator, class I>
94  void operator()(
95  Iterator _begin,
96  Iterator _end,
97  Iterator _where,
98  I const& _info,
99  std::string msg,
100  variable_map& vm,
101  std::stringstream& error_msgs) const {
102 
103  using boost::phoenix::construct;
104  using boost::phoenix::val;
105  using boost::spirit::get_line;
106  using boost::format;
107  using std::setw;
108 
109  error_msgs << msg << std::endl;
110 
111  size_t idx_errline = 0;
112  idx_errline = get_line(_where);
113 
114  if (idx_errline > 0) {
115  error_msgs << "ERROR at line " << idx_errline << std::endl;
116 
117  std::basic_stringstream<char> sprogram;
118  sprogram << boost::make_iterator_range (_begin, _end);
119 
120  // show error in context 2 lines before, 1 lines after
121  size_t idx_errcol = 0;
122  idx_errcol = get_column(_begin,_where) - 1;
123 
124  std::string lineno = "";
125  format fmt_lineno("% 3d: ");
126 
127  std::string line_2before = "";
128  std::string line_before = "";
129  std::string line_err = "";
130  std::string line_after = "";
131 
132  size_t idx_line = 0;
133  size_t idx_before = idx_errline - 1;
134  if (idx_before > 0) {
135  // read lines up to error line, save 2 most recently read
136  while (idx_before > idx_line) {
137  line_2before = line_before;
138  std::getline(sprogram,line_before);
139  idx_line++;
140  }
141  if (line_2before.length() > 0) {
142  lineno = str(fmt_lineno % (idx_before - 1) );
143  error_msgs << lineno << line_2before << std::endl;
144  }
145  lineno = str(fmt_lineno % idx_before);
146  error_msgs << lineno << line_before << std::endl;
147  }
148 
149  std::getline(sprogram,line_err);
150  lineno = str(fmt_lineno % idx_errline);
151  error_msgs << lineno << line_err << std::endl
152  << setw(idx_errcol + lineno.length()) << "^" << std::endl;
153 
154  if (!sprogram.eof()) {
155  std::getline(sprogram,line_after);
156  lineno = str(fmt_lineno % (idx_errline+1));
157  error_msgs << lineno << line_after << std::endl;
158  }
159  }
160  error_msgs << std::endl;
161  }
162  };
163  boost::phoenix::function<program_error> program_error_f;
164 
165  template <typename Iterator>
166  program_grammar<Iterator>::program_grammar(const std::string& model_name)
167  : program_grammar::base_type(program_r),
168  model_name_(model_name),
169  var_map_(),
170  error_msgs_(),
171  expression_g(var_map_,error_msgs_),
172  var_decls_g(var_map_,error_msgs_),
173  statement_g(var_map_,error_msgs_),
174  functions_g(var_map_,error_msgs_) {
175 
176  using boost::spirit::qi::eps;
177  using boost::spirit::qi::lit;
178 
179  // add model_name to var_map with special origin and no
180  var_map_.add(model_name,
181  base_var_decl(),
183 
184  program_r.name("program");
185  program_r
186  %= -functions_g
187  > -data_var_decls_r
188  > -derived_data_var_decls_r
189  > -param_var_decls_r
190  // scope lp__ to "transformed params" and "model" only
191  > eps[add_lp_var_f(boost::phoenix::ref(var_map_))]
192  > -derived_var_decls_r
193  > model_r
194  > eps[remove_lp_var_f(boost::phoenix::ref(var_map_))]
195  > -generated_var_decls_r
196  ;
197 
198  model_r.name("model declaration");
199  model_r
200  %= lit("model")
201  > statement_g(true,local_origin,false) // assign only to locals
202  ;
203 
204  data_var_decls_r.name("data variable declarations");
205  data_var_decls_r
206  %= lit("data")
207  > lit('{')
208  > var_decls_g(true,data_origin) // +constraints
209  > lit('}');
210 
211  derived_data_var_decls_r.name("transformed data block");
212  derived_data_var_decls_r
213  %= ( lit("transformed")
214  >> lit("data") )
215  > lit('{')
216  > var_decls_g(true,transformed_data_origin) // -constraints
217  > *statement_g(false,transformed_data_origin,false) // -sampling
218  > lit('}');
219 
220  param_var_decls_r.name("parameter variable declarations");
221  param_var_decls_r
222  %= lit("parameters")
223  > lit('{')
224  > var_decls_g(true,parameter_origin) // +constraints
225  > lit('}');
226 
227  derived_var_decls_r.name("derived variable declarations");
228  derived_var_decls_r
229  %= ( lit("transformed")
230  >> lit("parameters") )
231  > lit('{')
232  > var_decls_g(true,transformed_parameter_origin) // -constraints
233  > *statement_g(false,transformed_parameter_origin,false) // -sampling
234  > lit('}');
235 
236  generated_var_decls_r.name("generated variable declarations");
237  generated_var_decls_r
238  %= lit("generated")
239  > lit("quantities")
240  > lit('{')
241  > var_decls_g(true,derived_origin) // -constraints
242  > *statement_g(false,derived_origin,false) // -sampling
243  > lit('}');
244 
245  using boost::spirit::qi::on_error;
246  using boost::spirit::qi::rethrow;
247  using namespace boost::spirit::qi::labels;
248 
249  on_error<rethrow>(
250  program_r,
251  program_error_f(
252  _1, _2, _3, _4 ,
253  "",
254  boost::phoenix::ref(var_map_),
255  boost::phoenix::ref(error_msgs_)
256  )
257  );
258  }
259 
260  }
261 }
262 
263 #endif
const int data_origin
Definition: ast.hpp:413
const int parameter_origin
Definition: ast.hpp:415
const int DOUBLE_T
Definition: ast.hpp:66
const int local_origin
Definition: ast.hpp:418
BOOST_FUSION_ADAPT_STRUCT(stan::gm::program,(std::vector< stan::gm::function_decl_def >, function_decl_defs_)(std::vector< stan::gm::var_decl >, data_decl_)(DUMMY_STRUCT::type, derived_data_decl_)(std::vector< stan::gm::var_decl >, parameter_decl_)(DUMMY_STRUCT::type, derived_decl_)(stan::gm::statement, statement_)(DUMMY_STRUCT::type, generated_decl_)) namespace stan
const int derived_origin
Definition: ast.hpp:417
const int model_name_origin
Definition: ast.hpp:412
const int transformed_data_origin
Definition: ast.hpp:414
const int transformed_parameter_origin
Definition: ast.hpp:416

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