1
// Copyright (c) 2001-2009 Hartmut Kaiser
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)
6
#if !defined(BOOST_SPIRIT_LEX_LEXER_MAR_13_2007_0145PM)
7
#define BOOST_SPIRIT_LEX_LEXER_MAR_13_2007_0145PM
9
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
10
#pragma once // MS compatible compilers support #pragma once
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>
23
#include <boost/range/iterator_range.hpp>
25
namespace boost { namespace spirit { namespace lex
29
///////////////////////////////////////////////////////////////////////
30
template <typename LexerDef>
32
: public proto::extends<
33
typename make_terminal_holder<
34
lexer_def_<LexerDef> const*, lexer_def_<LexerDef>
40
// avoid warnings about using 'this' in constructor
41
lexer_def_& this_() { return *this; }
43
// initialize proto base class
45
terminal_holder<lexer_def_ const*, lexer_def_>
47
typedef typename proto::terminal<terminal_holder_>::type tag;
48
typedef proto::extends<tag, lexer_def_> base_type;
50
typedef typename LexerDef::id_type id_type;
58
typedef typename LexerDef::char_type char_type;
59
typedef typename LexerDef::string_type string_type;
62
// Qi interface: metafunction calculating parser return type
63
template <typename Component, typename Context, typename Iterator>
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;
70
fusion::vector<id_type, iterator_range<iterator_type> >
75
// Qi interface: parse functionality
76
template <typename Iterator, typename Context, typename Skipper,
78
bool parse(Iterator& first, Iterator const& last,
79
Context& context, Skipper const& skipper, Attribute& attr) const
81
qi::skip(first, last, skipper); // always do a pre-skip
85
boost::detail::iterator_traits<Iterator>::value_type
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);
98
friend struct terminal_director;
100
static std::string what()
105
// allow to use the lexer.self.add("regex1", id1)("regex2", id2);
109
adder(lexer_def_& def_)
114
operator()(char_type c, id_type token_id = 0) const
117
token_id = static_cast<id_type>(c);
118
def.def.add_token (def.state.c_str(), lex::detail::escape(c),
123
operator()(string_type const& s, id_type token_id = id_type()) const
126
token_id = next_id<id_type>::get();
127
def.def.add_token (def.state.c_str(), s, token_id);
130
template <typename Attribute>
132
operator()(token_def<Attribute, char_type, id_type>& tokdef,
133
id_type token_id = id_type()) const
135
// make sure we have a token id
137
if (0 == tokdef.id()) {
138
token_id = next_id<id_type>::get();
142
token_id = tokdef.id();
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());
155
template <typename TokenSet>
157
operator()(token_set<TokenSet>& tokset) const
167
// allow to use lexer.self.add_pattern("pattern1", "regex1")(...);
171
pattern_adder(lexer_def_& def_)
176
operator()(string_type const& p, string_type const& s) const
178
def.def.add_pattern (def.state.c_str(), p, s);
184
friend struct pattern_adder;
187
///////////////////////////////////////////////////////////////////
188
template <typename Expr>
189
void define(Expr const& xpr)
192
result_of::as_component<lex::domain, Expr>::type
194
typedef typename component::director director;
196
component c = spirit::as_component(lex::domain(), xpr);
197
director::collect(c, def, state);
200
lexer_def_(LexerDef& def_, string_type const& state_)
201
: base_type(make_tag()), add(this_()), add_pattern(this_()),
202
def(def_), state(state_)
206
// allow to switch states
207
lexer_def_ operator()(char_type const* state) const
209
return lexer_def_(def, state);
211
lexer_def_ operator()(string_type const& state) const
213
return lexer_def_(def, state);
216
// allow to assign a token definition expression
217
template <typename Expr>
218
lexer_def_& operator= (Expr const& xpr)
221
spirit::traits::is_component<lex::domain, Expr>
224
// report invalid expression error as early as possible
225
BOOST_MPL_ASSERT_MSG(
227
xpr_is_not_convertible_to_a_token_definition, ());
229
def.clear(state.c_str());
235
pattern_adder add_pattern;
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)
248
spirit::traits::is_component<lex::domain, Expr>
251
// report invalid expression error as early as possible
252
BOOST_MPL_ASSERT_MSG(
254
xpr_is_not_convertible_to_a_token_definition, ());
260
template <typename LexerDef, typename Expr>
261
inline lexer_def_<LexerDef>&
262
operator+= (lexer_def_<LexerDef>& lexdef, Expr const& xpr)
265
spirit::traits::is_component<lex::domain, Expr>
268
// report invalid expression error as early as possible
269
BOOST_MPL_ASSERT_MSG(
271
xpr_is_not_convertible_to_a_token_definition, ());
278
///////////////////////////////////////////////////////////////////////////
279
// This represents a lexer definition (helper for token and token set
281
///////////////////////////////////////////////////////////////////////////
282
template <typename Lexer>
283
class lexer_def : private noncopyable, public Lexer
286
typedef lexer_def self_type;
288
// avoid warnings about using 'this' in constructor
289
lexer_def& this_() { return *this; }
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;
299
: self(this_(), Lexer::initial_state())
303
token_set self; // allow for easy token definition
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*/) {}
310
///////////////////////////////////////////////////////////////////////////
311
// This represents a lexer object
312
///////////////////////////////////////////////////////////////////////////
313
template <typename Definition>
314
class lexer : public safe_bool<lexer<Definition> >
317
// operator_bool() is needed for the safe_bool base class
318
bool operator_bool() const { return token_def; }
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;
325
lexer(Definition& token_def_)
326
: token_def(token_def_)
328
// call initialization routine supplied by the target lexer
329
token_def.def(token_def.self);
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(); }
338
std::size_t map_state(char_type const* state)
339
{ return token_def.add_state(state); }
341
Definition& get_definition() { return token_def; }
342
Definition const& get_definition() const { return token_def; }
345
Definition& token_def;
348
///////////////////////////////////////////////////////////////////////////
349
// Metafunction returning the iterator type of the lexer given the token
351
///////////////////////////////////////////////////////////////////////////
352
template <typename Definition>
353
struct lexer_iterator
355
typedef typename lexer<Definition>::iterator_type type;
358
///////////////////////////////////////////////////////////////////////////
359
// Generator function helping to construct a proper lexer object
361
///////////////////////////////////////////////////////////////////////////
362
template <typename Definition>
363
inline lexer<Definition>
364
make_lexer(Definition& def)
366
return lexer<Definition>(def);
1
// Copyright (c) 2001-2009 Hartmut Kaiser
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)
6
#if !defined(BOOST_SPIRIT_LEX_LEXER_MAR_13_2007_0145PM)
7
#define BOOST_SPIRIT_LEX_LEXER_MAR_13_2007_0145PM
9
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
10
#pragma once // MS compatible compilers support #pragma once
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>
23
#include <boost/range/iterator_range.hpp>
25
namespace boost { namespace spirit { namespace lex
29
///////////////////////////////////////////////////////////////////////
30
template <typename LexerDef>
32
: public proto::extends<
33
typename make_terminal_holder<
34
lexer_def_<LexerDef> const*, lexer_def_<LexerDef>
40
// avoid warnings about using 'this' in constructor
41
lexer_def_& this_() { return *this; }
43
// initialize proto base class
45
terminal_holder<lexer_def_ const*, lexer_def_>
47
typedef typename proto::terminal<terminal_holder_>::type tag;
48
typedef proto::extends<tag, lexer_def_> base_type;
50
typedef typename LexerDef::id_type id_type;
58
typedef typename LexerDef::char_type char_type;
59
typedef typename LexerDef::string_type string_type;
62
// Qi interface: metafunction calculating parser return type
63
template <typename Component, typename Context, typename Iterator>
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;
70
fusion::vector<id_type, iterator_range<iterator_type> >
75
// Qi interface: parse functionality
76
template <typename Iterator, typename Context, typename Skipper,
78
bool parse(Iterator& first, Iterator const& last,
79
Context& context, Skipper const& skipper, Attribute& attr) const
81
qi::skip(first, last, skipper); // always do a pre-skip
85
boost::detail::iterator_traits<Iterator>::value_type
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);
98
friend struct terminal_director;
100
static std::string what()
105
// allow to use the lexer.self.add("regex1", id1)("regex2", id2);
109
adder(lexer_def_& def_)
114
operator()(char_type c, id_type token_id = 0) const
117
token_id = static_cast<id_type>(c);
118
def.def.add_token (def.state.c_str(), lex::detail::escape(c),
123
operator()(string_type const& s, id_type token_id = id_type()) const
126
token_id = next_id<id_type>::get();
127
def.def.add_token (def.state.c_str(), s, token_id);
130
template <typename Attribute>
132
operator()(token_def<Attribute, char_type, id_type>& tokdef,
133
id_type token_id = id_type()) const
135
// make sure we have a token id
137
if (0 == tokdef.id()) {
138
token_id = next_id<id_type>::get();
142
token_id = tokdef.id();
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());
155
template <typename TokenSet>
157
operator()(token_set<TokenSet>& tokset) const
167
// allow to use lexer.self.add_pattern("pattern1", "regex1")(...);
171
pattern_adder(lexer_def_& def_)
176
operator()(string_type const& p, string_type const& s) const
178
def.def.add_pattern (def.state.c_str(), p, s);
184
friend struct pattern_adder;
187
///////////////////////////////////////////////////////////////////
188
template <typename Expr>
189
void define(Expr const& xpr)
192
result_of::as_component<lex::domain, Expr>::type
194
typedef typename component::director director;
196
component c = spirit::as_component(lex::domain(), xpr);
197
director::collect(c, def, state);
200
lexer_def_(LexerDef& def_, string_type const& state_)
201
: base_type(make_tag()), add(this_()), add_pattern(this_()),
202
def(def_), state(state_)
206
// allow to switch states
207
lexer_def_ operator()(char_type const* state) const
209
return lexer_def_(def, state);
211
lexer_def_ operator()(string_type const& state) const
213
return lexer_def_(def, state);
216
// allow to assign a token definition expression
217
template <typename Expr>
218
lexer_def_& operator= (Expr const& xpr)
221
spirit::traits::is_component<lex::domain, Expr>
224
// report invalid expression error as early as possible
225
BOOST_MPL_ASSERT_MSG(
227
xpr_is_not_convertible_to_a_token_definition, ());
229
def.clear(state.c_str());
235
pattern_adder add_pattern;
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)
248
spirit::traits::is_component<lex::domain, Expr>
251
// report invalid expression error as early as possible
252
BOOST_MPL_ASSERT_MSG(
254
xpr_is_not_convertible_to_a_token_definition, ());
260
template <typename LexerDef, typename Expr>
261
inline lexer_def_<LexerDef>&
262
operator+= (lexer_def_<LexerDef>& lexdef, Expr const& xpr)
265
spirit::traits::is_component<lex::domain, Expr>
268
// report invalid expression error as early as possible
269
BOOST_MPL_ASSERT_MSG(
271
xpr_is_not_convertible_to_a_token_definition, ());
278
///////////////////////////////////////////////////////////////////////////
279
// This represents a lexer definition (helper for token and token set
281
///////////////////////////////////////////////////////////////////////////
282
template <typename Lexer>
283
class lexer_def : private noncopyable, public Lexer
286
typedef lexer_def self_type;
288
// avoid warnings about using 'this' in constructor
289
lexer_def& this_() { return *this; }
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;
299
: self(this_(), Lexer::initial_state())
303
token_set self; // allow for easy token definition
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*/) {}
310
///////////////////////////////////////////////////////////////////////////
311
// This represents a lexer object
312
///////////////////////////////////////////////////////////////////////////
313
template <typename Definition>
314
class lexer : public safe_bool<lexer<Definition> >
317
// operator_bool() is needed for the safe_bool base class
318
bool operator_bool() const { return token_def; }
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;
325
lexer(Definition& token_def_)
326
: token_def(token_def_)
328
// call initialization routine supplied by the target lexer
329
token_def.def(token_def.self);
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(); }
338
std::size_t map_state(char_type const* state)
339
{ return token_def.add_state(state); }
341
Definition& get_definition() { return token_def; }
342
Definition const& get_definition() const { return token_def; }
345
Definition& token_def;
348
///////////////////////////////////////////////////////////////////////////
349
// Metafunction returning the iterator type of the lexer given the token
351
///////////////////////////////////////////////////////////////////////////
352
template <typename Definition>
353
struct lexer_iterator
355
typedef typename lexer<Definition>::iterator_type type;
358
///////////////////////////////////////////////////////////////////////////
359
// Generator function helping to construct a proper lexer object
361
///////////////////////////////////////////////////////////////////////////
362
template <typename Definition>
363
inline lexer<Definition>
364
make_lexer(Definition& def)
366
return lexer<Definition>(def);