]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/boost/spirit/home/x3/support/utility/error_reporting.hpp
import quincy beta 17.1.0
[ceph.git] / ceph / src / boost / boost / spirit / home / x3 / support / utility / error_reporting.hpp
CommitLineData
7c673cae
FG
1/*=============================================================================
2 Copyright (c) 2014 Joel de Guzman
3
4 Distributed under the Boost Software License, Version 1.0. (See accompanying
5 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6==============================================================================*/
7#if !defined(BOOST_SPIRIT_X3_ERROR_REPORTING_MAY_19_2014_00405PM)
8#define BOOST_SPIRIT_X3_ERROR_REPORTING_MAY_19_2014_00405PM
9
7c673cae 10#include <boost/spirit/home/x3/support/ast/position_tagged.hpp>
20effc67 11#include <boost/spirit/home/x3/support/utility/utf8.hpp>
7c673cae
FG
12#include <ostream>
13
14// Clang-style error handling utilities
15
16namespace boost { namespace spirit { namespace x3
17{
18 // tag used to get our error handler from the context
19 struct error_handler_tag;
20
21 template <typename Iterator>
22 class error_handler
23 {
24 public:
25
26 typedef Iterator iterator_type;
27
28 error_handler(
29 Iterator first, Iterator last, std::ostream& err_out
30 , std::string file = "", int tabs = 4)
31 : err_out(err_out)
32 , file(file)
33 , tabs(tabs)
34 , pos_cache(first, last) {}
35
36 typedef void result_type;
37
38 void operator()(Iterator err_pos, std::string const& error_message) const;
39 void operator()(Iterator err_first, Iterator err_last, std::string const& error_message) const;
40 void operator()(position_tagged pos, std::string const& message) const
41 {
42 auto where = pos_cache.position_of(pos);
43 (*this)(where.begin(), where.end(), message);
44 }
45
46 template <typename AST>
47 void tag(AST& ast, Iterator first, Iterator last)
48 {
49 return pos_cache.annotate(ast, first, last);
50 }
51
52 boost::iterator_range<Iterator> position_of(position_tagged pos) const
53 {
54 return pos_cache.position_of(pos);
55 }
56
92f5a8d4
TL
57 position_cache<std::vector<Iterator>> const& get_position_cache() const
58 {
59 return pos_cache;
60 }
61
7c673cae
FG
62 private:
63
64 void print_file_line(std::size_t line) const;
65 void print_line(Iterator line_start, Iterator last) const;
66 void print_indicator(Iterator& line_start, Iterator last, char ind) const;
67 void skip_whitespace(Iterator& err_pos, Iterator last) const;
68 void skip_non_whitespace(Iterator& err_pos, Iterator last) const;
69 Iterator get_line_start(Iterator first, Iterator pos) const;
70 std::size_t position(Iterator i) const;
71
72 std::ostream& err_out;
73 std::string file;
74 int tabs;
75 position_cache<std::vector<Iterator>> pos_cache;
76 };
77
78 template <typename Iterator>
79 void error_handler<Iterator>::print_file_line(std::size_t line) const
80 {
81 if (file != "")
82 {
7c673cae 83 err_out << "In file " << file << ", ";
7c673cae
FG
84 }
85 else
86 {
87 err_out << "In ";
88 }
89
90 err_out << "line " << line << ':' << std::endl;
91 }
92
93 template <typename Iterator>
94 void error_handler<Iterator>::print_line(Iterator start, Iterator last) const
95 {
96 auto end = start;
97 while (end != last)
98 {
99 auto c = *end;
100 if (c == '\r' || c == '\n')
101 break;
102 else
103 ++end;
104 }
105 typedef typename std::iterator_traits<Iterator>::value_type char_type;
106 std::basic_string<char_type> line{start, end};
20effc67 107 err_out << x3::to_utf8(line) << std::endl;
7c673cae
FG
108 }
109
110 template <typename Iterator>
111 void error_handler<Iterator>::print_indicator(Iterator& start, Iterator last, char ind) const
112 {
113 for (; start != last; ++start)
114 {
115 auto c = *start;
116 if (c == '\r' || c == '\n')
117 break;
118 else if (c == '\t')
119 for (int i = 0; i < tabs; ++i)
120 err_out << ind;
121 else
122 err_out << ind;
123 }
124 }
125
126 template <typename Iterator>
127 void error_handler<Iterator>::skip_whitespace(Iterator& err_pos, Iterator last) const
128 {
129 // make sure err_pos does not point to white space
130 while (err_pos != last)
131 {
132 char c = *err_pos;
133 if (std::isspace(c))
134 ++err_pos;
135 else
136 break;
137 }
138 }
139
140 template <typename Iterator>
141 void error_handler<Iterator>::skip_non_whitespace(Iterator& err_pos, Iterator last) const
142 {
143 // make sure err_pos does not point to white space
144 while (err_pos != last)
145 {
146 char c = *err_pos;
147 if (std::isspace(c))
148 break;
149 else
150 ++err_pos;
151 }
152 }
153
154 template <class Iterator>
155 inline Iterator error_handler<Iterator>::get_line_start(Iterator first, Iterator pos) const
156 {
157 Iterator latest = first;
158 for (Iterator i = first; i != pos; ++i)
159 if (*i == '\r' || *i == '\n')
160 latest = i;
161 return latest;
162 }
163
164 template <typename Iterator>
165 std::size_t error_handler<Iterator>::position(Iterator i) const
166 {
167 std::size_t line { 1 };
168 typename std::iterator_traits<Iterator>::value_type prev { 0 };
169
170 for (Iterator pos = pos_cache.first(); pos != i; ++pos) {
171 auto c = *pos;
172 switch (c) {
173 case '\n':
174 if (prev != '\r') ++line;
175 break;
176 case '\r':
11fdf7f2 177 ++line;
7c673cae
FG
178 break;
179 default:
180 break;
181 }
182 prev = c;
183 }
184
185 return line;
186 }
187
188 template <typename Iterator>
189 void error_handler<Iterator>::operator()(
190 Iterator err_pos, std::string const& error_message) const
191 {
192 Iterator first = pos_cache.first();
193 Iterator last = pos_cache.last();
194
195 // make sure err_pos does not point to white space
196 skip_whitespace(err_pos, last);
197
198 print_file_line(position(err_pos));
199 err_out << error_message << std::endl;
200
201 Iterator start = get_line_start(first, err_pos);
202 if (start != first)
203 ++start;
204 print_line(start, last);
205 print_indicator(start, err_pos, '_');
206 err_out << "^_" << std::endl;
207 }
208
209 template <typename Iterator>
210 void error_handler<Iterator>::operator()(
211 Iterator err_first, Iterator err_last, std::string const& error_message) const
212 {
213 Iterator first = pos_cache.first();
214 Iterator last = pos_cache.last();
215
216 // make sure err_pos does not point to white space
217 skip_whitespace(err_first, last);
218
219 print_file_line(position(err_first));
220 err_out << error_message << std::endl;
221
222 Iterator start = get_line_start(first, err_first);
223 if (start != first)
224 ++start;
225 print_line(start, last);
226 print_indicator(start, err_first, ' ');
227 print_indicator(start, err_last, '~');
228 err_out << " <<-- Here" << std::endl;
229 }
230
231}}}
232
233#endif