1 | /*============================================================================= |
---|
2 | Copyright (c) 2003 Vaclav Vesely |
---|
3 | http://spirit.sourceforge.net/ |
---|
4 | |
---|
5 | Use, modification and distribution is subject to the Boost Software |
---|
6 | License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at |
---|
7 | http://www.boost.org/LICENSE_1_0.txt) |
---|
8 | =============================================================================*/ |
---|
9 | // |
---|
10 | // This example demonstrates the lazy_p parser. You should read |
---|
11 | // "The Lazy Parser" in the documentation. |
---|
12 | // |
---|
13 | // We want to parse nested blocks of numbers like this: |
---|
14 | // |
---|
15 | // dec { |
---|
16 | // 1 2 3 |
---|
17 | // bin { |
---|
18 | // 1 10 11 |
---|
19 | // } |
---|
20 | // 4 5 6 |
---|
21 | // } |
---|
22 | // |
---|
23 | // where the numbers in the "dec" block are wrote in the decimal system and |
---|
24 | // the numbers in the "bin" block are wrote in the binary system. We want |
---|
25 | // parser to return the overall sum. |
---|
26 | // |
---|
27 | // To achive this when base ("bin" or "dec") is parsed, in semantic action |
---|
28 | // we store a pointer to the appropriate numeric parser in the closure |
---|
29 | // variable block.int_rule. Than, when we need to parse a number we use lazy_p |
---|
30 | // parser to invoke the parser stored in the block.int_rule pointer. |
---|
31 | // |
---|
32 | //----------------------------------------------------------------------------- |
---|
33 | #include <cassert> |
---|
34 | #include <boost/cstdlib.hpp> |
---|
35 | #include <boost/spirit/phoenix.hpp> |
---|
36 | #include <boost/spirit/core.hpp> |
---|
37 | #include <boost/spirit/symbols.hpp> |
---|
38 | #include <boost/spirit/attribute.hpp> |
---|
39 | #include <boost/spirit/dynamic.hpp> |
---|
40 | |
---|
41 | using namespace boost; |
---|
42 | using namespace spirit; |
---|
43 | using namespace phoenix; |
---|
44 | |
---|
45 | //----------------------------------------------------------------------------- |
---|
46 | // my grammar |
---|
47 | |
---|
48 | struct my_grammar |
---|
49 | : public grammar<my_grammar, parser_context<int> > |
---|
50 | { |
---|
51 | // grammar definition |
---|
52 | template<typename ScannerT> |
---|
53 | struct definition |
---|
54 | { |
---|
55 | typedef rule<ScannerT> rule_t; |
---|
56 | typedef stored_rule<ScannerT, parser_context<int> > number_rule_t; |
---|
57 | |
---|
58 | struct block_closure; |
---|
59 | typedef spirit::closure< |
---|
60 | block_closure, |
---|
61 | int, |
---|
62 | typename number_rule_t::alias_t> |
---|
63 | closure_base_t; |
---|
64 | |
---|
65 | struct block_closure : closure_base_t |
---|
66 | { |
---|
67 | typename closure_base_t::member1 sum; |
---|
68 | typename closure_base_t::member2 int_rule; |
---|
69 | }; |
---|
70 | |
---|
71 | // block rule type |
---|
72 | typedef rule<ScannerT, typename block_closure::context_t> block_rule_t; |
---|
73 | |
---|
74 | block_rule_t block; |
---|
75 | rule_t block_item; |
---|
76 | symbols<number_rule_t> base; |
---|
77 | |
---|
78 | definition(my_grammar const& self) |
---|
79 | { |
---|
80 | block = |
---|
81 | base[ |
---|
82 | block.sum = 0, |
---|
83 | // store a number rule in a closure member |
---|
84 | block.int_rule = arg1 |
---|
85 | ] |
---|
86 | >> "{" |
---|
87 | >> *block_item |
---|
88 | >> "}" |
---|
89 | ; |
---|
90 | |
---|
91 | block_item = |
---|
92 | // use the stored rule |
---|
93 | lazy_p(block.int_rule)[block.sum += arg1] |
---|
94 | | block[block.sum += arg1] |
---|
95 | ; |
---|
96 | |
---|
97 | // bind base keywords and number parsers |
---|
98 | base.add |
---|
99 | ("bin", bin_p) |
---|
100 | ("dec", uint_p) |
---|
101 | ; |
---|
102 | } |
---|
103 | |
---|
104 | block_rule_t const& start() const |
---|
105 | { |
---|
106 | return block; |
---|
107 | } |
---|
108 | }; |
---|
109 | }; |
---|
110 | |
---|
111 | //----------------------------------------------------------------------------- |
---|
112 | |
---|
113 | int main() |
---|
114 | { |
---|
115 | my_grammar gram; |
---|
116 | parse_info<> info; |
---|
117 | |
---|
118 | int result; |
---|
119 | info = parse("bin{1 dec{1 2 3} 10}", gram[var(result) = arg1], space_p); |
---|
120 | assert(info.full); |
---|
121 | assert(result == 9); |
---|
122 | |
---|
123 | return exit_success; |
---|
124 | } |
---|
125 | |
---|
126 | //----------------------------------------------------------------------------- |
---|