summaryrefslogtreecommitdiff
path: root/boost/spirit/home/x3/support/utility/error_reporting.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/spirit/home/x3/support/utility/error_reporting.hpp')
-rw-r--r--boost/spirit/home/x3/support/utility/error_reporting.hpp241
1 files changed, 241 insertions, 0 deletions
diff --git a/boost/spirit/home/x3/support/utility/error_reporting.hpp b/boost/spirit/home/x3/support/utility/error_reporting.hpp
new file mode 100644
index 0000000000..9e65f2149b
--- /dev/null
+++ b/boost/spirit/home/x3/support/utility/error_reporting.hpp
@@ -0,0 +1,241 @@
+/*=============================================================================
+ Copyright (c) 2014 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+==============================================================================*/
+#if !defined(BOOST_SPIRIT_X3_ERROR_REPORTING_MAY_19_2014_00405PM)
+#define BOOST_SPIRIT_X3_ERROR_REPORTING_MAY_19_2014_00405PM
+
+#include <boost/filesystem/path.hpp>
+#include <boost/spirit/home/x3/support/ast/position_tagged.hpp>
+#include <ostream>
+
+// Clang-style error handling utilities
+
+namespace boost { namespace spirit { namespace x3
+{
+ template <typename Iterator>
+ class error_handler
+ {
+ public:
+
+ typedef Iterator iterator_type;
+
+ error_handler(
+ Iterator first, Iterator last, std::ostream& err_out
+ , std::string file = "", int tabs = 4)
+ : err_out(err_out)
+ , file(file)
+ , tabs(tabs)
+ , pos_cache(first, last) {}
+
+ typedef void result_type;
+
+ void operator()(Iterator err_pos, std::string const& error_message) const;
+ void operator()(Iterator err_first, Iterator err_last, std::string const& error_message) const;
+ void operator()(position_tagged pos, std::string const& message) const
+ {
+ auto where = pos_cache.position_of(pos);
+ (*this)(
+ where.begin()
+ , where.end()
+ , message
+ );
+ }
+
+ template <typename AST>
+ void tag(AST& ast, Iterator first, Iterator last)
+ {
+ return pos_cache.annotate(ast, first, last);
+ }
+//
+// void operator()(
+// Iterator first
+// , Iterator last
+// , Iterator err_op
+// , Iterator err_first
+// , Iterator err_last
+// , std::string const& error_message
+// ) const;
+
+ private:
+
+ void print_file_line(std::size_t line) const;
+ void print_line(Iterator& line_start, Iterator last) const;
+ void print_indicator(Iterator& line_start, Iterator last, char ind) const;
+ void skip_whitespace(Iterator& err_pos, Iterator last) const;
+ void skip_non_whitespace(Iterator& err_pos, Iterator last) const;
+ Iterator get_line_start(Iterator first, Iterator pos) const;
+ std::size_t position(Iterator i) const;
+
+ std::ostream& err_out;
+ std::string file;
+ int tabs;
+ position_cache<std::vector<Iterator>> pos_cache;
+ };
+
+ template <typename Iterator>
+ void error_handler<Iterator>::print_file_line(std::size_t line) const
+ {
+ namespace fs = boost::filesystem;
+
+ if (file != "")
+ err_out << "In file " << fs::path(file).generic_string() << ", ";
+ else
+ err_out << "In ";
+
+ err_out << "line " << line << ':' << std::endl;
+ }
+
+ template <typename Iterator>
+ void error_handler<Iterator>::print_line(Iterator& start, Iterator last) const
+ {
+ for (; start != last; ++start)
+ {
+ auto c = *start;
+ if (c == '\r' || c == '\n')
+ break;
+ else
+ err_out << c;
+ }
+ err_out << std::endl;
+ }
+
+ template <typename Iterator>
+ void error_handler<Iterator>::print_indicator(Iterator& start, Iterator last, char ind) const
+ {
+ for (; start != last; ++start)
+ {
+ auto c = *start;
+ if (c == '\r' || c == '\n')
+ break;
+ else if (c == '\t')
+ for (int i = 0; i < tabs; ++i)
+ err_out << ind;
+ else
+ err_out << ind;
+ }
+ }
+
+ template <typename Iterator>
+ void error_handler<Iterator>::skip_whitespace(Iterator& err_pos, Iterator last) const
+ {
+ // make sure err_pos does not point to white space
+ while (err_pos != last)
+ {
+ char c = *err_pos;
+ if (std::isspace(c))
+ ++err_pos;
+ else
+ break;
+ }
+ }
+
+ template <typename Iterator>
+ void error_handler<Iterator>::skip_non_whitespace(Iterator& err_pos, Iterator last) const
+ {
+ // make sure err_pos does not point to white space
+ while (err_pos != last)
+ {
+ char c = *err_pos;
+ if (std::isspace(c))
+ break;
+ else
+ ++err_pos;
+ }
+ }
+
+ template <class Iterator>
+ inline Iterator error_handler<Iterator>::get_line_start(Iterator first, Iterator pos) const
+ {
+ Iterator latest = first;
+ for (Iterator i = first; i != pos; ++i)
+ if (*i == '\r' || *i == '\n')
+ latest = i;
+ return latest;
+ }
+
+ template <typename Iterator>
+ std::size_t error_handler<Iterator>::position(Iterator i) const
+ {
+ // $$$ asumes iterator is similar to line_pos_iterator $$$
+ return i.position();
+ }
+
+ template <typename Iterator>
+ void error_handler<Iterator>::operator()(
+ Iterator err_pos, std::string const& error_message) const
+ {
+ Iterator first = pos_cache.first();
+ Iterator last = pos_cache.last();
+
+ // make sure err_pos does not point to white space
+ skip_whitespace(err_pos, last);
+
+ print_file_line(position(err_pos));
+ err_out << error_message << std::endl;
+
+ Iterator start = get_line_start(first, err_pos);
+ if (start != first)
+ ++start;
+ Iterator i = start;
+ print_line(i, last);
+ print_indicator(start, err_pos, '_');
+ err_out << "^_" << std::endl;
+ }
+
+ template <typename Iterator>
+ void error_handler<Iterator>::operator()(
+ Iterator err_first, Iterator err_last, std::string const& error_message) const
+ {
+ Iterator first = pos_cache.first();
+ Iterator last = pos_cache.last();
+
+ // make sure err_pos does not point to white space
+ skip_whitespace(err_first, last);
+
+ print_file_line(position(err_first));
+ err_out << error_message << std::endl;
+
+ Iterator start = get_line_start(first, err_first);
+ if (start != first)
+ ++start;
+ Iterator i = start;
+ print_line(i, last);
+ print_indicator(start, err_first, ' ');
+ print_indicator(start, err_last, '~');
+ err_out << " <<-- Here" << std::endl;
+ }
+//
+// template <typename Iterator>
+// void error_handler<Iterator>::operator()(
+// Iterator first
+// , Iterator last
+// , Iterator err_op
+// , Iterator err_first
+// , Iterator err_last
+// , std::string const& error_message
+// ) const
+// {
+// // make sure err_pos does not point to white space
+// skip_whitespace(err_first, last);
+//
+// print_file_line(position(err_pos));
+// err_out << error_message << std::endl;
+//
+// Iterator start = get_line_start(first, err_first);
+// if (start != first)
+// ++start;
+// Iterator i = start;
+// print_line(i, last);
+// print_indicator(start, err_first, ' ');
+// print_indicator(start, err_op, '~');
+// err_out << '^';
+// print_indicator(++start, err_last, '~');
+// err_out << " <<-- Here" << std::endl;
+// }
+
+}}}
+
+#endif