GG: ReportParseError.h Source File

GG

- Main Page
- Related Pages
- Namespaces
- Classes
- Files

- File List
- File Members

ReportParseError.h
Go to the documentation of this file.
1 // -*- C++ -*-
2 /* GG is a GUI for SDL and OpenGL.
3 Copyright (C) 2003-2008 T. Zachary Laine
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public License
7 as published by the Free Software Foundation; either version 2.1
8 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free
17 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18 02111-1307 USA
19
20 If you do not wish to comply with the terms of the LGPL please
21 contact the author as other terms are available for a fee.
22
23 Zach Laine
24 whatwasthataddress@gmail.com */
25
28 #ifndef _GG_ReportParseError_h_
29 #define _GG_ReportParseError_h_
30
31 #include <GG/Export.h>
32 #include <GG/LexerFwd.h>
33
34 #include <boost/algorithm/string/replace.hpp>
35 #include <boost/tuple/tuple.hpp>
36
37
38 namespace GG {
39
40 namespace detail {
41
42 inline void default_send_error_string(const std::string& str)
43 { std::cerr << str; }
44
45 extern GG_API const char* s_filename;
46 extern GG_API text_iterator* s_text_it;
47 extern GG_API text_iterator s_begin;
48 extern GG_API text_iterator s_end;
49
50 }
51
52 template <typename TokenType>
53 struct report_error_
54 {
55 template <typename Arg1, typename Arg2, typename Arg3, typename Arg4>
56 struct result
57 { typedef void type; };
58
59 template <typename Arg1, typename Arg2, typename Arg3, typename Arg4>
60 void operator()(Arg1 first, Arg2, Arg3 it, Arg4 rule_name) const
61 {
62 std::string error_string;
63 generate_error_string(first, it, rule_name, error_string);
64 send_error_string(error_string);
65 }
66
67 static boost::function<void (const std::string&)> send_error_string;
68
69 private:
70 std::pair<text_iterator, unsigned int> line_start_and_line_number(text_iterator error_position) const
71 {
72 unsigned int line = 1;
73 text_iterator it = detail::s_begin;
74 text_iterator line_start = detail::s_begin;
75 while (it != error_position) {
76 bool eol = false;
77 if (it != error_position && *it == '\r') {
78 eol = true;
79 line_start = ++it;
80 }
81 if (it != error_position && *it == '\n') {
82 eol = true;
83 line_start = ++it;
84 }
85 if (eol)
86 ++line;
87 else
88 ++it;
89 }
90 return std::pair<text_iterator, unsigned int>(line_start, line);
91 }
92
93 std::string get_line(text_iterator line_start) const
94 {
95 text_iterator line_end = line_start;
96 while (line_end != detail::s_end && *line_end != '\r' && *line_end != '\n') {
97 ++line_end;
98 }
99 return std::string(line_start, line_end);
100 }
101
102 template <typename TokenIter>
103 void generate_error_string(const TokenIter& first,
104 const TokenIter& it,
105 const boost::spirit::info& rule_name,
106 std::string& str) const
107 {
108 std::stringstream is;
109
110 GG::text_iterator line_start;
111 unsigned int line_number;
112 GG::text_iterator text_it = it->matched().begin();
113 if (it->matched().begin() == it->matched().end()) {
114 text_it = *detail::s_text_it;
115 if (text_it != detail::s_end)
116 ++text_it;
117 }
118 boost::tie(line_start, line_number) = line_start_and_line_number(text_it);
119 std::size_t column_number = std::distance(line_start, text_it);
120
121 is << detail::s_filename << ":" << line_number << ":" << column_number << ": "
122 << "Parse error: expected " << rule_name;
123
124 if (text_it == detail::s_end) {
125 is << " before end of input.\n";
126 } else {
127 is << " here:\n"
128 << " " << get_line(line_start) << "\n"
129 << " " << std::string(column_number, ' ') << '^' << std::endl;
130 }
131
132 str = is.str();
133 }
134 };
135
136 template <typename TokenType>
137 boost::function<void (const std::string&)> report_error_<TokenType>::send_error_string =
138 &detail::default_send_error_string;
139
140 }
141
142 #endif