~twpol/dcplusplus/trunk

« back to all changes in this revision

Viewing changes to boost/boost/spirit/home/lex/lexer/lexer.hpp

  • Committer: James Ross
  • Date: 2010-07-05 00:03:18 UTC
  • mfrom: (1524.1.650 dcplusplus)
  • Revision ID: silver@warwickcompsoc.co.uk-20100705000318-awwqm8ocpp5m47yz
Merged to trunk.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
//  Copyright (c) 2001-2009 Hartmut Kaiser
2
 
// 
3
 
//  Distributed under the Boost Software License, Version 1.0. (See accompanying 
4
 
//  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5
 
 
6
 
#if !defined(BOOST_SPIRIT_LEX_LEXER_MAR_13_2007_0145PM)
7
 
#define BOOST_SPIRIT_LEX_LEXER_MAR_13_2007_0145PM
8
 
 
9
 
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
10
 
#pragma once      // MS compatible compilers support #pragma once
11
 
#endif
12
 
 
13
 
#include <boost/spirit/home/support/safe_bool.hpp>
14
 
#include <boost/spirit/home/lex/lexer/lexer_fwd.hpp>
15
 
#include <boost/spirit/home/lex/lexer/terminal_holder.hpp>
16
 
#include <boost/spirit/home/lex/lexer/token_def.hpp>
17
 
#include <boost/noncopyable.hpp>
18
 
#include <boost/detail/iterator.hpp>
19
 
#include <boost/fusion/include/vector.hpp>
20
 
#include <boost/assert.hpp>
21
 
#include <boost/mpl/assert.hpp>
22
 
#include <string>
23
 
#include <boost/range/iterator_range.hpp>
24
 
 
25
 
