]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/spirit/example/lex/custom_token_attribute.cpp
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / boost / libs / spirit / example / lex / custom_token_attribute.cpp
1 // Copyright (c) 2001-2010 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 // 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
10 // rules.
11
12 #include <boost/spirit/include/lex_lexertl.hpp>
13 #include <boost/spirit/include/qi.hpp>
14
15 namespace lex = boost::spirit::lex;
16 namespace qi = boost::spirit::qi;
17 namespace mpl = boost::mpl;
18
19 ///////////////////////////////////////////////////////////////////////////////
20 // This is just a simple custom rational data structure holding two ints to be
21 // interpreted as a rational number
22 struct rational
23 {
24 rational(int n = 0, int d = 0)
25 : nominator_(n), denominator_(d)
26 {}
27
28 int nominator_;
29 int denominator_;
30 };
31
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.
37 //
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<>.
41 //
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
46 {
47 template <typename Iterator>
48 struct assign_to_attribute_from_iterators<rational, Iterator>
49 {
50 static void
51 call(Iterator const& first, Iterator const& last, rational& attr)
52 {
53 int x, y;
54 Iterator b = first;
55 qi::parse(b, last,
56 '{' >> qi::int_ >> ',' >> qi::int_ >> '}', x, y);
57 attr = rational(x, y);
58 }
59 };
60 }}}
61
62 ///////////////////////////////////////////////////////////////////////////////
63 // a lexer recognizing a single token type: rational
64 template <typename Lexer>
65 struct lex_rational : lex::lexer<Lexer>
66 {
67 lex_rational()
68 {
69 this->self.add_pattern("INT", "[1-9][0-9]*");
70
71 rt = "\\{{INT},{INT}\\}";
72 this->self.add(rt);
73 }
74 lex::token_def<rational> rt;
75 };
76
77
78 int main()
79 {
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;
84
85 // use actor_lexer<> here if your token definitions have semantic
86 // actions
87 typedef lex::lexertl::lexer<token_type> lexer_type;
88
89 // this is the iterator exposed by the lexer, we use this for parsing
90 typedef lexer_type::iterator_type iterator_type;
91
92 // create a lexer instance
93 std::string input("{3,4}");
94 std::string::iterator s = input.begin();
95
96 lex_rational<lexer_type> lex;
97 iterator_type b = lex.begin(s, input.end());
98
99 // use the embedded token_def as a parser, it exposes its token value type
100 // as its parser attribute type
101 rational r;
102 if (!qi::parse(b, lex.end(), lex.rt, r))
103 {
104 std::cerr << "Parsing failed!" << std::endl;
105 return -1;
106 }
107
108 std::cout << "Parsing succeeded: {"
109 << r.nominator_ << ", " << r.denominator_ << "}" << std::endl;
110 return 0;
111 }
112