1 // Copyright (c) 2001-2010 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 // The purpose of this example is to demonstrate how custom, user defined types
7 // can be easily integrated with the lexer as token value types. Moreover, the
8 // custom token values are properly exposed to the parser as well, allowing to
9 // retrieve the custom values using the built in parser attribute propagation
12 #include <boost/spirit/include/lex_lexertl.hpp>
13 #include <boost/spirit/include/qi.hpp>
15 namespace lex
= boost::spirit::lex
;
16 namespace qi
= boost::spirit::qi
;
17 namespace mpl
= boost::mpl
;
19 ///////////////////////////////////////////////////////////////////////////////
20 // This is just a simple custom rational data structure holding two ints to be
21 // interpreted as a rational number
24 rational(int n
= 0, int d
= 0)
25 : nominator_(n
), denominator_(d
)
32 ///////////////////////////////////////////////////////////////////////////////
33 // A rational is represented as "{n,d}", where 'n' and 'd' are the nominator
34 // and denominator of the number. We use Spirit.Qi to do the low level parsing
35 // of the input sequence as matched by the lexer. Certainly, any other
36 // conversion could be used instead.
38 // The lexer uses the template assign_to_attribute_from_iterators<> to convert
39 // the matched input sequence (pair of iterators) to the token value type as
40 // specified while defining the lex::token_def<>.
42 // Our specialization of assign_to_attribute_from_iterators<> for the rational
43 // data type defined above has to be placed into the
44 // namespace boost::spirit::traits, otherwise it won't be found by the library.
45 namespace boost
{ namespace spirit
{ namespace traits
47 template <typename Iterator
>
48 struct assign_to_attribute_from_iterators
<rational
, Iterator
>
51 call(Iterator
const& first
, Iterator
const& last
, rational
& attr
)
56 '{' >> qi::int_
>> ',' >> qi::int_
>> '}', x
, y
);
57 attr
= rational(x
, y
);
62 ///////////////////////////////////////////////////////////////////////////////
63 // a lexer recognizing a single token type: rational
64 template <typename Lexer
>
65 struct lex_rational
: lex::lexer
<Lexer
>
69 this->self
.add_pattern("INT", "[1-9][0-9]*");
71 rt
= "\\{{INT},{INT}\\}";
74 lex::token_def
<rational
> rt
;
80 // the token type needs to know the iterator type of the underlying
81 // input and the set of used token value types
82 typedef lex::lexertl::token
<std::string::iterator
,
83 mpl::vector
<rational
> > token_type
;
85 // use actor_lexer<> here if your token definitions have semantic
87 typedef lex::lexertl::lexer
<token_type
> lexer_type
;
89 // this is the iterator exposed by the lexer, we use this for parsing
90 typedef lexer_type::iterator_type iterator_type
;
92 // create a lexer instance
93 std::string
input("{3,4}");
94 std::string::iterator s
= input
.begin();
96 lex_rational
<lexer_type
> lex
;
97 iterator_type b
= lex
.begin(s
, input
.end());
99 // use the embedded token_def as a parser, it exposes its token value type
100 // as its parser attribute type
102 if (!qi::parse(b
, lex
.end(), lex
.rt
, r
))
104 std::cerr
<< "Parsing failed!" << std::endl
;
108 std::cout
<< "Parsing succeeded: {"
109 << r
.nominator_
<< ", " << r
.denominator_
<< "}" << std::endl
;