File indexing completed on 2025-01-31 10:02:38
0001
0002
0003
0004
0005
0006
0007 #if !defined(BOOST_SPIRIT_X3_ERROR_REPORTING_MAY_19_2014_00405PM)
0008 #define BOOST_SPIRIT_X3_ERROR_REPORTING_MAY_19_2014_00405PM
0009
0010 #include <boost/spirit/home/x3/support/ast/position_tagged.hpp>
0011 #include <boost/spirit/home/x3/support/utility/utf8.hpp>
0012 #include <ostream>
0013
0014
0015
0016 namespace boost { namespace spirit { namespace x3
0017 {
0018
0019 struct error_handler_tag;
0020
0021 template <typename Iterator>
0022 class error_handler
0023 {
0024 public:
0025
0026 typedef Iterator iterator_type;
0027
0028 error_handler(
0029 Iterator first, Iterator last, std::ostream& err_out
0030 , std::string file = "", int tabs = 4)
0031 : err_out(err_out)
0032 , file(file)
0033 , tabs(tabs)
0034 , pos_cache(first, last) {}
0035
0036 typedef void result_type;
0037
0038 void operator()(Iterator err_pos, std::string const& error_message) const;
0039 void operator()(Iterator err_first, Iterator err_last, std::string const& error_message) const;
0040 void operator()(position_tagged pos, std::string const& message) const
0041 {
0042 auto where = pos_cache.position_of(pos);
0043 (*this)(where.begin(), where.end(), message);
0044 }
0045
0046 template <typename AST>
0047 void tag(AST& ast, Iterator first, Iterator last)
0048 {
0049 return pos_cache.annotate(ast, first, last);
0050 }
0051
0052 boost::iterator_range<Iterator> position_of(position_tagged pos) const
0053 {
0054 return pos_cache.position_of(pos);
0055 }
0056
0057 position_cache<std::vector<Iterator>> const& get_position_cache() const
0058 {
0059 return pos_cache;
0060 }
0061
0062 private:
0063
0064 void print_file_line(std::size_t line) const;
0065 void print_line(Iterator line_start, Iterator last) const;
0066 void print_indicator(Iterator& line_start, Iterator last, char ind) const;
0067 Iterator get_line_start(Iterator first, Iterator pos) const;
0068 std::size_t position(Iterator i) const;
0069
0070 std::ostream& err_out;
0071 std::string file;
0072 int tabs;
0073 position_cache<std::vector<Iterator>> pos_cache;
0074 };
0075
0076 template <typename Iterator>
0077 void error_handler<Iterator>::print_file_line(std::size_t line) const
0078 {
0079 if (file != "")
0080 {
0081 err_out << "In file " << file << ", ";
0082 }
0083 else
0084 {
0085 err_out << "In ";
0086 }
0087
0088 err_out << "line " << line << ':' << std::endl;
0089 }
0090
0091 template <typename Iterator>
0092 void error_handler<Iterator>::print_line(Iterator start, Iterator last) const
0093 {
0094 auto end = start;
0095 while (end != last)
0096 {
0097 auto c = *end;
0098 if (c == '\r' || c == '\n')
0099 break;
0100 else
0101 ++end;
0102 }
0103 typedef typename std::iterator_traits<Iterator>::value_type char_type;
0104 std::basic_string<char_type> line{start, end};
0105 err_out << x3::to_utf8(line) << std::endl;
0106 }
0107
0108 template <typename Iterator>
0109 void error_handler<Iterator>::print_indicator(Iterator& start, Iterator last, char ind) const
0110 {
0111 for (; start != last; ++start)
0112 {
0113 auto c = *start;
0114 if (c == '\r' || c == '\n')
0115 break;
0116 else if (c == '\t')
0117 for (int i = 0; i < tabs; ++i)
0118 err_out << ind;
0119 else
0120 err_out << ind;
0121 }
0122 }
0123
0124 template <class Iterator>
0125 inline Iterator error_handler<Iterator>::get_line_start(Iterator first, Iterator pos) const
0126 {
0127 Iterator latest = first;
0128 for (Iterator i = first; i != pos;)
0129 if (*i == '\r' || *i == '\n')
0130 latest = ++i;
0131 else
0132 ++i;
0133 return latest;
0134 }
0135
0136 template <typename Iterator>
0137 std::size_t error_handler<Iterator>::position(Iterator i) const
0138 {
0139 std::size_t line { 1 };
0140 typename std::iterator_traits<Iterator>::value_type prev { 0 };
0141
0142 for (Iterator pos = pos_cache.first(); pos != i; ++pos) {
0143 auto c = *pos;
0144 switch (c) {
0145 case '\n':
0146 if (prev != '\r') ++line;
0147 break;
0148 case '\r':
0149 ++line;
0150 break;
0151 default:
0152 break;
0153 }
0154 prev = c;
0155 }
0156
0157 return line;
0158 }
0159
0160 template <typename Iterator>
0161 void error_handler<Iterator>::operator()(
0162 Iterator err_pos, std::string const& error_message) const
0163 {
0164 Iterator first = pos_cache.first();
0165 Iterator last = pos_cache.last();
0166
0167 print_file_line(position(err_pos));
0168 err_out << error_message << std::endl;
0169
0170 Iterator start = get_line_start(first, err_pos);
0171 print_line(start, last);
0172 print_indicator(start, err_pos, '_');
0173 err_out << "^_" << std::endl;
0174 }
0175
0176 template <typename Iterator>
0177 void error_handler<Iterator>::operator()(
0178 Iterator err_first, Iterator err_last, std::string const& error_message) const
0179 {
0180 Iterator first = pos_cache.first();
0181 Iterator last = pos_cache.last();
0182
0183 print_file_line(position(err_first));
0184 err_out << error_message << std::endl;
0185
0186 Iterator start = get_line_start(first, err_first);
0187 print_line(start, last);
0188 print_indicator(start, err_first, ' ');
0189 print_indicator(start, err_last, '~');
0190 err_out << " <<-- Here" << std::endl;
0191 }
0192
0193 }}}
0194
0195 #endif