namespace boost { namespace spirit { namespace lex
26
 
{
27
 
    namespace detail
28
 
    {
29
 
        ///////////////////////////////////////////////////////////////////////
30
 
        template <typename LexerDef>
31
 
        struct lexer_def_
32
 
          : public proto::extends<
33
 
                typename make_terminal_holder<
34
 
                    lexer_def_<LexerDef> const*, lexer_def_<LexerDef>
35
 
                >::type,
36
 
                lexer_def_<LexerDef>
37
 
            >
38
 
        {
39
 
        private:
40
 
            // avoid warnings about using 'this' in constructor
41
 
            lexer_def_& this_() { return *this; }    
42
 
 
43
 
            // initialize proto base class
44
 
            typedef 
45
 
                terminal_holder<lexer_def_ const*, lexer_def_> 
46
 
            terminal_holder_;
47
 
            typedef typename proto::terminal<terminal_holder_>::type tag;
48
 
            typedef proto::extends<tag, lexer_def_> base_type;
49
 
 
50
 
            typedef typename LexerDef::id_type id_type;
51
 
            
52
 
            tag make_tag() const
53
 
            {
54
 
                tag xpr = {{ this }};
55
 
                return xpr;
56
 
            }
57
 
            
58
 
            typedef typename LexerDef::char_type char_type;
59
 
            typedef typename LexerDef::string_type string_type;
60
 
 
61
 
        public:
62
 
            // Qi interface: metafunction calculating parser return type
63
 
            template <typename Component, typename Context, typename Iterator>
64
 
            struct attribute
65
 
            {
66
 
                //  the return value of a token set contains the matched token 
67
 
                //  id, and the corresponding pair of iterators
68
 
                typedef typename Iterator::base_iterator_type iterator_type;
69
 
                typedef 
70
 
                    fusion::vector<id_type, iterator_range<iterator_type> > 
71
 
                type;
72
 
            };
73
 
                
74
 
        private:
75
 
            // Qi interface: parse functionality
76
 
            template <typename Iterator, typename Context, typename Skipper, 
77
 
                typename Attribute>
78
 
            bool parse(Iterator& first, Iterator const& last, 
79
 
                Context& context, Skipper const& skipper, Attribute& attr) const
80
 
            {
81
 
                qi::skip(first, last, skipper);   // always do a pre-skip
82
 
 
83
 
                if (first != last) {
84
 
                    typedef typename 
85
 
                        boost::detail::iterator_traits<Iterator>::value_type 
86
 
                    token_type;
87
 
 
88
 
                    token_type &t = *first;
89
 
                    if (token_is_valid(t)) {
90
 
                    // any of the token definitions matched
91
 
                        qi::detail::assign_to(t, attr);
92
 
                        ++first;
93
 
                        return true;
94
 
                    }
95
 
                }
96
 
                return false;
97
 
            }
98
 
            friend struct terminal_director;
99
 
 
100
 
            static std::string what()
101
 
            {
102
 
                return "lexer";
103
 
            }
104
 
 
105
 
            // allow to use the lexer.self.add("regex1", id1)("regex2", id2);
106
 
            // syntax
107
 
            struct adder
108
 
            {
109
 
                adder(lexer_def_& def_) 
110
 
                : def(def_)
111
 
                {}
112
 
 
113
 
                adder const&
114
 
                operator()(char_type c, id_type token_id = 0) const
115
 
                {
116
 
                    if (0 == token_id)
117
 
                        token_id = static_cast<id_type>(c);
118
 
                    def.def.add_token (def.state.c_str(), lex::detail::escape(c), 
119
 
                        token_id);
120
 
                    return *this;
121
 
                }
122
 
                adder const&
123
 
                operator()(string_type const& s, id_type token_id = id_type()) const
124
 
                {
125
 
                    if (0 == token_id)
126
 
                        token_id = next_id<id_type>::get();
127
 
                    def.def.add_token (def.state.c_str(), s, token_id);
128
 
                    return *this;
129
 
                }
130
 
                template <typename Attribute>
131
 
                adder const&
132
 
                operator()(token_def<Attribute, char_type, id_type>& tokdef, 
133
 
                    id_type token_id = id_type()) const
134
 
                {
135
 
                    // make sure we have a token id
136
 
                    if (0 == token_id) {
137
 
                        if (0 == tokdef.id()) {
138
 
                            token_id = next_id<id_type>::get();
139
 
                            tokdef.id(token_id);
140
 
                        }
141
 
                        else {
142
 
                            token_id = tokdef.id();
143
 
                        }
144
 
                    }
145
 
                    else { 
146
 
                    // the following assertion makes sure, that the token_def
147
 
                    // instance has not been assigned a different id earlier
148
 
                        BOOST_ASSERT(0 == tokdef.id() || token_id == tokdef.id());
149
 
                        tokdef.id(token_id);
150
 
                    }
151
 
                    
152
 
                    def.define(tokdef);
153
 
                    return *this;
154
 
                }
155
 
                template <typename TokenSet>
156
 
                adder const&
157
 
                operator()(token_set<TokenSet>& tokset) const
158
 
                {
159
 
                    def.define(tokset);
160
 
                    return *this;
161
 
                }
162
 
 
163
 
                lexer_def_& def;
164
 
            };
165
 
            friend struct adder;
166
 
            
167
 
            // allow to use lexer.self.add_pattern("pattern1", "regex1")(...);
168
 
            // syntax
169
 
            struct pattern_adder
170
 
            {
171
 
                pattern_adder(lexer_def_& def_) 
172
 
                : def(def_)
173
 
                {}
174
 
 
175
 
                pattern_adder const&
176
 
                operator()(string_type const& p, string_type const& s) const
177
 
                {
178
 
                    def.def.add_pattern (def.state.c_str(), p, s);
179
 
                    return *this;
180
 
                }
181
 
 
182
 
                lexer_def_& def;
183
 
            };
184
 
            friend struct pattern_adder;
185
 
            
186
 
        public:
187
 
            ///////////////////////////////////////////////////////////////////
188
 
            template <typename Expr>
189
 
            void define(Expr const& xpr)
190
 
            {
191
 
                typedef typename
192
 
                    result_of::as_component<lex::domain, Expr>::type
193
 
                component;
194
 
                typedef typename component::director director;
195
 
                
196
 
                component c = spirit::as_component(lex::domain(), xpr);
197
 
                director::collect(c, def, state);
198
 
            }
199
 
 
200
 
            lexer_def_(LexerDef& def_, string_type const& state_)
201
 
              : base_type(make_tag()), add(this_()), add_pattern(this_()),
202
 
                def(def_), state(state_)
203
 
            {
204
 
            }
205
 
 
206
 
            // allow to switch states
207
 
            lexer_def_ operator()(char_type const* state) const
208
 
            {
209
 
                return lexer_def_(def, state);
210
 
            }
211
 
            lexer_def_ operator()(string_type const& state) const
212
 
            {
213
 
                return lexer_def_(def, state);
214
 
            }
215
 
            
216
 
            // allow to assign a token definition expression
217
 
            template <typename Expr>
218
 
            lexer_def_& operator= (Expr const& xpr)
219
 
            {
220
 
                typedef 
221
 
                    spirit::traits::is_component<lex::domain, Expr> 
222
 
                is_component;
223
 
 
224
 
                // report invalid expression error as early as possible
225
 
                BOOST_MPL_ASSERT_MSG(
226
 
                    is_component::value,
227
 
                    xpr_is_not_convertible_to_a_token_definition, ());
228
 
 
229
 
                def.clear(state.c_str());
230
 
                define(xpr);
231
 
                return *this;
232
 
            }
233
 
 
234
 
            adder add;
235
 
            pattern_adder add_pattern;
236
 
            
237
 
        private:
238
 
            LexerDef& def;
239
 
            string_type state;
240
 
        };
241
 
    
242
 
        // allow to assign a token definition expression
243
 
        template <typename LexerDef, typename Expr>
244
 
        inline lexer_def_<LexerDef>&
245
 
        operator+= (lexer_def_<LexerDef>& lexdef, Expr& xpr)
246
 
        {
247
 
            typedef 
248
 
                spirit::traits::is_component<lex::domain, Expr> 
249
 
            is_component;
250
 
 
251
 
            // report invalid expression error as early as possible
252
 
            BOOST_MPL_ASSERT_MSG(
253
 
                is_component::value,
254
 
                xpr_is_not_convertible_to_a_token_definition, ());
255
 
 
256
 
            lexdef.define(xpr);
257
 
            return lexdef;
258
 
        }
259
 
        
260
 
        template <typename LexerDef, typename Expr>
261
 
        inline lexer_def_<LexerDef>& 
262
 
        operator+= (lexer_def_<LexerDef>& lexdef, Expr const& xpr)
263
 
        {
264
 
            typedef 
265
 
                spirit::traits::is_component<lex::domain, Expr> 
266
 
            is_component;
267
 
 
268
 
            // report invalid expression error as early as possible
269
 
            BOOST_MPL_ASSERT_MSG(
270
 
                is_component::value,
271
 
                xpr_is_not_convertible_to_a_token_definition, ());
272
 
 
273
 
            lexdef.define(xpr);
274
 
            return lexdef;
275
 
        }
276
 
    }
277
 
 
278
 
    ///////////////////////////////////////////////////////////////////////////
279
 
    //  This represents a lexer definition (helper for token and token set 
280
 
    //  definitions
281
 
    ///////////////////////////////////////////////////////////////////////////
282
 
    template <typename Lexer>
283
 
    class lexer_def : private noncopyable, public Lexer
284
 
    {
285
 
    private:
286
 
        typedef lexer_def self_type;
287
 
        
288
 
        // avoid warnings about using 'this' in constructor
289
 
        lexer_def& this_() { return *this; }    
290
 
 
291
 
    public:        
292
 
        typedef Lexer lexer_type;
293
 
        typedef typename Lexer::id_type id_type;
294
 
        typedef detail::lexer_def_<self_type> token_set;
295
 
        typedef typename Lexer::char_type char_type;
296
 
        typedef std::basic_string<char_type> string_type;
297
 
        
298
 
        lexer_def() 
299
 
          : self(this_(), Lexer::initial_state())  
300
 
        {
301
 
        }
302
 
 
303
 
        token_set self;  // allow for easy token definition
304
 
        
305
 
        // this is just a dummy implementation to allow to use lexer_def 
306
 
        // directly, without having to derive a separate class
307
 
        void def(token_set& /*self*/) {}
308
 
    };
309
 
    
310
 
    ///////////////////////////////////////////////////////////////////////////
311
 
    //  This represents a lexer object
312
 
    ///////////////////////////////////////////////////////////////////////////
313
 
    template <typename Definition>
314
 
    class lexer : public safe_bool<lexer<Definition> >
315
 
    {
316
 
    public:
317
 
        // operator_bool() is needed for the safe_bool base class
318
 
        bool operator_bool() const { return token_def; }
319
 
 
320
 
        typedef typename Definition::lexer_type lexer_type;
321
 
        typedef typename Definition::char_type char_type;
322
 
        typedef typename Definition::iterator_type iterator_type;
323
 
        typedef typename Definition::id_type id_type;
324
 
 
325
 
        lexer(Definition& token_def_)
326
 
          : token_def(token_def_) 
327
 
        {
328
 
            // call initialization routine supplied by the target lexer
329
 
            token_def.def(token_def.self);
330
 
        }
331
 
 
332
 
        // access iterator interface
333
 
        template <typename Iterator>
334
 
        iterator_type begin(Iterator& first, Iterator const& last) const
335
 
            { return token_def.begin(first, last); }
336
 
        iterator_type end() const { return token_def.end(); }
337
 
    
338
 
        std::size_t map_state(char_type const* state)
339
 
            { return token_def.add_state(state); }
340
 
        
341
 
        Definition& get_definition() { return token_def; }
342
 
        Definition  const& get_definition() const { return token_def; }
343
 
        
344
 
    private:
345
 
        Definition& token_def;
346
 
    };
347
 
 
348
 
    ///////////////////////////////////////////////////////////////////////////
349
 
    //  Metafunction returning the iterator type of the lexer given the token 
350
 
    //  definition type.
351
 
    ///////////////////////////////////////////////////////////////////////////
352
 
    template <typename Definition>
353
 
    struct lexer_iterator
354
 
    {
355
 
        typedef typename lexer<Definition>::iterator_type type;
356
 
    };
357
 
 
358
 
    ///////////////////////////////////////////////////////////////////////////
359
 
    //  Generator function helping to construct a proper lexer object 
360
 
    //  instance
361
 
    ///////////////////////////////////////////////////////////////////////////
362
 
    template <typename Definition>
363
 
    inline lexer<Definition> 
364
 
    make_lexer(Definition& def)
365
 
    {
366
 
        return lexer<Definition>(def);
367
 
    }
368
 
    
369
 
}}}
370
 
 
371
 
