• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 achieve 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 
definitionmy_grammar::definition78         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 
startmy_grammar::definition104         block_rule_t const& start() const
105         {
106             return block;
107         }
108     };
109 };
110 
111 //-----------------------------------------------------------------------------
112 
main()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 //-----------------------------------------------------------------------------
127