Stan  2.14.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  const bool allow_undefined = false) {
64  using boost::spirit::multi_pass;
65  using boost::spirit::make_default_multi_pass;
66  using std::istreambuf_iterator;
67 
68  using boost::spirit::qi::expectation_failure;
69  using boost::spirit::qi::phrase_parse;
70 
71  using boost::phoenix::construct;
72  using boost::phoenix::val;
73 
75 
76  std::ostringstream buf;
77  buf << input.rdbuf();
78  std::string stan_string = buf.str();
79 
80  typedef std::string::const_iterator input_iterator;
81  typedef boost::spirit::line_pos_iterator<input_iterator> lp_iterator;
82 
83  lp_iterator fwd_begin = lp_iterator(stan_string.begin());
84  lp_iterator fwd_end = lp_iterator(stan_string.end());
85 
86  program_grammar<lp_iterator> prog_grammar(model_name, allow_undefined);
87  whitespace_grammar<lp_iterator> whitesp_grammar;
88 
89  bool parse_succeeded = false;
90  try {
91  parse_succeeded = phrase_parse(fwd_begin,
92  fwd_end,
93  prog_grammar,
94  whitesp_grammar,
95  result);
96  std::string diagnostics = prog_grammar.error_msgs_.str();
97  if (output_stream && is_nonempty(diagnostics)) {
98  *output_stream << "DIAGNOSTIC(S) FROM PARSER:"
99  << std::endl
100  << diagnostics
101  << std::endl;
102  }
103  } catch (const expectation_failure<lp_iterator>& e) {
104  std::stringstream msg;
105  std::string diagnostics = prog_grammar.error_msgs_.str();
106  if (output_stream && is_nonempty(diagnostics)) {
107  msg << "SYNTAX ERROR, MESSAGE(S) FROM PARSER:"
108  << std::endl
109  << std::endl
110  << diagnostics;
111  }
112  if (output_stream) {
113  std::stringstream ss;
114  ss << e.what_;
115  std::string e_what = ss.str();
116  std::string angle_eps("<eps>");
117  if (e_what != angle_eps)
118  msg << "PARSER EXPECTED: "
119  << e.what_
120  << std::endl;
121  }
122  throw std::invalid_argument(msg.str());
123  } catch (const std::exception& e) {
124  std::stringstream msg;
125  msg << "PROGRAM ERROR, MESSAGE(S) FROM PARSER:"
126  << std::endl
127  << prog_grammar.error_msgs_.str()
128  << std::endl;
129 
130  throw std::invalid_argument(msg.str());
131  }
132 
133  bool consumed_all_input = (fwd_begin == fwd_end);
134  bool success = parse_succeeded && consumed_all_input;
135 
136  if (!success) {
137  std::stringstream msg;
138  if (!parse_succeeded)
139  msg << "PARSE FAILED." << std::endl;
140 
141  if (!consumed_all_input) {
142  std::basic_stringstream<char> unparsed_non_ws;
143  unparsed_non_ws << boost::make_iterator_range(fwd_begin, fwd_end);
144  msg << "PARSER EXPECTED: whitespace to end of file."
145  << std::endl
146  << "FOUND AT line "
147  << get_line(fwd_begin)
148  << ": "
149  << std::endl
150  << unparsed_non_ws.str()
151  << std::endl;
152  }
153  msg << std::endl << prog_grammar.error_msgs_.str() << std::endl;
154  throw std::invalid_argument(msg.str());
155  }
156 
157  return true;
158  }
159 
160 
161  }
162 }
163 
164 #endif
Probability, optimization and sampling library.
bool parse(std::ostream *output_stream, std::istream &input, const std::string &model_name, program &result, const bool allow_undefined=false)
Definition: parser.hpp:59
static void reset_sigs()
Reset the signature singleton to contain no instances.
bool is_space(char c)
Definition: parser.hpp:48
AST node for a complete Stan program.
Definition: program.hpp:17
bool is_nonempty(std::string &s)
Definition: parser.hpp:52

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