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