diff options
Diffstat (limited to '3rdParty/Boost/src/boost/spirit/home/lex/lexer/lexertl/token.hpp')
-rw-r--r-- | 3rdParty/Boost/src/boost/spirit/home/lex/lexer/lexertl/token.hpp | 654 |
1 files changed, 654 insertions, 0 deletions
diff --git a/3rdParty/Boost/src/boost/spirit/home/lex/lexer/lexertl/token.hpp b/3rdParty/Boost/src/boost/spirit/home/lex/lexer/lexertl/token.hpp new file mode 100644 index 0000000..90961af --- /dev/null +++ b/3rdParty/Boost/src/boost/spirit/home/lex/lexer/lexertl/token.hpp @@ -0,0 +1,654 @@ +// Copyright (c) 2001-2011 Hartmut Kaiser +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#if !defined(BOOST_SPIRIT_LEX_TOKEN_FEB_10_2008_0751PM) +#define BOOST_SPIRIT_LEX_TOKEN_FEB_10_2008_0751PM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/config.hpp> +#include <boost/detail/workaround.hpp> +#include <boost/spirit/home/qi/detail/assign_to.hpp> +#include <boost/spirit/home/support/attributes.hpp> +#include <boost/spirit/home/support/argument.hpp> +#include <boost/spirit/home/support/detail/lexer/generator.hpp> +#include <boost/spirit/home/support/detail/lexer/rules.hpp> +#include <boost/spirit/home/support/detail/lexer/consts.hpp> +#include <boost/spirit/home/support/utree/utree_traits_fwd.hpp> +#include <boost/spirit/home/lex/lexer/terminals.hpp> +#include <boost/fusion/include/vector.hpp> +#include <boost/fusion/include/at.hpp> +#include <boost/fusion/include/value_at.hpp> +#include <boost/detail/iterator.hpp> +#include <boost/variant.hpp> +#include <boost/mpl/bool.hpp> +#include <boost/mpl/vector.hpp> +#include <boost/mpl/is_sequence.hpp> +#include <boost/mpl/begin.hpp> +#include <boost/mpl/insert.hpp> +#include <boost/mpl/vector.hpp> +#include <boost/mpl/if.hpp> +#include <boost/mpl/or.hpp> +#include <boost/type_traits/is_same.hpp> +#include <boost/range/iterator_range.hpp> +#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) +#include <boost/static_assert.hpp> +#endif + +#if defined(BOOST_SPIRIT_DEBUG) +#include <iosfwd> +#endif + +namespace boost { namespace spirit { namespace lex { namespace lexertl +{ + /////////////////////////////////////////////////////////////////////////// + // + // The token is the type of the objects returned by default by the + // iterator. + // + // template parameters: + // Iterator The type of the iterator used to access the + // underlying character stream. + // AttributeTypes A mpl sequence containing the types of all + // required different token values to be supported + // by this token type. + // HasState A mpl::bool_ indicating, whether this token type + // should support lexer states. + // Idtype The type to use for the token id (defaults to + // std::size_t). + // + // It is possible to use other token types with the spirit::lex + // framework as well. If you plan to use a different type as your token + // type, you'll need to expose the following things from your token type + // to make it compatible with spirit::lex: + // + // typedefs + // iterator_type The type of the iterator used to access the + // underlying character stream. + // + // id_type The type of the token id used. + // + // methods + // default constructor + // This should initialize the token as an end of + // input token. + // constructors The prototype of the other required + // constructors should be: + // + // token(int) + // This constructor should initialize the token as + // an invalid token (not carrying any specific + // values) + // + // where: the int is used as a tag only and its value is + // ignored + // + // and: + // + // token(Idtype id, std::size_t state, + // iterator_type first, iterator_type last); + // + // where: id: token id + // state: lexer state this token was matched in + // first, last: pair of iterators marking the matched + // range in the underlying input stream + // + // accessors + // id() return the token id of the matched input sequence + // id(newid) set the token id of the token instance + // + // state() return the lexer state this token was matched in + // + // value() return the token value + // + // Additionally, you will have to implement a couple of helper functions + // in the same namespace as the token type: a comparison operator==() to + // compare your token instances, a token_is_valid() function and different + // specializations of the Spirit customization point + // assign_to_attribute_from_value as shown below. + // + /////////////////////////////////////////////////////////////////////////// + template <typename Iterator = char const* + , typename AttributeTypes = mpl::vector0<> + , typename HasState = mpl::true_ + , typename Idtype = std::size_t> + struct token; + + /////////////////////////////////////////////////////////////////////////// + // This specialization of the token type doesn't contain any item data and + // doesn't support working with lexer states. + /////////////////////////////////////////////////////////////////////////// + template <typename Iterator, typename Idtype> + struct token<Iterator, lex::omit, mpl::false_, Idtype> + { + typedef Iterator iterator_type; + typedef mpl::false_ has_state; + typedef Idtype id_type; + typedef unused_type token_value_type; + + // default constructed tokens correspond to EOI tokens + token() : id_(id_type(boost::lexer::npos)) {} + + // construct an invalid token + explicit token(int) : id_(id_type(0)) {} + + token(id_type id, std::size_t) : id_(id) {} + + token(id_type id, std::size_t, token_value_type) + : id_(id) {} + + token_value_type& value() { static token_value_type u; return u; } + token_value_type const& value() const { return unused; } + +#if defined(BOOST_SPIRIT_DEBUG) + token(id_type id, std::size_t, Iterator const& first + , Iterator const& last) + : matched_(first, last) + , id_(id) {} +#else + token(id_type id, std::size_t, Iterator const&, Iterator const&) + : id_(id) {} +#endif + + // this default conversion operator is needed to allow the direct + // usage of tokens in conjunction with the primitive parsers defined + // in Qi + operator id_type() const { return id_; } + + // Retrieve or set the token id of this token instance. + id_type id() const { return id_; } + void id(id_type newid) { id_ = newid; } + + std::size_t state() const { return 0; } // always '0' (INITIAL state) + + bool is_valid() const + { + return 0 != id_ && id_type(boost::lexer::npos) != id_; + } + +#if defined(BOOST_SPIRIT_DEBUG) +#if BOOST_WORKAROUND(BOOST_MSVC, == 1600) + // workaround for MSVC10 which has problems copying a default + // constructed iterator_range + token& operator= (token const& rhs) + { + if (this != &rhs) + { + id_ = rhs.id_; + if (is_valid()) + matched_ = rhs.matched_; + } + return *this; + } +#endif + std::pair<Iterator, Iterator> matched_; +#endif + + protected: + id_type id_; // token id, 0 if nothing has been matched + }; + +#if defined(BOOST_SPIRIT_DEBUG) + template <typename Char, typename Traits, typename Iterator + , typename AttributeTypes, typename HasState, typename Idtype> + inline std::basic_ostream<Char, Traits>& + operator<< (std::basic_ostream<Char, Traits>& os + , token<Iterator, AttributeTypes, HasState, Idtype> const& t) + { + if (t.is_valid()) { + Iterator end = t.matched_.second; + for (Iterator it = t.matched_.first; it != end; ++it) + os << *it; + } + else { + os << "<invalid token>"; + } + return os; + } +#endif + + /////////////////////////////////////////////////////////////////////////// + // This specialization of the token type doesn't contain any item data but + // supports working with lexer states. + /////////////////////////////////////////////////////////////////////////// + template <typename Iterator, typename Idtype> + struct token<Iterator, lex::omit, mpl::true_, Idtype> + : token<Iterator, lex::omit, mpl::false_, Idtype> + { + private: + typedef token<Iterator, lex::omit, mpl::false_, Idtype> base_type; + + public: + typedef typename base_type::id_type id_type; + typedef Iterator iterator_type; + typedef mpl::true_ has_state; + typedef unused_type token_value_type; + + // default constructed tokens correspond to EOI tokens + token() : state_(boost::lexer::npos) {} + + // construct an invalid token + explicit token(int) : base_type(0), state_(boost::lexer::npos) {} + + token(id_type id, std::size_t state) + : base_type(id, boost::lexer::npos), state_(state) {} + + token(id_type id, std::size_t state, token_value_type) + : base_type(id, boost::lexer::npos, unused) + , state_(state) {} + + token(id_type id, std::size_t state + , Iterator const& first, Iterator const& last) + : base_type(id, boost::lexer::npos, first, last) + , state_(state) {} + + std::size_t state() const { return state_; } + +#if defined(BOOST_SPIRIT_DEBUG) && BOOST_WORKAROUND(BOOST_MSVC, == 1600) + // workaround for MSVC10 which has problems copying a default + // constructed iterator_range + token& operator= (token const& rhs) + { + if (this != &rhs) + { + this->base_type::operator=(static_cast<base_type const&>(rhs)); + state_ = rhs.state_; + } + return *this; + } +#endif + + protected: + std::size_t state_; // lexer state this token was matched in + }; + + /////////////////////////////////////////////////////////////////////////// + // The generic version of the token type derives from the + // specialization above and adds a single data member holding the item + // data carried by the token instance. + /////////////////////////////////////////////////////////////////////////// + namespace detail + { + /////////////////////////////////////////////////////////////////////// + // Meta-function to calculate the type of the variant data item to be + // stored with each token instance. + // + // Note: The iterator pair needs to be the first type in the list of + // types supported by the generated variant type (this is being + // used to identify whether the stored data item in a particular + // token instance needs to be converted from the pair of + // iterators (see the first of the assign_to_attribute_from_value + // specializations below). + /////////////////////////////////////////////////////////////////////// + template <typename IteratorPair, typename AttributeTypes> + struct token_value_typesequence + { + typedef typename mpl::insert< + AttributeTypes + , typename mpl::begin<AttributeTypes>::type + , IteratorPair + >::type sequence_type; + typedef typename make_variant_over<sequence_type>::type type; + }; + + /////////////////////////////////////////////////////////////////////// + // The type of the data item stored with a token instance is defined + // by the template parameter 'AttributeTypes' and may be: + // + // lex::omit: no data item is stored with the token + // instance (this is handled by the + // specializations of the token class + // below) + // mpl::vector0<>: each token instance stores a pair of + // iterators pointing to the matched input + // sequence + // mpl::vector<...>: each token instance stores a variant being + // able to store the pair of iterators pointing + // to the matched input sequence, or any of the + // types a specified in the mpl::vector<> + // + // All this is done to ensure the token type is as small (in terms + // of its byte-size) as possible. + /////////////////////////////////////////////////////////////////////// + template <typename IteratorPair, typename AttributeTypes> + struct token_value_type + : mpl::eval_if< + mpl::or_< + is_same<AttributeTypes, mpl::vector0<> > + , is_same<AttributeTypes, mpl::vector<> > > + , mpl::identity<IteratorPair> + , token_value_typesequence<IteratorPair, AttributeTypes> > + {}; + } + + template <typename Iterator, typename AttributeTypes, typename HasState + , typename Idtype> + struct token : token<Iterator, lex::omit, HasState, Idtype> + { + private: // precondition assertions +#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) + BOOST_STATIC_ASSERT((mpl::is_sequence<AttributeTypes>::value || + is_same<AttributeTypes, lex::omit>::value)); +#endif + typedef token<Iterator, lex::omit, HasState, Idtype> base_type; + + protected: + // If no additional token value types are given, the the token will + // hold the plain pair of iterators pointing to the matched range + // in the underlying input sequence. Otherwise the token value is + // stored as a variant and will again hold the pair of iterators but + // is able to hold any of the given data types as well. The conversion + // from the iterator pair to the required data type is done when it is + // accessed for the first time. + typedef iterator_range<Iterator> iterpair_type; + + public: + typedef typename base_type::id_type id_type; + typedef typename detail::token_value_type< + iterpair_type, AttributeTypes + >::type token_value_type; + + typedef Iterator iterator_type; + + // default constructed tokens correspond to EOI tokens + token() : value_(iterpair_type(iterator_type(), iterator_type())) {} + + // construct an invalid token + explicit token(int) + : base_type(0) + , value_(iterpair_type(iterator_type(), iterator_type())) {} + + token(id_type id, std::size_t state, token_value_type const& value) + : base_type(id, state, value) + , value_(value) {} + + token(id_type id, std::size_t state, Iterator const& first + , Iterator const& last) + : base_type(id, state, first, last) + , value_(iterpair_type(first, last)) {} + + token_value_type& value() { return value_; } + token_value_type const& value() const { return value_; } + +#if BOOST_WORKAROUND(BOOST_MSVC, == 1600) + // workaround for MSVC10 which has problems copying a default + // constructed iterator_range + token& operator= (token const& rhs) + { + if (this != &rhs) + { + this->base_type::operator=(static_cast<base_type const&>(rhs)); + if (this->is_valid()) + value_ = rhs.value_; + } + return *this; + } +#endif + + protected: + token_value_type value_; // token value, by default a pair of iterators + }; + + /////////////////////////////////////////////////////////////////////////// + // tokens are considered equal, if their id's match (these are unique) + template <typename Iterator, typename AttributeTypes, typename HasState + , typename Idtype> + inline bool + operator== (token<Iterator, AttributeTypes, HasState, Idtype> const& lhs, + token<Iterator, AttributeTypes, HasState, Idtype> const& rhs) + { + return lhs.id() == rhs.id(); + } + + /////////////////////////////////////////////////////////////////////////// + // This overload is needed by the multi_pass/functor_input_policy to + // validate a token instance. It has to be defined in the same namespace + // as the token class itself to allow ADL to find it. + /////////////////////////////////////////////////////////////////////////// + template <typename Iterator, typename AttributeTypes, typename HasState + , typename Idtype> + inline bool + token_is_valid(token<Iterator, AttributeTypes, HasState, Idtype> const& t) + { + return t.is_valid(); + } +}}}} + +namespace boost { namespace spirit { namespace traits +{ + /////////////////////////////////////////////////////////////////////////// + // We have to provide specializations for the customization point + // assign_to_attribute_from_value allowing to extract the needed value + // from the token. + /////////////////////////////////////////////////////////////////////////// + + // This is called from the parse function of token_def if the token_def + // has been defined to carry a special attribute type + template <typename Attribute, typename Iterator, typename AttributeTypes + , typename HasState, typename Idtype> + struct assign_to_attribute_from_value<Attribute + , lex::lexertl::token<Iterator, AttributeTypes, HasState, Idtype> > + { + static void + call(lex::lexertl::token<Iterator, AttributeTypes, HasState, Idtype> const& t + , Attribute& attr) + { + // The goal of this function is to avoid the conversion of the pair of + // iterators (to the matched character sequence) into the token value + // of the required type being done more than once. For this purpose it + // checks whether the stored value type is still the default one (pair + // of iterators) and if yes, replaces the pair of iterators with the + // converted value to be returned from subsequent calls. + + if (0 == t.value().which()) { + // first access to the token value + typedef iterator_range<Iterator> iterpair_type; + iterpair_type const& ip = boost::get<iterpair_type>(t.value()); + + // Interestingly enough we use the assign_to() framework defined in + // Spirit.Qi allowing to convert the pair of iterators to almost any + // required type (assign_to(), if available, uses the standard Spirit + // parsers to do the conversion). + spirit::traits::assign_to(ip.begin(), ip.end(), attr); + + // If you get an error during the compilation of the following + // assignment expression, you probably forgot to list one or more + // types used as token value types (in your token_def<...> + // definitions) in your definition of the token class. I.e. any token + // value type used for a token_def<...> definition has to be listed + // during the declaration of the token type to use. For instance let's + // assume we have two token_def's: + // + // token_def<int> number; number = "..."; + // token_def<std::string> identifier; identifier = "..."; + // + // Then you'll have to use the following token type definition + // (assuming you are using the token class): + // + // typedef mpl::vector<int, std::string> token_values; + // typedef token<base_iter_type, token_values> token_type; + // + // where: base_iter_type is the iterator type used to expose the + // underlying input stream. + // + // This token_type has to be used as the second template parameter + // to the lexer class: + // + // typedef lexer<base_iter_type, token_type> lexer_type; + // + // again, assuming you're using the lexer<> template for your + // tokenization. + + typedef lex::lexertl::token< + Iterator, AttributeTypes, HasState, Idtype> token_type; + spirit::traits::assign_to( + attr, const_cast<token_type&>(t).value()); // re-assign value + } + else { + // reuse the already assigned value + spirit::traits::assign_to(boost::get<Attribute>(t.value()), attr); + } + } + }; + + template <typename Attribute, typename Iterator, typename AttributeTypes + , typename HasState, typename Idtype> + struct assign_to_container_from_value<Attribute + , lex::lexertl::token<Iterator, AttributeTypes, HasState, Idtype> > + : assign_to_attribute_from_value<Attribute + , lex::lexertl::token<Iterator, AttributeTypes, HasState, Idtype> > + {}; + + template <typename Iterator, typename AttributeTypes + , typename HasState, typename Idtype> + struct assign_to_container_from_value<utree + , lex::lexertl::token<Iterator, AttributeTypes, HasState, Idtype> > + : assign_to_attribute_from_value<utree + , lex::lexertl::token<Iterator, AttributeTypes, HasState, Idtype> > + {}; + + template <typename Iterator> + struct assign_to_container_from_value< + iterator_range<Iterator>, iterator_range<Iterator> > + { + static void + call(iterator_range<Iterator> const& val, iterator_range<Iterator>& attr) + { + attr = val; + } + }; + + // These are called from the parse function of token_def if the token type + // has no special attribute type assigned + template <typename Attribute, typename Iterator, typename HasState + , typename Idtype> + struct assign_to_attribute_from_value<Attribute + , lex::lexertl::token<Iterator, mpl::vector0<>, HasState, Idtype> > + { + static void + call(lex::lexertl::token<Iterator, mpl::vector0<>, HasState, Idtype> const& t + , Attribute& attr) + { + // The default type returned by the token_def parser component (if + // it has no token value type assigned) is the pair of iterators + // to the matched character sequence. + spirit::traits::assign_to(t.value().begin(), t.value().end(), attr); + } + }; + +// template <typename Attribute, typename Iterator, typename HasState +// , typename Idtype> +// struct assign_to_container_from_value<Attribute +// , lex::lexertl::token<Iterator, mpl::vector0<>, HasState, Idtype> > +// : assign_to_attribute_from_value<Attribute +// , lex::lexertl::token<Iterator, mpl::vector0<>, HasState, Idtype> > +// {}; + + // same as above but using mpl::vector<> instead of mpl::vector0<> + template <typename Attribute, typename Iterator, typename HasState + , typename Idtype> + struct assign_to_attribute_from_value<Attribute + , lex::lexertl::token<Iterator, mpl::vector<>, HasState, Idtype> > + { + static void + call(lex::lexertl::token<Iterator, mpl::vector<>, HasState, Idtype> const& t + , Attribute& attr) + { + // The default type returned by the token_def parser component (if + // it has no token value type assigned) is the pair of iterators + // to the matched character sequence. + spirit::traits::assign_to(t.value().begin(), t.value().end(), attr); + } + }; + +// template <typename Attribute, typename Iterator, typename HasState +// , typename Idtype> +// struct assign_to_container_from_value<Attribute +// , lex::lexertl::token<Iterator, mpl::vector<>, HasState, Idtype> > +// : assign_to_attribute_from_value<Attribute +// , lex::lexertl::token<Iterator, mpl::vector<>, HasState, Idtype> > +// {}; + + // This is called from the parse function of token_def if the token type + // has been explicitly omitted (i.e. no attribute value is used), which + // essentially means that every attribute gets initialized using default + // constructed values. + template <typename Attribute, typename Iterator, typename HasState + , typename Idtype> + struct assign_to_attribute_from_value<Attribute + , lex::lexertl::token<Iterator, lex::omit, HasState, Idtype> > + { + static void + call(lex::lexertl::token<Iterator, lex::omit, HasState, Idtype> const& t + , Attribute& attr) + { + // do nothing + } + }; + + template <typename Attribute, typename Iterator, typename HasState + , typename Idtype> + struct assign_to_container_from_value<Attribute + , lex::lexertl::token<Iterator, lex::omit, HasState, Idtype> > + : assign_to_attribute_from_value<Attribute + , lex::lexertl::token<Iterator, lex::omit, HasState, Idtype> > + {}; + + // This is called from the parse function of lexer_def_ + template <typename Iterator, typename AttributeTypes, typename HasState + , typename Idtype_, typename Idtype> + struct assign_to_attribute_from_value< + fusion::vector2<Idtype_, iterator_range<Iterator> > + , lex::lexertl::token<Iterator, AttributeTypes, HasState, Idtype> > + { + static void + call(lex::lexertl::token<Iterator, AttributeTypes, HasState, Idtype> const& t + , fusion::vector2<Idtype_, iterator_range<Iterator> >& attr) + { + // The type returned by the lexer_def_ parser components is a + // fusion::vector containing the token id of the matched token + // and the pair of iterators to the matched character sequence. + typedef iterator_range<Iterator> iterpair_type; + typedef fusion::vector2<Idtype_, iterator_range<Iterator> > + attribute_type; + + iterpair_type const& ip = boost::get<iterpair_type>(t.value()); + attr = attribute_type(t.id(), ip); + } + }; + + template <typename Iterator, typename AttributeTypes, typename HasState + , typename Idtype_, typename Idtype> + struct assign_to_container_from_value< + fusion::vector2<Idtype_, iterator_range<Iterator> > + , lex::lexertl::token<Iterator, AttributeTypes, HasState, Idtype> > + : assign_to_attribute_from_value< + fusion::vector2<Idtype_, iterator_range<Iterator> > + , lex::lexertl::token<Iterator, AttributeTypes, HasState, Idtype> > + {}; + + /////////////////////////////////////////////////////////////////////////// + // Overload debug output for a single token, this integrates lexer tokens + // with Qi's simple_trace debug facilities + template <typename Iterator, typename Attribute, typename HasState + , typename Idtype> + struct token_printer_debug< + lex::lexertl::token<Iterator, Attribute, HasState, Idtype> > + { + typedef lex::lexertl::token<Iterator, Attribute, HasState, Idtype> token_type; + + template <typename Out> + static void print(Out& out, token_type const& val) + { + out << '['; + spirit::traits::print_token(out, val.value()); + out << ']'; + } + }; +}}} + +#endif |