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