Stan  2.5.0
probability, sampling & optimization
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
parser.hpp
Go to the documentation of this file.
1 #ifndef STAN__GM__PARSER__PARSER__HPP
2 #define STAN__GM__PARSER__PARSER__HPP
3 
4 #include <boost/lexical_cast.hpp>
5 #include <boost/fusion/include/adapt_struct.hpp>
6 #include <boost/fusion/include/std_pair.hpp>
7 #include <boost/config/warning_disable.hpp>
8 #include <boost/spirit/include/qi.hpp>
9 #include <boost/spirit/include/qi_numeric.hpp>
10 #include <boost/spirit/include/phoenix_core.hpp>
11 #include <boost/spirit/include/phoenix_function.hpp>
12 #include <boost/spirit/include/phoenix_fusion.hpp>
13 #include <boost/spirit/include/phoenix_object.hpp>
14 #include <boost/spirit/include/phoenix_operator.hpp>
15 #include <boost/spirit/include/phoenix_stl.hpp>
16 #include <boost/spirit/include/support_multi_pass.hpp>
17 #include <boost/tuple/tuple.hpp>
18 #include <boost/variant/apply_visitor.hpp>
19 #include <boost/variant/recursive_variant.hpp>
20 
21 #include <boost/spirit/include/version.hpp>
22 #include <boost/spirit/home/support/iterators/line_pos_iterator.hpp>
23 
24 #include <cstddef>
25 #include <iomanip>
26 #include <iostream>
27 #include <istream>
28 #include <iterator>
29 #include <map>
30 #include <set>
31 #include <sstream>
32 #include <string>
33 #include <utility>
34 #include <vector>
35 #include <stdexcept>
36 
37 #include <stan/gm/ast.hpp>
38 
45 
46 namespace stan {
47 
48  namespace gm {
49 
50  bool is_space(char c) {
51  return c == ' ' || c == '\n' || c == '\r' || c == '\t';
52  }
53 
54  bool is_nonempty(std::string& s) {
55  for (size_t i = 0; i < s.size(); ++i)
56  if (!is_space(s[i]))
57  return true;
58  return false;
59  }
60 
61  inline bool parse(std::ostream* output_stream,
62  std::istream& input,
63  const std::string& filename,
64  const std::string& model_name,
65  program& result) {
66 
67  using boost::spirit::multi_pass;
68  using boost::spirit::make_default_multi_pass;
69  using std::istreambuf_iterator;
70 
71  using boost::spirit::qi::expectation_failure;
72  using boost::spirit::qi::phrase_parse;
73 
74  using boost::phoenix::construct;
75  using boost::phoenix::val;
76 
78 
79  std::ostringstream buf;
80  buf << input.rdbuf();
81  std::string stan_string = buf.str();
82 
83  typedef std::string::const_iterator input_iterator;
84  typedef boost::spirit::line_pos_iterator<input_iterator> lp_iterator;
85 
86  lp_iterator fwd_begin = lp_iterator (stan_string.begin());
87  lp_iterator fwd_end = lp_iterator (stan_string.end());
88 
89  program_grammar<lp_iterator> prog_grammar(model_name);
90  whitespace_grammar<lp_iterator> whitesp_grammar;
91 
92  bool parse_succeeded = false;
93  try {
94  parse_succeeded = phrase_parse(fwd_begin,
95  fwd_end,
96  prog_grammar,
97  whitesp_grammar,
98  result);
99  std::string diagnostics = prog_grammar.error_msgs_.str();
100  if (output_stream && is_nonempty(diagnostics)) {
101  *output_stream << "DIAGNOSTIC(S) FROM PARSER:"
102  << std::endl
103  << diagnostics
104  << std::endl;
105  }
106  } catch (const expectation_failure<lp_iterator>& e) {
107 
108  std::stringstream msg;
109  std::string diagnostics = prog_grammar.error_msgs_.str();
110  if (output_stream && is_nonempty(diagnostics)) {
111  msg << "SYNTAX ERROR, MESSAGE(S) FROM PARSER:"
112  << std::endl
113  << diagnostics
114  << std::endl;
115  }
116 
117  throw std::invalid_argument(msg.str());
118 
119  } catch (const std::runtime_error& e) {
120  std::stringstream msg;
121  msg << "PROGRAM ERROR, MESSAGE(S) FROM PARSER:"
122  << std::endl
123  << prog_grammar.error_msgs_.str()
124  << std::endl;
125 
126  throw std::invalid_argument(msg.str());
127  }
128 
129  bool consumed_all_input = (fwd_begin == fwd_end);
130  bool success = parse_succeeded && consumed_all_input;
131 
132  if (!success) {
133 
134  std::stringstream msg;
135  if (!parse_succeeded)
136  msg << "PARSE FAILED." << std::endl;
137  if (!consumed_all_input) {
138  // get rest of program
139  std::basic_stringstream<char> unparsed_non_ws;
140  unparsed_non_ws << boost::make_iterator_range(fwd_begin, fwd_end);
141  // get next two lines (if possible)
142  msg << "PARSING HALTED AT LINE "
143  << get_line(fwd_begin)
144  << std::endl
145  << "UNPARSED STAN PROGRAM: "
146  << std::endl
147  << unparsed_non_ws.str()
148  << std::endl;
149  }
150  msg << std::endl << prog_grammar.error_msgs_.str() << std::endl;
151  throw std::invalid_argument(msg.str());
152  }
153  return true;
154  }
155 
156 
157  }
158 }
159 
160 #endif
bool is_space(char c)
Definition: parser.hpp:50
bool parse(std::ostream *output_stream, std::istream &input, const std::string &filename, const std::string &model_name, program &result)
Definition: parser.hpp:61
double e()
Return the base of the natural logarithm.
Definition: constants.hpp:86
bool is_nonempty(std::string &s)
Definition: parser.hpp:54

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