GG

Token.h

Go to the documentation of this file.
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_