// 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(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 #include #include #include #include #if defined(BOOST_SPIRIT_DEBUG) #include #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 // 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 LexerTables = static_::lexer , typename Iterator = typename Token::iterator_type , typename Functor = functor > 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::value_type char_type; typedef std::basic_string 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 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 iterator_type begin(Iterator_& first, Iterator_ const& last , char_type const* initial_state = 0) const { iterator_data_type iterator_data( &tables_type::template next, 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) { return unique_id_++; } std::size_t add_token (char_type const*, string_type const& , std::size_t) { 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 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 LexerTables = static_::lexer , typename Iterator = typename Token::iterator_type , typename Functor = functor > class static_actor_lexer : public static_lexer { protected: // Lexer instances can be created by means of a derived class only. static_actor_lexer(unsigned int flags) : static_lexer(flags) {} }; }}}} #endif