Stan  1.0
probability, sampling & optimization
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/classic_position_iterator.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/tuple/tuple.hpp>
19 #include <boost/variant/apply_visitor.hpp>
20 #include <boost/variant/recursive_variant.hpp>
21 
22 #include <cstddef>
23 #include <iomanip>
24 #include <iostream>
25 #include <istream>
26 #include <map>
27 #include <set>
28 #include <sstream>
29 #include <string>
30 #include <utility>
31 #include <vector>
32 #include <stdexcept>
33 
34 #include <stan/gm/ast.hpp>
35 
41 
42 namespace stan {
43 
44  namespace gm {
45 
46  bool is_space(char c) {
47  return c == ' ' || c == '\n' || c == '\r' || c == '\t';
48  }
49 
50  bool is_nonempty(std::string& s) {
51  for (size_t i = 0; i < s.size(); ++i)
52  if (!is_space(s[i]))
53  return true;
54  return false;
55  }
56 
57  // Cut and paste source for iterator & reporting pattern:
58  // http://boost-spirit.com/home/articles/qi-example
59  // /tracking-the-input-position-while-parsing/
60  // http://boost-spirit.com/dl_more/parsing_tracking_position
61  // /stream_iterator_errorposition_parsing.cpp
62  inline bool parse(std::ostream* output_stream,
63  std::istream& input,
64  const std::string& filename,
65  program& result) {
66  namespace classic = boost::spirit::classic;
67 
68  using boost::spirit::classic::position_iterator2;
69  using boost::spirit::multi_pass;
70  using boost::spirit::make_default_multi_pass;
71  using std::istreambuf_iterator;
72 
73  using boost::spirit::qi::expectation_failure;
74  using boost::spirit::classic::file_position_base;
75  using boost::spirit::qi::phrase_parse;
76 
77 
78  // iterate over stream input
79  typedef istreambuf_iterator<char> base_iterator_type;
80  typedef multi_pass<base_iterator_type> forward_iterator_type;
81  typedef position_iterator2<forward_iterator_type> pos_iterator_type;
82 
83  base_iterator_type in_begin(input);
84 
85  forward_iterator_type fwd_begin = make_default_multi_pass(in_begin);
86  forward_iterator_type fwd_end;
87 
88  pos_iterator_type position_begin(fwd_begin, fwd_end, filename);
89  pos_iterator_type position_end;
90 
93 
94  bool parse_succeeded = false;
95  try {
96  parse_succeeded = phrase_parse(position_begin,
97  position_end,
98  prog_grammar,
99  whitesp_grammar,
100  result);
101  std::string diagnostics = prog_grammar.error_msgs_.str();
102  if (output_stream && is_nonempty(diagnostics)) {
103  *output_stream << "DIAGNOSTIC(S) FROM PARSER:"
104  << std::endl
105  << diagnostics
106  << std::endl;
107  }
108  } catch (const expectation_failure<pos_iterator_type>& e) {
109  const file_position_base<std::string>& pos = e.first.get_position();
110  std::stringstream msg;
111  msg << "EXPECTATION FAILURE LOCATION: file=" << pos.file
112  << "; line=" << pos.line
113  << ", column=" << pos.column
114  << std::endl;
115  msg << std::endl << e.first.get_currentline()
116  << std::endl;
117  for (int i = 2; i < pos.column; ++i)
118  msg << ' ';
119  msg << " ^-- here"
120  << std::endl << std::endl;
121  std::string diagnostics = prog_grammar.error_msgs_.str();
122  if (output_stream && is_nonempty(diagnostics)) {
123  msg << std::endl
124  << "DIAGNOSTIC(S) FROM PARSER:"
125  << diagnostics
126  << std::endl;
127  }
128  throw std::invalid_argument(msg.str());
129 
130  } catch (const std::runtime_error& e) {
131  std::stringstream msg;
132  msg << "LOCATION: unknown" << std::endl;
133 
134  msg << "DIAGNOSTICS FROM PARSER:" << std::endl;
135  msg << prog_grammar.error_msgs_.str() << std::endl << std::endl;
136  throw std::invalid_argument(msg.str());
137  }
138 
139  bool consumed_all_input = (position_begin == position_end);
140  bool success = parse_succeeded && consumed_all_input;
141 
142  if (!success) {
143  std::stringstream msg;
144  if (!parse_succeeded)
145  msg << "PARSE DID NOT SUCCEED." << std::endl;
146  if (!consumed_all_input)
147  msg << "ERROR: non-whitespace beyond end of program:" << std::endl;
148 
149  const file_position_base<std::string>& pos
150  = position_begin.get_position();
151  msg << "LOCATION: file=" << pos.file
152  << "; line=" << pos.line
153  << ", column=" << pos.column
154  << std::endl;
155  msg << position_begin.get_currentline()
156  << std::endl;
157  for (int i = 2; i < pos.column; ++i)
158  msg << ' ';
159  msg << " ^-- starting here"
160  << std::endl << std::endl;
161 
162  msg << "DIAGNOSTICS FROM PARSER:" << std::endl;
163  msg << prog_grammar.error_msgs_.str() << std::endl << std::endl;
164 
165  throw std::invalid_argument(msg.str());
166  }
167  return true;
168  }
169 
170 
171  }
172 }
173 
174 #endif
bool is_space(char c)
Definition: parser.hpp:46
bool is_nonempty(std::string &s)
Definition: parser.hpp:50
bool parse(std::ostream *output_stream, std::istream &input, const std::string &filename, program &result)
Definition: parser.hpp:62
double e()
Return the base of the natural logarithm.
Probability, optimization and sampling library.
Definition: agrad.cpp:6
std::stringstream error_msgs_

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