📄 token_set.hpp
字号:
// 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_SET_MAR_13_2007_0145PM)#define BOOST_SPIRIT_LEX_TOKEN_SET_MAR_13_2007_0145PM#if defined(_MSC_VER) && (_MSC_VER >= 1020)#pragma once // MS compatible compilers support #pragma once#endif#include <boost/spirit/home/lex/lexer/lexer_fwd.hpp>#include <boost/spirit/home/lex/lexer/terminal_holder.hpp>#include <boost/spirit/home/lex/lexer/token_def.hpp>#include <boost/detail/iterator.hpp>#include <boost/fusion/include/vector.hpp>#include <boost/mpl/assert.hpp>#include <boost/range/iterator_range.hpp>#include <cstdlib>namespace boost { namespace spirit { namespace lex{ /////////////////////////////////////////////////////////////////////////// // token_set /////////////////////////////////////////////////////////////////////////// template <typename TokenSet> class token_set : public TokenSet, public proto::extends< typename make_terminal_holder< token_set<TokenSet>*, token_set<TokenSet> >::type, token_set<TokenSet> > { protected: typedef typename TokenSet::char_type char_type; typedef typename TokenSet::string_type string_type; private: // avoid warnings about using 'this' in constructor token_set& this_() { return *this; } typedef token_set self_type; typedef TokenSet base_token_set; // initialize proto base class typedef terminal_holder<token_set*, token_set> terminal_holder_; typedef typename proto::terminal<terminal_holder_>::type tag; typedef proto::extends<tag, token_set> base_type; tag make_tag() { tag xpr = {{ this }}; return xpr; } public: typedef typename TokenSet::id_type id_type; // Qi interface: metafunction calculating parser return type template <typename Component, typename Context, typename Iterator> struct attribute { // the return value of a token set contains the matched token id, // and the corresponding pair of iterators typedef typename Iterator::base_iterator_type iterator_type; typedef fusion::vector<id_type, iterator_range<iterator_type> > type; }; private: // Qi interface: parse functionality template <typename Iterator, typename Context, typename Skipper, typename Attribute> bool parse(Iterator& first, Iterator const& last, Context& context, Skipper const& skipper, Attribute& attr) const { qi::skip(first, last, skipper); // always do a pre-skip if (first != last) { typedef typename boost::detail::iterator_traits<Iterator>::value_type token_type; // If the following assertion fires you probably forgot to // associate this token set definition with a lexer instance. BOOST_ASSERT(~0 != token_state); token_type &t = *first; if (token_is_valid(t) && token_state == t.state()) { // any of the token definitions matched qi::detail::assign_to(t, attr); ++first; return true; } } return false; } friend struct terminal_director; static std::string what() { return "token_set"; } /////////////////////////////////////////////////////////////////////// // Lex interface: collect token definitions and put it into the // provided lexer def template <typename LexerDef, typename String> void collect(LexerDef& lexdef, String const& state) { token_state = lexdef.add_state(state.c_str()); lexdef.add_token (state.c_str(), *this); } // allow to use the tokset.add("regex1", id1)("regex2", id2); // syntax struct adder { adder(token_set& def_) : def(def_) {} adder const& operator()(char_type c, id_type token_id = id_type()) const { if (0 == token_id) token_id = static_cast<std::size_t>(c); def.add_token (def.initial_state().c_str(), lex::detail::escape(c), token_id); return *this; } adder const& operator()(string_type const& s, id_type token_id = id_type()) const { if (0 == token_id) token_id = next_id<id_type>::get(); def.add_token (def.initial_state().c_str(), s, token_id); return *this; } template <typename Attribute> adder const& operator()(token_def<Attribute, char_type, id_type>& tokdef, id_type token_id = id_type()) const { // make sure we have a token id if (0 == token_id) { if (0 == tokdef.id()) { token_id = next_id<id_type>::get(); tokdef.id(token_id); } else { token_id = tokdef.id(); } } else { // the following assertion makes sure, that the token_def // instance has not been assigned a different id earlier BOOST_ASSERT(0 == tokdef.id() || token_id == tokdef.id()); tokdef.id(token_id); } def.add_token (def.initial_state().c_str(), tokdef.definition(), token_id); return *this; } template <typename TokenSet_> adder const& operator()(token_set<TokenSet_> const& tokset) const { def.add_token (def.initial_state().c_str(), tokset); return *this; } token_set& def; }; friend struct adder; // allow to use lexer.self.add_pattern("pattern1", "regex1")(...); // syntax struct pattern_adder { pattern_adder(token_set& def_) : def(def_) {} pattern_adder const& operator()(string_type const& p, string_type const& s) const { def.add_pattern (def.state.c_str(), p, s); return *this; } token_set& def; }; friend struct pattern_adder; public: /////////////////////////////////////////////////////////////////// template <typename Expr> void define(Expr const& xpr) { typedef typename result_of::as_component<lex::domain, Expr>::type component; typedef typename component::director director; component c = spirit::as_component(lex::domain(), xpr); director::collect(c, *this, base_token_set::initial_state()); } token_set() : base_type(make_tag()), add(this_()), add_pattern(this_()), token_state(~0) {} // allow to assign a token definition expression template <typename Expr> token_set& operator= (Expr const& xpr) { typedef spirit::traits::is_component<lex::domain, Expr> is_component; // report invalid expression error as early as possible BOOST_MPL_ASSERT_MSG( is_component::value, xpr_is_not_convertible_to_a_token_definition, ()); this->clear(); define(xpr); return *this; } adder add; pattern_adder add_pattern; private: std::size_t token_state; }; // allow to assign a token definition expression template <typename TokenSet, typename Expr> inline token_set<TokenSet>& operator+= (token_set<TokenSet>& tokset, Expr& xpr) { typedef spirit::traits::is_component<lex::domain, Expr> is_component; // report invalid expression error as early as possible BOOST_MPL_ASSERT_MSG( is_component::value, xpr_is_not_convertible_to_a_token_definition, ()); tokset.define(xpr); return tokset; } template <typename TokenSet, typename Expr> inline token_set<TokenSet>& operator+= (token_set<TokenSet>& tokset, Expr const& xpr) { typedef spirit::traits::is_component<lex::domain, Expr> is_component; // report invalid expression error as early as possible BOOST_MPL_ASSERT_MSG( is_component::value, xpr_is_not_convertible_to_a_token_definition, ()); tokset.define(xpr); return tokset; }}}}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -