28 #ifndef _GG_ReportParseError_h_
29 #define _GG_ReportParseError_h_
34 #include <boost/algorithm/string/replace.hpp>
35 #include <boost/tuple/tuple.hpp>
42 inline void default_send_error_string(
const std::string& str)
45 extern GG_API
const char* s_filename;
46 extern GG_API text_iterator* s_text_it;
47 extern GG_API text_iterator s_begin;
48 extern GG_API text_iterator s_end;
52 template <
typename TokenType>
55 template <
typename Arg1,
typename Arg2,
typename Arg3,
typename Arg4>
57 {
typedef void type; };
59 template <
typename Arg1,
typename Arg2,
typename Arg3,
typename Arg4>
60 void operator()(Arg1 first, Arg2, Arg3 it, Arg4 rule_name)
const
62 std::string error_string;
63 generate_error_string(first, it, rule_name, error_string);
64 send_error_string(error_string);
67 static boost::function<void (const std::string&)> send_error_string;
70 std::pair<text_iterator, unsigned int> line_start_and_line_number(text_iterator error_position)
const
72 unsigned int line = 1;
73 text_iterator it = detail::s_begin;
74 text_iterator line_start = detail::s_begin;
75 while (it != error_position) {
77 if (it != error_position && *it ==
'\r') {
81 if (it != error_position && *it ==
'\n') {
90 return std::pair<text_iterator, unsigned int>(line_start, line);
93 std::string get_line(text_iterator line_start)
const
95 text_iterator line_end = line_start;
96 while (line_end != detail::s_end && *line_end !=
'\r' && *line_end !=
'\n') {
99 return std::string(line_start, line_end);
102 template <
typename TokenIter>
103 void generate_error_string(
const TokenIter& first,
105 const boost::spirit::info& rule_name,
106 std::string& str)
const
108 std::stringstream is;
110 GG::text_iterator line_start;
111 unsigned int line_number;
112 GG::text_iterator text_it = it->matched().begin();
113 if (it->matched().begin() == it->matched().end()) {
114 text_it = *detail::s_text_it;
115 if (text_it != detail::s_end)
118 boost::tie(line_start, line_number) = line_start_and_line_number(text_it);
119 std::size_t column_number = std::distance(line_start, text_it);
121 is << detail::s_filename <<
":" << line_number <<
":" << column_number <<
": "
122 <<
"Parse error: expected " << rule_name;
124 if (text_it == detail::s_end) {
125 is <<
" before end of input.\n";
128 <<
" " << get_line(line_start) <<
"\n"
129 <<
" " << std::string(column_number,
' ') <<
'^' << std::endl;
136 template <
typename TokenType>
137 boost::function<void (const std::string&)> report_error_<TokenType>::send_error_string =
138 &detail::default_send_error_string;