support_functions.hpp 7.4 KB

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