// 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(BOOST_SPIRIT_LEX_STATIC_LEXER_FEB_10_2008_0753PM) | |
#define BOOST_SPIRIT_LEX_STATIC_LEXER_FEB_10_2008_0753PM | |
#if defined(_MSC_VER) | |
#pragma once | |
#endif | |
#include <boost/spirit/home/lex/lexer/lexertl/token.hpp> | |
#include <boost/spirit/home/lex/lexer/lexertl/functor.hpp> | |
#include <boost/spirit/home/lex/lexer/lexertl/static_functor_data.hpp> | |
#include <boost/spirit/home/lex/lexer/lexertl/iterator.hpp> | |
#include <boost/spirit/home/lex/lexer/lexertl/static_version.hpp> | |
#if defined(BOOST_SPIRIT_DEBUG) | |
#include <boost/spirit/home/support/detail/lexer/debug.hpp> | |
#endif | |
namespace boost { namespace spirit { namespace lex { namespace lexertl | |
{ | |
/////////////////////////////////////////////////////////////////////////// | |
// forward declaration | |
/////////////////////////////////////////////////////////////////////////// | |
namespace static_ | |
{ | |
struct lexer; | |
} | |
/////////////////////////////////////////////////////////////////////////// | |
// | |
// Every lexer type to be used as a lexer for Spirit has to conform to | |
// the following public interface: | |
// | |
// typedefs: | |
// iterator_type The type of the iterator exposed by this lexer. | |
// token_type The type of the tokens returned from the exposed | |
// iterators. | |
// | |
// functions: | |
// default constructor | |
// Since lexers are instantiated as base classes | |
// only it might be a good idea to make this | |
// constructor protected. | |
// begin, end Return a pair of iterators, when dereferenced | |
// returning the sequence of tokens recognized in | |
// the input stream given as the parameters to the | |
// begin() function. | |
// add_token Should add the definition of a token to be | |
// recognized by this lexer. | |
// clear Should delete all current token definitions | |
// associated with the given state of this lexer | |
// object. | |
// | |
// template parameters: | |
// Token The type of the tokens to be returned from the | |
// exposed token iterator. | |
// LexerTables See explanations below. | |
// Iterator The type of the iterator used to access the | |
// underlying character stream. | |
// Functor The type of the InputPolicy to use to instantiate | |
// the multi_pass iterator type to be used as the | |
// token iterator (returned from begin()/end()). | |
// | |
// Additionally, this implementation of a static lexer has a template | |
// parameter LexerTables allowing to customize the static lexer tables | |
// to be used. The LexerTables is expected to be a type exposing | |
// the following functions: | |
// | |
// static std::size_t const state_count() | |
// | |
// This function needs toreturn the number of lexer states | |
// contained in the table returned from the state_names() | |
// function. | |
// | |
// static char const* const* state_names() | |
// | |
// This function needs to return a pointer to a table of | |
// names of all lexer states. The table needs to have as | |
// much entries as the state_count() function returns | |
// | |
// template<typename Iterator> | |
// std::size_t next(std::size_t &start_state_, Iterator const& start_ | |
// , Iterator &start_token_, Iterator const& end_ | |
// , std::size_t& unique_id_); | |
// | |
// This function is expected to return the next matched | |
// token from the underlying input stream. | |
// | |
/////////////////////////////////////////////////////////////////////////// | |
/////////////////////////////////////////////////////////////////////////// | |
// | |
// The static_lexer class is a implementation of a Spirit.Lex | |
// lexer on top of Ben Hanson's lexertl library (For more information | |
// about lexertl go here: http://www.benhanson.net/lexertl.html). | |
// | |
// This class is designed to be used in conjunction with a generated, | |
// static lexer. For more information see the documentation (The Static | |
// Lexer Model). | |
// | |
// This class is supposed to be used as the first and only template | |
// parameter while instantiating instances of a lex::lexer class. | |
// | |
/////////////////////////////////////////////////////////////////////////// | |
template <typename Token = token<> | |
, typename LexerTables = static_::lexer | |
, typename Iterator = typename Token::iterator_type | |
, typename Functor = functor<Token, detail::static_data, Iterator> > | |
class static_lexer | |
{ | |
private: | |
struct dummy { void true_() {} }; | |
typedef void (dummy::*safe_bool)(); | |
public: | |
// object is always valid | |
operator safe_bool() const { return &dummy::true_; } | |
typedef typename boost::detail::iterator_traits<Iterator>::value_type | |
char_type; | |
typedef std::basic_string<char_type> string_type; | |
// Every lexer type to be used as a lexer for Spirit has to conform to | |
// a public interface | |
typedef Token token_type; | |
typedef typename Token::id_type id_type; | |
typedef iterator<Functor> iterator_type; | |
private: | |
// this type is purely used for the iterator_type construction below | |
struct iterator_data_type | |
{ | |
typedef typename Functor::next_token_functor next_token_functor; | |
typedef typename Functor::semantic_actions_type semantic_actions_type; | |
typedef typename Functor::get_state_name_type get_state_name_type; | |
iterator_data_type(next_token_functor next | |
, semantic_actions_type const& actions | |
, get_state_name_type get_state_name, std::size_t num_states | |
, bool bol) | |
: next_(next), actions_(actions), get_state_name_(get_state_name) | |
, num_states_(num_states), bol_(bol) | |
{} | |
next_token_functor next_; | |
semantic_actions_type const& actions_; | |
get_state_name_type get_state_name_; | |
std::size_t num_states_; | |
bool bol_; | |
private: | |
// silence MSVC warning C4512: assignment operator could not be generated | |
iterator_data_type& operator= (iterator_data_type const&); | |
}; | |
typedef LexerTables tables_type; | |
// The following static assertion fires if the referenced static lexer | |
// tables are generated by a different static lexer version as used for | |
// the current compilation unit. Please regenerate your static lexer | |
// tables before trying to create a static_lexer<> instance. | |
BOOST_SPIRIT_ASSERT_MSG( | |
tables_type::static_version == SPIRIT_STATIC_LEXER_VERSION | |
, incompatible_static_lexer_version, (LexerTables)); | |
public: | |
// Return the start iterator usable for iterating over the generated | |
// tokens, the generated function next_token(...) is called to match | |
// the next token from the input. | |
template <typename Iterator_> | |
iterator_type begin(Iterator_& first, Iterator_ const& last | |
, char_type const* initial_state = 0) const | |
{ | |
iterator_data_type iterator_data( | |
&tables_type::template next<Iterator_>, actions_ | |
, &tables_type::state_name, tables_type::state_count() | |
, tables_type::supports_bol | |
); | |
return iterator_type(iterator_data, first, last, initial_state); | |
} | |
// Return the end iterator usable to stop iterating over the generated | |
// tokens. | |
iterator_type end() const | |
{ | |
return iterator_type(); | |
} | |
protected: | |
// Lexer instances can be created by means of a derived class only. | |
static_lexer(unsigned int) : unique_id_(0) {} | |
public: | |
// interface for token definition management | |
std::size_t add_token (char_type const*, char_type, std::size_t | |
, char_type const*) | |
{ | |
return unique_id_++; | |
} | |
std::size_t add_token (char_type const*, string_type const& | |
, std::size_t, char_type const*) | |
{ | |
return unique_id_++; | |
} | |
// interface for pattern definition management | |
void add_pattern (char_type const*, string_type const& | |
, string_type const&) {} | |
void clear(char_type const*) {} | |
std::size_t add_state(char_type const* state) | |
{ | |
return detail::get_state_id(state, &tables_type::state_name | |
, tables_type::state_count()); | |
} | |
string_type initial_state() const | |
{ | |
return tables_type::state_name(0); | |
} | |
// register a semantic action with the given id | |
template <typename F> | |
void add_action(id_type unique_id, std::size_t state, F act) | |
{ | |
typedef typename Functor::wrap_action_type wrapper_type; | |
actions_.add_action(unique_id, state, wrapper_type::call(act)); | |
} | |
bool init_dfa(bool minimize = false) const { return true; } | |
private: | |
typename Functor::semantic_actions_type actions_; | |
std::size_t unique_id_; | |
}; | |
/////////////////////////////////////////////////////////////////////////// | |
// | |
// The static_actor_lexer class is another implementation of a | |
// Spirit.Lex lexer on top of Ben Hanson's lexertl library as outlined | |
// above (For more information about lexertl go here: | |
// http://www.benhanson.net/lexertl.html). | |
// | |
// Just as the static_lexer class it is meant to be used with | |
// a statically generated lexer as outlined above. | |
// | |
// The only difference to the static_lexer class above is that | |
// token_def definitions may have semantic (lexer) actions attached while | |
// being defined: | |
// | |
// int w; | |
// token_def<> word = "[^ \t\n]+"; | |
// self = word[++ref(w)]; // see example: word_count_lexer | |
// | |
// This class is supposed to be used as the first and only template | |
// parameter while instantiating instances of a lex::lexer class. | |
// | |
/////////////////////////////////////////////////////////////////////////// | |
template <typename Token = token<> | |
, typename LexerTables = static_::lexer | |
, typename Iterator = typename Token::iterator_type | |
, typename Functor | |
= functor<Token, detail::static_data, Iterator, mpl::true_> > | |
class static_actor_lexer | |
: public static_lexer<Token, LexerTables, Iterator, Functor> | |
{ | |
protected: | |
// Lexer instances can be created by means of a derived class only. | |
static_actor_lexer(unsigned int flags) | |
: static_lexer<Token, LexerTables, Iterator, Functor>(flags) | |
{} | |
}; | |
}}}} | |
#endif |