#endif
 
1
//  Copyright (c) 2001-2009 Hartmut Kaiser
 
2
// 
 
3
//  Distributed under the Boost Software License, Version 1.0. (See accompanying 
 
4
//  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
 
5
 
 
6
#if !defined(BOOST_SPIRIT_LEX_LEXER_MAR_13_2007_0145PM)
 
7
#define BOOST_SPIRIT_LEX_LEXER_MAR_13_2007_0145PM
 
8
 
 
9
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
 
10
#pragma once      // MS compatible compilers support #pragma once
 
11
#endif
 
12
 
 
13
#include <boost/spirit/home/support/safe_bool.hpp>
 
14
#include <boost/spirit/home/lex/lexer/lexer_fwd.hpp>
 
15
#include <boost/spirit/home/lex/lexer/terminal_holder.hpp>
 
16
#include <boost/spirit/home/lex/lexer/token_def.hpp>
 
17
#include <boost/noncopyable.hpp>
 
18
#include <boost/detail/iterator.hpp>
 
19
#include <boost/fusion/include/vector.hpp>
 
20
#include <boost/assert.hpp>
 
21
#include <boost/mpl/assert.hpp>
 
22
#include <string>
 
23
#include <boost/range/iterator_range.hpp>
 
24
 
 
25
namespace boost { namespace spirit { namespace lex
 
26
{
 
27
    namespace detail
 
28
    {
 
29
        ///////////////////////////////////////////////////////////////////////
 
30
        template <typename LexerDef>
 
31
        struct lexer_def_
 
32
          : public proto::extends<
 
33
                typename make_terminal_holder<
 
34
                    lexer_def_<LexerDef> const*, lexer_def_<LexerDef>
 
35
                >::type,
 
36
                lexer_def_<LexerDef>
 
37
            >
 
38
        {
 
39
        private:
 
40
            // avoid warnings about using 'this' in constructor
 
41
            lexer_def_& this_() { return *this; }    
 
42
 
 
43
            // initialize proto base class
 
44
            typedef 
 
45
                terminal_holder<lexer_def_ const*, lexer_def_> 
 
46
            terminal_holder_;
 
47
            typedef typename proto::terminal<terminal_holder_>::type tag;
 
48
            typedef proto::extends<tag, lexer_def_> base_type;
 
49
 
 
50
            typedef typename LexerDef::id_type id_type;
 
51
            
 
52
            tag make_tag() const
 
53
            {
 
54
                tag xpr = {{ this }};
 
55
                return xpr;
 
56
            }
 
57
            
 
58
            typedef typename LexerDef::char_type char_type;
 
59
            typedef typename LexerDef::string_type string_type;
 
60
 
 
61
        public:
 
62
            // Qi interface: metafunction calculating parser return type
 
63
            template <typename Component, typename Context, typename Iterator>
 
64
            struct attribute
 
65
            {
 
66
                //  the return value of a token set contains the matched token 
 
67
                //  id, and the corresponding pair of iterators
 
68
                typedef typename Iterator::base_iterator_type iterator_type;
 
69
                typedef 
 
70
                    fusion::vector<id_type, iterator_range<iterator_type> > 
 
71
                type;
 
72
            };
 
73
                
 
74
        private:
 
75
            // Qi interface: parse functionality
 
76
            template <typename Iterator, typename Context, typename Skipper, 
 
77
                typename Attribute>
 
78
            bool parse(Iterator& first, Iterator const& last, 
 
79
                Context& context, Skipper const& skipper, Attribute& attr) const
 
80
            {
 
81
                qi::skip(first, last, skipper);   // always do a pre-skip
 
82
 
 
83
                if (first != last) {
 
84
                    typedef typename 
 
85
                        boost::detail::iterator_traits<Iterator>::value_type 
 
86
                    token_type;
 
87
 
 
88
                    token_type &t = *first;
 
89
                    if (token_is_valid(t)) {
 
90
                    // any of the token definitions matched
 
91
                        qi::detail::assign_to(t, attr);
 
92
                        ++first;
 
93
                        return true;
 
94
                    }
 
95
                }
 
96
                return false;
 
97
            }
 
98
            friend struct terminal_director;
 
99
 
 
100
            static std::string what()
 
101
            {
 
102
                return "lexer";
 
103
            }
 
104
 
 
105
            // allow to use the lexer.self.add("regex1", id1)("regex2", id2);
 
106
            // syntax
 
107
            struct adder
 
108
            {
 
109
                adder(lexer_def_& def_) 
 
110
                : def(def_)
 
111
                {}
 
112
 
 
113
                adder const&
 
114
                operator()(char_type c, id_type token_id = 0) const
 
115
                {
 
116
                    if (0 == token_id)
 
117
                        token_id = static_cast<id_type>(c);
 
118
                    def.def.add_token (def.state.c_str(), lex::detail::escape(c), 
 
119
                        token_id);
 
120
                    return *this;
 
121
                }
 
122
                adder const&
 
123
                operator()(string_type const& s, id_type token_id = id_type()) const
 
124
                {
 
125
                    if (0 == token_id)
 
126
                        token_id = next_id<id_type>::get();
 
127
                    def.def.add_token (def.state.c_str(), s, token_id);
 
128
                    return *this;
 
129
                }
 
130
                template <typename Attribute>
 
131
                adder const&
 
132
                operator()(token_def<Attribute, char_type, id_type>& tokdef, 
 
133
                    id_type token_id = id_type()) const
 
134
                {
 
135
                    // make sure we have a token id
 
136
                    if (0 == token_id) {
 
137
                        if (0 == tokdef.id()) {
 
138
                            token_id = next_id<id_type>::get();
 
139
                            tokdef.id(token_id);
 
140
                        }
 
141
                        else {
 
142
                            token_id = tokdef.id();
 
143
                        }
 
144
                    }
 
145
                    else { 
 
146
                    // the following assertion makes sure, that the token_def
 
147
                    // instance has not been assigned a different id earlier
 
148
                        BOOST_ASSERT(0 == tokdef.id() || token_id == tokdef.id());
 
149
                        tokdef.id(token_id);
 
150
                    }
 
151
                    
 
152
                    def.define(tokdef);
 
153
                    return *this;
 
154
                }
 
155
                template <typename TokenSet>
 
156
                adder const&
 
157
                operator()(token_set<TokenSet>& tokset) const
 
158
                {
 
159
                    def.define(tokset);
 
160
                    return *this;
 
161
                }
 
162
 
 
163
                lexer_def_& def;
 
164
            };
 
165
            friend struct adder;
 
166
            
 
167
            // allow to use lexer.self.add_pattern("pattern1", "regex1")(...);
 
168
            // syntax
 
169
            struct pattern_adder
 
170
            {
 
171
                pattern_adder(lexer_def_& def_) 
 
172
                : def(def_)
 
173
                {}
 
174
 
 
175
                pattern_adder const&
 
176
                operator()(string_type const& p, string_type const& s) const
 
177
                {
 
178
                    def.def.add_pattern (def.state.c_str(), p, s);
 
179
                    return *this;
 
180
                }
 
181
 
 
182
                lexer_def_& def;
 
183
            };
 
184
            friend struct pattern_adder;
 
185
            
 
186
        public:
 
187
            ///////////////////////////////////////////////////////////////////
 
188
            template <typename Expr>
 
189
            void define(Expr const& xpr)
 
190
            {
 
191
                typedef typename
 
192
                    result_of::as_component<lex::domain, Expr>::type
 
193
                component;
 
194
                typedef typename component::director director;
 
195
                
 
196
                component c = spirit::as_component(lex::domain(), xpr);
 
197
                director::collect(c, def, state);
 
198
            }
 
199
 
 
200
            lexer_def_(LexerDef& def_, string_type const& state_)
 
201
              : base_type(make_tag()), add(this_()), add_pattern(this_()),
 
202
                def(def_), state(state_)
 
203
            {
 
204
            }
 
205
 
 
206
            // allow to switch states
 
207
            lexer_def_ operator()(char_type const* state) const
 
208
            {
 
209
                return lexer_def_(def, state);
 
210
            }
 
211
            lexer_def_ operator()(string_type const& state) const
 
212
            {
 
213
                return lexer_def_(def, state);
 
214
            }
 
215
            
 
216
            // allow to assign a token definition expression
 
217
            template <typename Expr>
 
218
            lexer_def_& operator= (Expr const& xpr)
 
219
            {
 
220
                typedef 
 
221
                    spirit::traits::is_component<lex::domain, Expr> 
 
222
                is_component;
 
223
 
 
224
                // report invalid expression error as early as possible
 
225
                BOOST_MPL_ASSERT_MSG(
 
226
                    is_component::value,
 
227
                    xpr_is_not_convertible_to_a_token_definition, ());
 
228
 
 
229
                def.clear(state.c_str());
 
230
                define(xpr);
 
231
                return *this;
 
232
            }
 
233
 
 
234
            adder add;
 
235
            pattern_adder add_pattern;
 
236
            
 
237
        private:
 
238
            LexerDef& def;
 
239
            string_type state;
 
240
        };
 
241
    
 
242
        // allow to assign a token definition expression
 
243
        template <typename LexerDef, typename Expr>
 
244
        inline lexer_def_<LexerDef>&
 
245
        operator+= (lexer_def_<LexerDef>& lexdef, Expr& xpr)
 
246
        {
 
247
            typedef 
 
248
                spirit::traits::is_component<lex::domain, Expr> 
 
249
            is_component;
 
250
 
 
251
            // report invalid expression error as early as possible
 
252
            BOOST_MPL_ASSERT_MSG(
 
253
                is_component::value,
 
254
                xpr_is_not_convertible_to_a_token_definition, ());
 
255
 
 
256
            lexdef.define(xpr);
 
257
            return lexdef;
 
258
        }
 
259
        
 
260
        template <typename LexerDef, typename Expr>
 
261
        inline lexer_def_<LexerDef>& 
 
262
        operator+= (lexer_def_<LexerDef>& lexdef, Expr const& xpr)
 
263
        {
 
264
            typedef 
 
265
                spirit::traits::is_component<lex::domain, Expr> 
 
266
            is_component;
 
267
 
 
268
            // report invalid expression error as early as possible
 
269
            BOOST_MPL_ASSERT_MSG(
 
270
                is_component::value,
 
271
                xpr_is_not_convertible_to_a_token_definition, ());
 
272
 
 
273
            lexdef.define(xpr);
 
274
            return lexdef;
 
275
        }
 
276
    }
 
277
 
 
278
    ///////////////////////////////////////////////////////////////////////////
 
279
    //  This represents a lexer definition (helper for token and token set 
 
280
    //  definitions
 
281
    ///////////////////////////////////////////////////////////////////////////
 
282
    template <typename Lexer>
 
283
    class lexer_def : private noncopyable, public Lexer
 
284
    {
 
285
    private:
 
286
        typedef lexer_def self_type;
 
287
        
 
288
        // avoid warnings about using 'this' in constructor
 
289
        lexer_def& this_() { return *this; }    
 
290
 
 
291
    public:        
 
292
        typedef Lexer lexer_type;
 
293
        typedef typename Lexer::id_type id_type;
 
294
        typedef detail::lexer_def_<self_type> token_set;
 
295
        typedef typename Lexer::char_type char_type;
 
296
        typedef std::basic_string<char_type> string_type;
 
297
        
 
298
        lexer_def() 
 
299
          : self(this_(), Lexer::initial_state())  
 
300
        {
 
301
        }
 
302
 
 
303
        token_set self;  // allow for easy token definition
 
304
        
 
305
        // this is just a dummy implementation to allow to use lexer_def 
 
306
        // directly, without having to derive a separate class
 
307
        void def(token_set& /*self*/) {}
 
308
    };
 
309
    
 
310
    ///////////////////////////////////////////////////////////////////////////
 
311
    //  This represents a lexer object
 
312
    ///////////////////////////////////////////////////////////////////////////
 
313
    template <typename Definition>
 
314
    class lexer : public safe_bool<lexer<Definition> >
 
315
    {
 
316
    public:
 
317
        // operator_bool() is needed for the safe_bool base class
 
318
        bool operator_bool() const { return token_def; }
 
319
 
 
320
        typedef typename Definition::lexer_type lexer_type;
 
321
        typedef typename Definition::char_type char_type;
 
322
        typedef typename Definition::iterator_type iterator_type;
 
323
        typedef typename Definition::id_type id_type;
 
324
 
 
325
        lexer(Definition& token_def_)
 
326
          : token_def(token_def_) 
 
327
        {
 
328
            // call initialization routine supplied by the target lexer
 
329
            token_def.def(token_def.self);
 
330
        }
 
331
 
 
332
        // access iterator interface
 
333
        template <typename Iterator>
 
334
        iterator_type begin(Iterator& first, Iterator const& last) const
 
335
            { return token_def.begin(first, last); }
 
336
        iterator_type end() const { return token_def.end(); }
 
337
    
 
338
        std::size_t map_state(char_type const* state)
 
339
            { return token_def.add_state(state); }
 
340
        
 
341
        Definition& get_definition() { return token_def; }
 
342
        Definition  const& get_definition() const { return token_def; }
 
343
        
 
344
    private:
 
345
        Definition& token_def;
 
346
    };
 
347
 
 
348
    ///////////////////////////////////////////////////////////////////////////
 
349
    //  Metafunction returning the iterator type of the lexer given the token 
 
350
    //  definition type.
 
351
    ///////////////////////////////////////////////////////////////////////////
 
352
    template <typename Definition>
 
353
    struct lexer_iterator
 
354
    {
 
355
        typedef typename lexer<Definition>::iterator_type type;
 
356
    };
 
357
 
 
358
    ///////////////////////////////////////////////////////////////////////////
 
359
    //  Generator function helping to construct a proper lexer object 
 
360
    //  instance
 
361
    ///////////////////////////////////////////////////////////////////////////
 
362
    template <typename Definition>
 
363
    inline lexer<Definition> 
 
364
    make_lexer(Definition& def)
 
365
    {
 
366
        return lexer<Definition>(def);
 
367
    }
 
368
    
 
369
}}}
 
370
 
 
371
#endif