blob: 4630080e55d1cff3e265a032049dd9320a8b5947 [file] [log] [blame]
// 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