// Copyright (c) 2001-2008 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_DEF_MAR_13_2007_0145PM) #define BOOST_SPIRIT_LEX_TOKEN_DEF_MAR_13_2007_0145PM #if defined(_MSC_VER) && (_MSC_VER >= 1020) #pragma once // MS compatible compilers support #pragma once #endif #include #include #include #include #include #include #include #include #include #include #include namespace boost { namespace spirit { namespace lex { /////////////////////////////////////////////////////////////////////////// // create a unique token id, note this is not thread safe /////////////////////////////////////////////////////////////////////////// enum tokenids { // this is the first token id automatically assigned by the library // if needed min_token_id = 0x10000 }; /////////////////////////////////////////////////////////////////////////// // The next_id template needs to be specialized for any non-default token // id type used by a custom token type. It need to expose a function // 'static Idtype get()' returning the next available token id each time // it is called. template struct next_id; /////////////////////////////////////////////////////////////////////////// // Default specialization for the next_id template returning the next // available token id. template <> struct next_id { static std::size_t get() { static std::size_t next_token_id = min_token_id; return next_token_id++; } }; /////////////////////////////////////////////////////////////////////////// // This component represents a token definition /////////////////////////////////////////////////////////////////////////// template class token_def : public proto::extends< typename make_terminal_holder< token_def*, token_def >::type, token_def > { private: // initialize proto base class typedef terminal_holder terminal_holder_; typedef typename proto::terminal::type tag; typedef proto::extends base_type; tag make_tag() { tag xpr = {{ this }}; return xpr; } public: // Qi interface: metafunction calculating parser return type template struct attribute { // The return value of the token_def is either the specified // attribute type, or the pair of iterators from the match of the // corresponding token (if no attribute type has been specified), // or unused_type (if omitted has been specified). typedef typename Iterator::base_iterator_type iterator_type; typedef typename mpl::if_< is_same, iterator_range, typename mpl::if_< is_same, unused_type, Attribute >::type >::type type; }; private: // Qi interface: parse functionality template bool parse(Iterator& first, Iterator const& last, Context& /*context*/, Skipper const& skipper, Attribute1& attr) const { qi::skip(first, last, skipper); // always do a pre-skip if (first != last) { typedef typename boost::detail::iterator_traits::value_type token_type; // If the following assertion fires you probably forgot to // associate this token definition with a lexer instance. BOOST_ASSERT((std::size_t)(~0) != token_state); token_type &t = *first; if (token_id == t.id() && token_state == t.state()) { qi::detail::assign_to(t, attr); ++first; return true; } } return false; } friend struct terminal_director; std::string what() const { std::string result = "token_def(\""; result += def; result += "\")"; return result; } /////////////////////////////////////////////////////////////////////// // Lex interface: collect token definitions and put it into the // provided lexer def template void collect(LexerDef& lexdef, String const& state) { token_state = lexdef.add_state(state.c_str()); if (0 == token_id) token_id = next_id::get(); lexdef.add_token (state.c_str(), def, token_id); } public: typedef Char char_type; typedef Idtype id_type; typedef std::basic_string string_type; // Lex interface: constructing token definitions token_def() : base_type(make_tag()), token_id(0), token_state(~0) {} explicit token_def(char_type def_, Idtype id_ = Idtype()) : base_type(make_tag()), def(lex::detail::escape(def_)), token_id(0 == id_ ? def_ : id_), token_state(~0) {} explicit token_def(string_type def_, Idtype id_ = Idtype()) : base_type(make_tag()), def(def_), token_id(id_), token_state(~0) {} template token_def& operator= (String const& definition) { def = definition; token_id = 0; return *this; } token_def& operator= (token_def const& rhs) { def = rhs.def; token_id = rhs.token_id; return *this; } // general accessors Idtype id() const { return token_id; } void id(Idtype id) { token_id = id; } string_type const& definition() const { return def; } std::size_t state() const { return token_state; } private: string_type def; Idtype token_id; std::size_t token_state; }; }}} #endif