Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-31 10:02:38

0001 /*=============================================================================
0002     Copyright (c) 2014 Joel de Guzman
0003 
0004     Distributed under the Boost Software License, Version 1.0. (See accompanying
0005     file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
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 // Clang-style error handling utilities
0015 
0016 namespace boost { namespace spirit { namespace x3
0017 {
0018     // tag used to get our error handler from the context
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