GG
|
00001 // -*- C++ -*- 00002 /* GG is a GUI for SDL and OpenGL. 00003 Copyright (C) 2003-2008 T. Zachary Laine 00004 00005 This library is free software; you can redistribute it and/or 00006 modify it under the terms of the GNU Lesser General Public License 00007 as published by the Free Software Foundation; either version 2.1 00008 of the License, or (at your option) any later version. 00009 00010 This library is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 Lesser General Public License for more details. 00014 00015 You should have received a copy of the GNU Lesser General Public 00016 License along with this library; if not, write to the Free 00017 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 00018 02111-1307 USA 00019 00020 If you do not wish to comply with the terms of the LGPL please 00021 contact the author as other terms are available for a fee. 00022 00023 Zach Laine 00024 whatwasthataddress@gmail.com */ 00025 00028 #ifndef _GG_Token_h_ 00029 #define _GG_Token_h_ 00030 00031 #include <boost/spirit/home/lex/lexer/terminals.hpp> 00032 #include <boost/spirit/home/lex/lexer/lexertl/token.hpp> 00033 00034 00035 namespace GG { 00036 00037 template <typename Iter = const char*, 00038 typename AttributeTypes = boost::mpl::vector0<>, 00039 typename HasState = boost::mpl::true_> 00040 struct position_tracking_token : 00041 boost::spirit::lex::lexertl::token<Iter, AttributeTypes, HasState> 00042 { 00043 typedef boost::spirit::lex::lexertl::token<Iter, AttributeTypes, HasState> base; 00044 typedef typename base::iterator_type iterator_type; 00045 typedef typename base::has_state has_state; 00046 typedef typename base::id_type id_type; 00047 typedef typename base::token_value_type token_value_type; 00048 00049 // default constructed tokens correspond to EOI tokens 00050 position_tracking_token() : 00051 base(), 00052 m_matched_range(), 00053 m_line_number(std::numeric_limits<std::size_t>::max()), 00054 m_line_start() 00055 {} 00056 00057 // construct an invalid token 00058 explicit position_tracking_token(int i) : 00059 base(i), 00060 m_matched_range(), 00061 m_line_number(std::numeric_limits<std::size_t>::max()), 00062 m_line_start() 00063 {} 00064 00065 position_tracking_token(id_type id, std::size_t size) : 00066 base(id, size), 00067 m_matched_range(), 00068 m_line_number(std::numeric_limits<std::size_t>::max()), 00069 m_line_start() 00070 {} 00071 00072 position_tracking_token(id_type id, std::size_t size, token_value_type tvt) : 00073 base(id, size, tvt), 00074 m_matched_range(), 00075 m_line_number(std::numeric_limits<std::size_t>::max()), 00076 m_line_start() 00077 {} 00078 00079 position_tracking_token(id_type id, std::size_t size, const Iter& first, const Iter& last) : 00080 base(id, size, first, last), 00081 m_matched_range(first, last), 00082 m_line_number(std::numeric_limits<std::size_t>::max()), 00083 m_line_start() 00084 {} 00085 00086 const char* filename() const 00087 { return s_filename; } 00088 00089 const std::pair<Iter, Iter>& matched_range() const 00090 { return m_matched_range; } 00091 00092 std::size_t line_number() const 00093 { 00094 line_start(); 00095 return m_line_number; 00096 } 00097 00098 Iter line_start() const 00099 { 00100 if (m_line_number == std::numeric_limits<std::size_t>::max()) { 00101 m_line_number = std::count(s_begin, m_matched_range.first, '\n'); 00102 Iter it = m_matched_range.first; 00103 for (; it != s_begin; --it) { 00104 if (*it == '\n') { 00105 ++it; 00106 break; 00107 } 00108 } 00109 m_line_start = it; 00110 } 00111 return m_line_start; 00112 } 00113 00114 static const char* s_filename; 00115 static Iter s_begin; 00116 00117 private: 00118 std::pair<Iter, Iter> m_matched_range; 00119 mutable std::size_t m_line_number; 00120 mutable Iter m_line_start; 00121 }; 00122 00123 template <typename Iter, typename AttributeTypes, typename HasState> 00124 const char* position_tracking_token<Iter, AttributeTypes, HasState>::s_filename = 0; 00125 00126 template <typename Iter, typename AttributeTypes, typename HasState> 00127 Iter position_tracking_token<Iter, AttributeTypes, HasState>::s_begin; 00128 00129 template <typename Iter, typename AttributeTypes, typename HasState> 00130 inline bool 00131 operator==(const position_tracking_token<Iter, AttributeTypes, HasState>& lhs, 00132 const position_tracking_token<Iter, AttributeTypes, HasState>& rhs) 00133 { return lhs.id() == rhs.id(); } 00134 00135 template <typename Iter, typename AttributeTypes, typename HasState> 00136 inline bool 00137 token_is_valid(const position_tracking_token<Iter, AttributeTypes, HasState>& t) 00138 { return t.is_valid(); } 00139 00140 } 00141 00142 namespace boost { namespace spirit { namespace traits 00143 { 00144 template <typename Attribute, typename Iter, typename AttributeTypes, typename HasState> 00145 struct assign_to_attribute_from_value<Attribute, 00146 GG::position_tracking_token<Iter, AttributeTypes, HasState> > 00147 { 00148 static void 00149 call(const GG::position_tracking_token<Iter, AttributeTypes, HasState>& t, Attribute& attr) 00150 { 00151 if (0 == t.value().which()) { 00152 typedef iterator_range<Iter> iterpair_type; 00153 const iterpair_type& ip = get<iterpair_type>(t.value()); 00154 spirit::traits::assign_to(ip.begin(), ip.end(), attr); 00155 typedef GG::position_tracking_token<Iter, AttributeTypes, HasState> token_type; 00156 const_cast<token_type&>(t).value() = attr; 00157 } else { 00158 spirit::traits::assign_to(get<Attribute>(t.value()), attr); 00159 } 00160 } 00161 }; 00162 00163 template <typename Attribute, typename Iter, typename HasState> 00164 struct assign_to_attribute_from_value<Attribute, 00165 GG::position_tracking_token<Iter, mpl::vector0<>, HasState> > 00166 { 00167 static void 00168 call(const GG::position_tracking_token<Iter, mpl::vector0<>, HasState>& t, Attribute& attr) 00169 { spirit::traits::assign_to(t.value().begin(), t.value().end(), attr); } 00170 }; 00171 00172 template <typename Attribute, typename Iter, typename HasState> 00173 struct assign_to_attribute_from_value<Attribute, 00174 GG::position_tracking_token<Iter, mpl::vector<>, HasState> > 00175 { 00176 static void 00177 call(const GG::position_tracking_token<Iter, mpl::vector<>, HasState>& t, Attribute& attr) 00178 { spirit::traits::assign_to(t.value().begin(), t.value().end(), attr); } 00179 }; 00180 00181 template <typename Attribute, typename Iter, typename HasState> 00182 struct assign_to_attribute_from_value<Attribute, 00183 GG::position_tracking_token<Iter, lex::omit, HasState> > 00184 { 00185 static void 00186 call(const GG::position_tracking_token<Iter, lex::omit, HasState>& t, Attribute& attr) 00187 {} 00188 }; 00189 00190 template <typename Iter, typename AttributeTypes, typename HasState> 00191 struct assign_to_attribute_from_value< 00192 fusion::vector2<std::size_t, iterator_range<Iter> >, 00193 GG::position_tracking_token<Iter, AttributeTypes, HasState> > 00194 { 00195 static void 00196 call(const GG::position_tracking_token<Iter, AttributeTypes, HasState>& t, 00197 fusion::vector2<std::size_t, iterator_range<Iter> >& attr) 00198 { 00199 typedef iterator_range<Iter> iterpair_type; 00200 typedef fusion::vector2<std::size_t, iterator_range<Iter> > attribute_type; 00201 const iterpair_type& ip = get<iterpair_type>(t.value()); 00202 attr = attribute_type(t.id(), get<iterpair_type>(t.value())); 00203 } 00204 }; 00205 00206 template <typename Iter, typename Attribute, typename HasState> 00207 struct token_printer_debug<GG::position_tracking_token<Iter, Attribute, HasState> > 00208 { 00209 typedef GG::position_tracking_token<Iter, Attribute, HasState> token_type; 00210 template <typename Out> 00211 static void print(Out& out, const token_type& val) 00212 { 00213 out << '<'; 00214 spirit::traits::print_token(out, val.value()); 00215 out << '>'; 00216 } 00217 }; 00218 00219 } } } 00220 00221 #endif // _GG_Token_h_