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

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