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