1 /*=============================================================================
2     Copyright (c) 2001-2011 Joel de Guzman
3     Copyright (c) 2001-2011 Hartmut Kaiser
4 
5     Distributed under the Boost Software License, Version 1.0. (See accompanying
6     file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 =============================================================================*/
8 #if !defined(BOOST_SPIRIT_CONJURE_ERROR_HANDLER_HPP)
9 #define BOOST_SPIRIT_CONJURE_ERROR_HANDLER_HPP
10 
11 #include <iostream>
12 #include <string>
13 #include <vector>
14 
15 namespace client
16 {
17     ///////////////////////////////////////////////////////////////////////////////
18     //  The error handler
19     ///////////////////////////////////////////////////////////////////////////////
20     template <typename BaseIterator, typename Iterator>
21     struct error_handler
22     {
23         template <typename, typename, typename>
24         struct result { typedef void type; };
25 
error_handlerclient::error_handler26         error_handler(BaseIterator first, BaseIterator last)
27           : first(first), last(last) {}
28 
29         template <typename Message, typename What>
operator ()client::error_handler30         void operator()(
31             Message const& message,
32             What const& what,
33             Iterator err_pos) const
34         {
35             // retrieve underlying iterator from current token, err_pos points
36             // to the last validly matched token, so we use its end iterator
37             // as the error position
38             BaseIterator err_pos_base = err_pos->matched().end();
39             std::cout << message << what << std::endl;
40             if (err_pos_base != BaseIterator())
41                 dump_error_line(err_pos_base);
42         }
43 
dump_error_lineclient::error_handler44         void dump_error_line(BaseIterator err_pos_base) const
45         {
46             int line;
47             BaseIterator line_start = get_pos(err_pos_base, line);
48             if (err_pos_base != last)
49             {
50                 std::cout << " line " << line << ':' << std::endl;
51                 std::cout << get_line(line_start) << std::endl;
52                 for (; line_start != err_pos_base; ++line_start)
53                     std::cout << ' ';
54                 std::cout << '^' << std::endl;
55             }
56             else
57             {
58                 std::cout << "Unexpected end of file.\n";
59             }
60 
61         }
62 
get_posclient::error_handler63         BaseIterator get_pos(BaseIterator err_pos, int& line) const
64         {
65             line = 1;
66             BaseIterator i = first;
67             BaseIterator line_start = first;
68             while (i != err_pos)
69             {
70                 bool eol = false;
71                 if (i != err_pos && *i == '\r') // CR
72                 {
73                     eol = true;
74                     line_start = ++i;
75                 }
76                 if (i != err_pos && *i == '\n') // LF
77                 {
78                     eol = true;
79                     line_start = ++i;
80                 }
81                 if (eol)
82                     ++line;
83                 else
84                     ++i;
85             }
86             return line_start;
87         }
88 
get_lineclient::error_handler89         std::string get_line(BaseIterator err_pos) const
90         {
91             BaseIterator i = err_pos;
92             // position i to the next EOL
93             while (i != last && (*i != '\r' && *i != '\n'))
94                 ++i;
95             return std::string(err_pos, i);
96         }
97 
98         BaseIterator first;
99         BaseIterator last;
100         std::vector<Iterator> iters;
101     };
102 }
103 
104 #endif
105 
106