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