]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 <boost/assert.hpp> | |
34 | #include <boost/cstdlib.hpp> | |
35 | #include <boost/spirit/include/phoenix1.hpp> | |
36 | #include <boost/spirit/include/classic_core.hpp> | |
37 | #include <boost/spirit/include/classic_symbols.hpp> | |
38 | #include <boost/spirit/include/classic_attribute.hpp> | |
39 | #include <boost/spirit/include/classic_dynamic.hpp> | |
40 | ||
41 | using namespace boost; | |
42 | using namespace BOOST_SPIRIT_CLASSIC_NS; | |
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 boost::spirit::classic::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 | BOOST_ASSERT(info.full); | |
121 | BOOST_ASSERT(result == 9); | |
122 | ||
123 | return exit_success; | |
124 | } | |
125 | ||
126 | //----------------------------------------------------------------------------- |