string_token_def.hpp 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. // Copyright (c) 2001-2011 Hartmut Kaiser
  2. //
  3. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  4. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  5. #if !defined(BOOST_SPIRIT_LEX_STRING_TOKEN_DEF_MAR_28_2007_0722PM)
  6. #define BOOST_SPIRIT_LEX_STRING_TOKEN_DEF_MAR_28_2007_0722PM
  7. #if defined(_MSC_VER)
  8. #pragma once
  9. #endif
  10. #include <boost/spirit/home/support/common_terminals.hpp>
  11. #include <boost/spirit/home/support/string_traits.hpp>
  12. #include <boost/spirit/home/lex/domain.hpp>
  13. #include <boost/spirit/home/lex/lexer_type.hpp>
  14. #include <boost/spirit/home/lex/meta_compiler.hpp>
  15. #include <boost/type_traits/add_const.hpp>
  16. #include <boost/type_traits/add_reference.hpp>
  17. #include <boost/type_traits/is_integral.hpp>
  18. #include <boost/type_traits/remove_const.hpp>
  19. #include <boost/fusion/include/vector.hpp>
  20. #include <boost/fusion/include/at.hpp>
  21. namespace boost { namespace spirit
  22. {
  23. ///////////////////////////////////////////////////////////////////////////
  24. // Enablers
  25. ///////////////////////////////////////////////////////////////////////////
  26. // enables strings
  27. template <typename T>
  28. struct use_terminal<lex::domain, T
  29. , typename enable_if<traits::is_string<T> >::type>
  30. : mpl::true_ {};
  31. // enables string(str)
  32. template <typename CharEncoding, typename A0>
  33. struct use_terminal<lex::domain
  34. , terminal_ex<
  35. tag::char_code<tag::string, CharEncoding>
  36. , fusion::vector1<A0> > >
  37. : traits::is_string<A0> {};
  38. // enables string(str, ID)
  39. template <typename CharEncoding, typename A0, typename A1>
  40. struct use_terminal<lex::domain
  41. , terminal_ex<
  42. tag::char_code<tag::string, CharEncoding>
  43. , fusion::vector2<A0, A1> > >
  44. : traits::is_string<A0> {};
  45. }}
  46. namespace boost { namespace spirit { namespace lex
  47. {
  48. // use string from standard character set by default
  49. #ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
  50. using spirit::standard::string;
  51. #endif
  52. using spirit::standard::string_type;
  53. ///////////////////////////////////////////////////////////////////////////
  54. //
  55. // string_token_def
  56. // represents a string based token definition
  57. //
  58. ///////////////////////////////////////////////////////////////////////////
  59. template <typename String, typename IdType = std::size_t
  60. , typename CharEncoding = char_encoding::standard>
  61. struct string_token_def
  62. : primitive_lexer<string_token_def<String, IdType, CharEncoding> >
  63. {
  64. typedef typename
  65. remove_const<typename traits::char_type_of<String>::type>::type
  66. char_type;
  67. typedef std::basic_string<char_type> string_type;
  68. string_token_def(typename add_reference<String>::type str, IdType const& id)
  69. : str_(str), id_(id), unique_id_(std::size_t(~0))
  70. , token_state_(std::size_t(~0))
  71. {}
  72. template <typename LexerDef, typename String_>
  73. void collect(LexerDef& lexdef, String_ const& state
  74. , String_ const& targetstate) const
  75. {
  76. std::size_t state_id = lexdef.add_state(state.c_str());
  77. // If the following assertion fires you are probably trying to use
  78. // a single string_token_def instance in more than one lexer state.
  79. // This is not possible. Please create a separate token_def instance
  80. // from the same regular expression for each lexer state it needs
  81. // to be associated with.
  82. BOOST_ASSERT(
  83. (std::size_t(~0) == token_state_ || state_id == token_state_) &&
  84. "Can't use single string_token_def with more than one lexer state");
  85. char_type const* target = targetstate.empty() ? 0 : targetstate.c_str();
  86. if (target)
  87. lexdef.add_state(target);
  88. token_state_ = state_id;
  89. if (IdType(~0) == id_)
  90. id_ = IdType(lexdef.get_next_id());
  91. unique_id_ = lexdef.add_token (state.c_str(), str_, id_, target);
  92. }
  93. template <typename LexerDef>
  94. void add_actions(LexerDef&) const {}
  95. std::size_t id() const { return id_; }
  96. std::size_t unique_id() const { return unique_id_; }
  97. std::size_t state() const { return token_state_; }
  98. string_type str_;
  99. mutable IdType id_;
  100. mutable std::size_t unique_id_;
  101. mutable std::size_t token_state_;
  102. };
  103. ///////////////////////////////////////////////////////////////////////////
  104. // Lex generators: make_xxx function (objects)
  105. ///////////////////////////////////////////////////////////////////////////
  106. template <typename T, typename Modifiers>
  107. struct make_primitive<T, Modifiers
  108. , typename enable_if<traits::is_string<T> >::type>
  109. {
  110. typedef typename add_const<T>::type const_string;
  111. typedef string_token_def<const_string> result_type;
  112. result_type operator()(
  113. typename add_reference<const_string>::type str, unused_type) const
  114. {
  115. return result_type(str, std::size_t(~0));
  116. }
  117. };
  118. template <typename Modifiers, typename CharEncoding, typename A0>
  119. struct make_primitive<
  120. terminal_ex<
  121. tag::char_code<tag::string, CharEncoding>
  122. , fusion::vector1<A0> >
  123. , Modifiers>
  124. {
  125. typedef typename add_const<A0>::type const_string;
  126. typedef string_token_def<const_string, std::size_t, CharEncoding>
  127. result_type;
  128. template <typename Terminal>
  129. result_type operator()(Terminal const& term, unused_type) const
  130. {
  131. return result_type(fusion::at_c<0>(term.args), std::size_t(~0));
  132. }
  133. };
  134. template <typename Modifiers, typename CharEncoding, typename A0, typename A1>
  135. struct make_primitive<
  136. terminal_ex<
  137. tag::char_code<tag::string, CharEncoding>
  138. , fusion::vector2<A0, A1> >
  139. , Modifiers>
  140. {
  141. typedef typename add_const<A0>::type const_string;
  142. typedef string_token_def<const_string, A1, CharEncoding> result_type;
  143. template <typename Terminal>
  144. result_type operator()(Terminal const& term, unused_type) const
  145. {
  146. return result_type(
  147. fusion::at_c<0>(term.args), fusion::at_c<1>(term.args));
  148. }
  149. };
  150. }}} // namespace boost::spirit::lex
  151. #endif