support_functions.hpp 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  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. #ifndef BOOST_SPIRIT_LEX_LEXER_SUPPORT_FUNCTIONS_HPP
  6. #define BOOST_SPIRIT_LEX_LEXER_SUPPORT_FUNCTIONS_HPP
  7. #if defined(_MSC_VER)
  8. #pragma once
  9. #endif
  10. #include <boost/spirit/home/support/detail/scoped_enum_emulation.hpp>
  11. #include <boost/spirit/home/lex/lexer/pass_flags.hpp>
  12. #include <boost/spirit/home/lex/lexer/support_functions_expression.hpp>
  13. #include <boost/phoenix/core/actor.hpp>
  14. #include <boost/phoenix/core/as_actor.hpp>
  15. #include <boost/phoenix/core/value.hpp> // includes as_actor specialization
  16. ///////////////////////////////////////////////////////////////////////////////
  17. namespace boost { namespace spirit { namespace lex
  18. {
  19. ///////////////////////////////////////////////////////////////////////////
  20. // The function object less_type is used by the implementation of the
  21. // support function lex::less(). Its functionality is equivalent to flex'
  22. // function yyless(): it returns an iterator positioned to the nth input
  23. // character beyond the current start iterator (i.e. by assigning the
  24. // return value to the placeholder '_end' it is possible to return all but
  25. // the first n characters of the current token back to the input stream.
  26. //
  27. // This Phoenix actor is invoked whenever the function lex::less(n) is
  28. // used inside a lexer semantic action:
  29. //
  30. // lex::token_def<> identifier = "[a-zA-Z_][a-zA-Z0-9_]*";
  31. // this->self = identifier [ _end = lex::less(4) ];
  32. //
  33. // The example shows how to limit the length of the matched identifier to
  34. // four characters.
  35. //
  36. // Note: the function lex::less() has no effect if used on it's own, you
  37. // need to use the returned result in order to make use of its
  38. // functionality.
  39. template <typename Actor>
  40. struct less_type
  41. {
  42. typedef mpl::true_ no_nullary;
  43. template <typename Env>
  44. struct result
  45. {
  46. typedef typename remove_reference<
  47. typename remove_const<
  48. typename mpl::at_c<typename Env::args_type, 4>::type
  49. >::type
  50. >::type context_type;
  51. typedef typename context_type::base_iterator_type type;
  52. };
  53. template <typename Env>
  54. typename result<Env>::type
  55. eval(Env const& env) const
  56. {
  57. typename result<Env>::type it;
  58. return fusion::at_c<4>(env.args()).less(it, actor_());
  59. }
  60. less_type(Actor const& actor)
  61. : actor_(actor) {}
  62. Actor actor_;
  63. };
  64. // The function lex::less() is used to create a Phoenix actor allowing to
  65. // implement functionality similar to flex' function yyless().
  66. template <typename T>
  67. inline typename expression::less<
  68. typename phoenix::as_actor<T>::type
  69. >::type const
  70. less(T const& v)
  71. {
  72. return expression::less<T>::make(phoenix::as_actor<T>::convert(v));
  73. }
  74. ///////////////////////////////////////////////////////////////////////////
  75. // The function object more_type is used by the implementation of the
  76. // support function lex::more(). Its functionality is equivalent to flex'
  77. // function yymore(): it tells the lexer that the next time it matches a
  78. // rule, the corresponding token should be appended onto the current token
  79. // value rather than replacing it.
  80. //
  81. // This Phoenix actor is invoked whenever the function lex::more(n) is
  82. // used inside a lexer semantic action:
  83. //
  84. // lex::token_def<> identifier = "[a-zA-Z_][a-zA-Z0-9_]*";
  85. // this->self = identifier [ lex::more() ];
  86. //
  87. // The example shows how prefix the next matched token with the matched
  88. // identifier.
  89. struct more_type
  90. {
  91. typedef mpl::true_ no_nullary;
  92. template <typename Env>
  93. struct result
  94. {
  95. typedef void type;
  96. };
  97. template <typename Env>
  98. void eval(Env const& env) const
  99. {
  100. fusion::at_c<4>(env.args()).more();
  101. }
  102. };
  103. // The function lex::more() is used to create a Phoenix actor allowing to
  104. // implement functionality similar to flex' function yymore().
  105. //inline expression::more<mpl::void_>::type const
  106. inline phoenix::actor<more_type> more()
  107. {
  108. return phoenix::actor<more_type>();
  109. }
  110. ///////////////////////////////////////////////////////////////////////////
  111. // The function object lookahead_type is used by the implementation of the
  112. // support function lex::lookahead(). Its functionality is needed to
  113. // emulate the flex' lookahead operator a/b. Use lex::lookahead() inside
  114. // of lexer semantic actions to test whether the argument to this function
  115. // matches the current look ahead input. lex::lookahead() can be used with
  116. // either a token id or a token_def instance as its argument. It returns
  117. // a bool indicating whether the look ahead has been matched.
  118. template <typename IdActor, typename StateActor>
  119. struct lookahead_type
  120. {
  121. typedef mpl::true_ no_nullary;
  122. template <typename Env>
  123. struct result
  124. {
  125. typedef bool type;
  126. };
  127. template <typename Env>
  128. bool eval(Env const& env) const
  129. {
  130. return fusion::at_c<4>(env.args()).
  131. lookahead(id_actor_(), state_actor_());
  132. }
  133. lookahead_type(IdActor const& id_actor, StateActor const& state_actor)
  134. : id_actor_(id_actor), state_actor_(state_actor) {}
  135. IdActor id_actor_;
  136. StateActor state_actor_;
  137. };
  138. // The function lex::lookahead() is used to create a Phoenix actor
  139. // allowing to implement functionality similar to flex' lookahead operator
  140. // a/b.
  141. template <typename T>
  142. inline typename expression::lookahead<
  143. typename phoenix::as_actor<T>::type
  144. , typename phoenix::as_actor<std::size_t>::type
  145. >::type const
  146. lookahead(T const& id)
  147. {
  148. typedef typename phoenix::as_actor<T>::type id_actor_type;
  149. typedef typename phoenix::as_actor<std::size_t>::type state_actor_type;
  150. return expression::lookahead<id_actor_type, state_actor_type>::make(
  151. phoenix::as_actor<T>::convert(id),
  152. phoenix::as_actor<std::size_t>::convert(std::size_t(~0)));
  153. }
  154. template <typename Attribute, typename Char, typename Idtype>
  155. inline typename expression::lookahead<
  156. typename phoenix::as_actor<Idtype>::type
  157. , typename phoenix::as_actor<std::size_t>::type
  158. >::type const
  159. lookahead(token_def<Attribute, Char, Idtype> const& tok)
  160. {
  161. typedef typename phoenix::as_actor<Idtype>::type id_actor_type;
  162. typedef typename phoenix::as_actor<std::size_t>::type state_actor_type;
  163. std::size_t state = tok.state();
  164. // The following assertion fires if you pass a token_def instance to
  165. // lex::lookahead without first associating this instance with the
  166. // lexer.
  167. BOOST_ASSERT(std::size_t(~0) != state &&
  168. "token_def instance not associated with lexer yet");
  169. return expression::lookahead<id_actor_type, state_actor_type>::make(
  170. phoenix::as_actor<Idtype>::convert(tok.id()),
  171. phoenix::as_actor<std::size_t>::convert(state));
  172. }
  173. ///////////////////////////////////////////////////////////////////////////
  174. inline BOOST_SCOPED_ENUM(pass_flags) ignore()
  175. {
  176. return pass_flags::pass_ignore;
  177. }
  178. }}}
  179. #endif