// Copyright (c) 2001-2011 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 #include #include #include /////////////////////////////////////////////////////////////////////////////// namespace boost { namespace spirit { namespace lex { /////////////////////////////////////////////////////////////////////////// // The function object less_type 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 struct less_type { typedef mpl::true_ no_nullary; template struct result { typedef typename remove_reference< typename remove_const< typename mpl::at_c::type >::type >::type context_type; typedef typename context_type::base_iterator_type type; }; template typename result::type eval(Env const& env) const { typename result::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 inline typename expression::less< typename phoenix::as_actor::type >::type const less(T const& v) { return expression::less::make(phoenix::as_actor::convert(v)); } /////////////////////////////////////////////////////////////////////////// // The function object more_type is used by the implementation 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::more(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 struct result { typedef void type; }; template 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 expression::more::type const inline phoenix::actor more() { return phoenix::actor(); } /////////////////////////////////////////////////////////////////////////// // The function object lookahead_type is used by the implementation of the // support function lex::lookahead(). Its functionality is needed to // emulate the flex' lookahead operator a/b. Use lex::lookahead() inside // of lexer semantic actions to test whether the argument to this function // matches the current look ahead input. lex::lookahead() can be used with // either a token id or a token_def instance as its argument. It returns // a bool indicating whether the look ahead has been matched. template struct lookahead_type { typedef mpl::true_ no_nullary; template struct result { typedef bool type; }; template bool eval(Env const& env) const { return fusion::at_c<4>(env.args()). lookahead(id_actor_(), state_actor_()); } lookahead_type(IdActor const& id_actor, StateActor const& state_actor) : id_actor_(id_actor), state_actor_(state_actor) {} IdActor id_actor_; StateActor state_actor_; }; // The function lex::lookahead() is used to create a Phoenix actor // allowing to implement functionality similar to flex' lookahead operator // a/b. template inline typename expression::lookahead< typename phoenix::as_actor::type , typename phoenix::as_actor::type >::type const lookahead(T const& id) { typedef typename phoenix::as_actor::type id_actor_type; typedef typename phoenix::as_actor::type state_actor_type; return expression::lookahead::make( phoenix::as_actor::convert(id), phoenix::as_actor::convert(std::size_t(~0))); } template inline typename expression::lookahead< typename phoenix::as_actor::type , typename phoenix::as_actor::type >::type const lookahead(token_def const& tok) { typedef typename phoenix::as_actor::type id_actor_type; typedef typename phoenix::as_actor::type state_actor_type; std::size_t state = tok.state(); // The following assertion fires if you pass a token_def instance to // lex::lookahead without first associating this instance with the // lexer. BOOST_ASSERT(std::size_t(~0) != state && "token_def instance not associated with lexer yet"); return expression::lookahead::make( phoenix::as_actor::convert(tok.id()), phoenix::as_actor::convert(state)); } /////////////////////////////////////////////////////////////////////////// inline BOOST_SCOPED_ENUM(pass_flags) ignore() { return pass_flags::pass_ignore; } }}} #endif