1 /*============================================================================= 2 Copyright (c) 2001-2011 Hartmut Kaiser 3 4 Distributed under the Boost Software License, Version 1.0. (See accompanying 5 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6 =============================================================================*/ 7 #if !defined(BOOST_SPIRIT_CONJURE_LEXER_HPP) 8 #define BOOST_SPIRIT_CONJURE_LEXER_HPP 9 10 #include <boost/spirit/include/lex_lexertl.hpp> 11 #include <boost/spirit/include/lex_lexertl_position_token.hpp> 12 13 #include "config.hpp" 14 #include "ids.hpp" 15 16 #if CONJURE_LEXER_STATIC_TABLES != 0 17 #include <boost/spirit/include/lex_static_lexertl.hpp> 18 #include "conjure_static_lexer.hpp" 19 #elif CONJURE_LEXER_STATIC_SWITCH != 0 20 #include <boost/spirit/include/lex_static_lexertl.hpp> 21 #include "conjure_static_switch_lexer.hpp" 22 #endif 23 #include <boost/assert.hpp> 24 25 namespace client { namespace lexer 26 { 27 namespace lex = boost::spirit::lex; 28 29 /////////////////////////////////////////////////////////////////////////// 30 namespace detail 31 { 32 namespace lex = boost::spirit::lex; 33 34 template <typename BaseIterator> 35 struct get_lexer_type 36 { 37 // Our token needs to be able to carry several token values: 38 // std::string, unsigned int, and bool 39 typedef boost::mpl::vector<std::string, unsigned int, bool> 40 token_value_types; 41 42 // Using the position_token class as the token type to be returned 43 // from the lexer iterators allows to retain positional information 44 // as every token instance stores an iterator pair pointing to the 45 // matched input sequence. 46 typedef lex::lexertl::position_token< 47 BaseIterator, token_value_types, boost::mpl::false_ 48 > token_type; 49 50 #if CONJURE_LEXER_DYNAMIC_TABLES != 0 51 // use the lexer based on runtime generated DFA tables 52 typedef lex::lexertl::actor_lexer<token_type> type; 53 #elif CONJURE_LEXER_STATIC_TABLES != 0 54 // use the lexer based on pre-generated static DFA tables 55 typedef lex::lexertl::static_actor_lexer< 56 token_type 57 , boost::spirit::lex::lexertl::static_::lexer_conjure_static 58 > type; 59 #elif CONJURE_LEXER_STATIC_SWITCH != 0 60 // use the lexer based on pre-generated static code 61 typedef lex::lexertl::static_actor_lexer< 62 token_type 63 , boost::spirit::lex::lexertl::static_::lexer_conjure_static_switch 64 > type; 65 #else 66 #error "Configuration problem: please select exactly one type of lexer to build" 67 #endif 68 }; 69 } 70 71 /////////////////////////////////////////////////////////////////////////// 72 template <typename BaseIterator> 73 struct conjure_tokens 74 : lex::lexer<typename detail::get_lexer_type<BaseIterator>::type> 75 { 76 private: 77 // get the type of any qi::raw_token(...) and qi::token(...) constructs 78 typedef typename boost::spirit::result_of::terminal< 79 boost::spirit::tag::raw_token(token_ids::type) 80 >::type raw_token_spec; 81 82 typedef typename boost::spirit::result_of::terminal< 83 boost::spirit::tag::token(token_ids::type) 84 >::type token_spec; 85 86 typedef std::map<std::string, token_ids::type> keyword_map_type; 87 88 protected: 89 // add a keyword to the mapping table 90 bool add_keyword(std::string const& keyword); 91 92 public: 93 typedef BaseIterator base_iterator_type; 94 95 conjure_tokens(); 96 97 // extract a raw_token(id) for the given registered keyword operator ()client::lexer::conjure_tokens98 raw_token_spec operator()(std::string const& kwd) const 99 { 100 namespace qi = boost::spirit::qi; 101 qi::raw_token_type raw_token; 102 103 typename keyword_map_type::const_iterator it = keywords_.find(kwd); 104 BOOST_ASSERT(it != keywords_.end()); 105 return raw_token((it != keywords_.end()) ? (*it).second : token_ids::invalid); 106 } 107 108 // extract a token(id) for the given registered keyword tokenclient::lexer::conjure_tokens109 token_spec token(std::string const& kwd) const 110 { 111 namespace qi = boost::spirit::qi; 112 qi::token_type token; 113 114 typename keyword_map_type::const_iterator it = keywords_.find(kwd); 115 BOOST_ASSERT(it != keywords_.end()); 116 return token((it != keywords_.end()) ? (*it).second : token_ids::invalid); 117 } 118 119 lex::token_def<std::string> identifier; 120 lex::token_def<unsigned int> lit_uint; 121 lex::token_def<bool> true_or_false; 122 keyword_map_type keywords_; 123 }; 124 }} 125 126 #endif 127 128 129