• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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