boost/spirit/home/lex/lexer/support_functions.hpp
// Copyright (c) 2001-2010 Hartmut Kaiser // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #if !defined(SPIRIT_LEX_SUPPORT_FUNCTIONS_JUN_08_2009_0211PM) #define SPIRIT_LEX_SUPPORT_FUNCTIONS_JUN_08_2009_0211PM #if defined(_MSC_VER) #pragma once #endif #include <boost/spirit/home/phoenix/core/actor.hpp> #include <boost/spirit/home/phoenix/core/argument.hpp> #include <boost/spirit/home/phoenix/core/compose.hpp> #include <boost/spirit/home/phoenix/core/value.hpp> #include <boost/spirit/home/phoenix/core/as_actor.hpp> #include <boost/spirit/home/support/detail/scoped_enum_emulation.hpp> #include <boost/spirit/home/lex/lexer/pass_flags.hpp> /////////////////////////////////////////////////////////////////////////////// namespace boost { namespace spirit { namespace lex { /////////////////////////////////////////////////////////////////////////// // The function less() is used by the implementation of the support // function lex::less(). Its functionality is equivalent to flex' function // yyless(): it returns an iterator positioned to the nth input character // beyond the current start iterator (i.e. by assigning the return value to // the placeholder '_end' it is possible to return all but the first n // characters of the current token back to the input stream. // // This Phoenix actor is invoked whenever the function lex::less(n) is // used inside a lexer semantic action: // // lex::token_def<> identifier = "[a-zA-Z_][a-zA-Z0-9_]*"; // this->self = identifier [ _end = lex::less(4) ]; // // The example shows how to limit the length of the matched identifier to // four characters. // // Note: the function lex::less() has no effect if used on it's own, you // need to use the returned result in order to make use of its // functionality. template <typename Actor> struct less_type { typedef mpl::true_ no_nullary; template <typename Env> struct result { typedef typename remove_const< typename mpl::at_c<typename Env::args_type, 4>::type >::type context_type; typedef typename context_type::base_iterator_type type; }; template <typename Env> typename result<Env>::type eval(Env const& env) const { typename result<Env>::type it; return fusion::at_c<4>(env.args()).less(it, actor_()); } less_type(Actor const& actor) : actor_(actor) {} Actor actor_; }; // The function lex::less() is used to create a Phoenix actor allowing to // implement functionality similar to flex' function yyless(). template <typename T> inline phoenix::actor<less_type<typename phoenix::as_actor<T>::type> > less(T const& v) { typedef typename phoenix::as_actor<T>::type actor_type; return less_type<actor_type>(phoenix::as_actor<T>::convert(v)); } /////////////////////////////////////////////////////////////////////////// // The function more() is used by the implemention of the support function // lex::more(). Its functionality is equivalent to flex' function yymore(): // it tells the lexer that the next time it matches a rule, the // corresponding token should be appended onto the current token value // rather than replacing it. // // This Phoenix actor is invoked whenever the function lex::less(n) is // used inside a lexer semantic action: // // lex::token_def<> identifier = "[a-zA-Z_][a-zA-Z0-9_]*"; // this->self = identifier [ lex::more() ]; // // The example shows how prefix the next matched token with the matched // identifier. struct more_type { typedef mpl::true_ no_nullary; template <typename Env> struct result { typedef void type; }; template <typename Env> void eval(Env const& env) const { fusion::at_c<4>(env.args()).more(); } }; // The function lex::more() is used to create a Phoenix actor allowing to // implement functionality similar to flex' function yymore(). inline phoenix::actor<more_type> more() { return more_type(); } /////////////////////////////////////////////////////////////////////////// template <typename Actor> struct lookahead_type { typedef mpl::true_ no_nullary; template <typename Env> struct result { typedef bool type; }; template <typename Env> bool eval(Env const& env) const { return fusion::at_c<4>(env.args()).lookahead(actor_()); } lookahead_type(Actor const& actor) : actor_(actor) {} Actor actor_; }; template <typename T> inline phoenix::actor< lookahead_type<typename phoenix::as_actor<T>::type> > lookahead(T const& id) { typedef typename phoenix::as_actor<T>::type actor_type; return lookahead_type<actor_type>(phoenix::as_actor<T>::convert(id)); } template <typename Attribute, typename Char, typename Idtype> inline phoenix::actor< lookahead_type<typename phoenix::as_actor<Idtype>::type> > lookahead(token_def<Attribute, Char, Idtype> const& tok) { typedef typename phoenix::as_actor<Idtype>::type actor_type; return lookahead_type<actor_type>( phoenix::as_actor<Idtype>::convert(tok.id())); } /////////////////////////////////////////////////////////////////////////// inline BOOST_SCOPED_ENUM(pass_flags) ignore() { return pass_flags::pass_ignore; } }}} #endif