1 | /*============================================================================= |
---|
2 | Copyright (c) 2001-2003 Hartmut Kaiser |
---|
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 sample show the usage of parser parameters. |
---|
11 | // |
---|
12 | // Parser parameters are used to pass some values from the outer parsing scope |
---|
13 | // to the next inner scope. They can be imagined as the opposite to the return |
---|
14 | // value paradigm, which returns some value from the inner to the next outer |
---|
15 | // scope. See the "Closures" chapter in the User's Guide. |
---|
16 | |
---|
17 | #include <string> |
---|
18 | #include <iostream> |
---|
19 | #include <cassert> |
---|
20 | |
---|
21 | #if defined(_MSC_VER) /*&& !defined(__COMO__)*/ |
---|
22 | #pragma warning(disable: 4244) |
---|
23 | #pragma warning(disable: 4355) |
---|
24 | #endif // defined(_MSC_VER) && !defined(__COMO__) |
---|
25 | |
---|
26 | #include <boost/spirit/core.hpp> |
---|
27 | #include <boost/spirit/symbols/symbols.hpp> |
---|
28 | |
---|
29 | #include <boost/spirit/phoenix/tuples.hpp> |
---|
30 | #include <boost/spirit/phoenix/tuple_helpers.hpp> |
---|
31 | #include <boost/spirit/phoenix/primitives.hpp> |
---|
32 | #include <boost/spirit/attribute/closure.hpp> |
---|
33 | |
---|
34 | /////////////////////////////////////////////////////////////////////////////// |
---|
35 | // used namespaces |
---|
36 | using namespace boost::spirit; |
---|
37 | using namespace phoenix; |
---|
38 | using namespace std; |
---|
39 | |
---|
40 | /////////////////////////////////////////////////////////////////////////////// |
---|
41 | // Helper class for encapsulation of the type for the parsed variable names |
---|
42 | class declaration_type |
---|
43 | { |
---|
44 | public: |
---|
45 | enum vartype { |
---|
46 | vartype_unknown = 0, // unknown variable type |
---|
47 | vartype_int = 1, // 'int' |
---|
48 | vartype_real = 2 // 'real' |
---|
49 | }; |
---|
50 | |
---|
51 | declaration_type() : type(vartype_unknown) |
---|
52 | { |
---|
53 | } |
---|
54 | template <typename ItT> |
---|
55 | declaration_type(ItT const &first, ItT const &last) |
---|
56 | { |
---|
57 | init(string(first, last-first-1)); |
---|
58 | } |
---|
59 | declaration_type(declaration_type const &type_) : type(type_.type) |
---|
60 | { |
---|
61 | } |
---|
62 | declaration_type(string const &type_) : type(vartype_unknown) |
---|
63 | { |
---|
64 | init(type_); |
---|
65 | } |
---|
66 | |
---|
67 | // access to the variable type |
---|
68 | operator vartype const &() const { return type; } |
---|
69 | operator string () |
---|
70 | { |
---|
71 | switch(type) { |
---|
72 | default: |
---|
73 | case vartype_unknown: break; |
---|
74 | case vartype_int: return string("int"); |
---|
75 | case vartype_real: return string("real"); |
---|
76 | } |
---|
77 | return string ("unknown"); |
---|
78 | } |
---|
79 | |
---|
80 | void swap(declaration_type &s) { std::swap(type, s.type); } |
---|
81 | |
---|
82 | protected: |
---|
83 | void init (string const &type_) |
---|
84 | { |
---|
85 | if (type_ == "int") |
---|
86 | type = vartype_int; |
---|
87 | else if (type_ == "real") |
---|
88 | type = vartype_real; |
---|
89 | else |
---|
90 | type = vartype_unknown; |
---|
91 | } |
---|
92 | |
---|
93 | private: |
---|
94 | vartype type; |
---|
95 | }; |
---|
96 | |
---|
97 | /////////////////////////////////////////////////////////////////////////////// |
---|
98 | // |
---|
99 | // used closure type |
---|
100 | // |
---|
101 | /////////////////////////////////////////////////////////////////////////////// |
---|
102 | struct var_decl_closure : boost::spirit::closure<var_decl_closure, declaration_type> |
---|
103 | { |
---|
104 | member1 val; |
---|
105 | }; |
---|
106 | |
---|
107 | /////////////////////////////////////////////////////////////////////////////// |
---|
108 | // |
---|
109 | // symbols_with_data |
---|
110 | // |
---|
111 | // Helper class for inserting an item with data into a symbol table |
---|
112 | // |
---|
113 | /////////////////////////////////////////////////////////////////////////////// |
---|
114 | template <typename T, typename InitT> |
---|
115 | class symbols_with_data |
---|
116 | { |
---|
117 | public: |
---|
118 | typedef |
---|
119 | symbol_inserter<T, boost::spirit::impl::tst<T, char> > |
---|
120 | symbol_inserter_t; |
---|
121 | |
---|
122 | symbols_with_data(symbol_inserter_t const &add_, InitT const &data_) : |
---|
123 | add(add_), data(as_actor<InitT>::convert(data_)) |
---|
124 | { |
---|
125 | } |
---|
126 | |
---|
127 | template <typename IteratorT> |
---|
128 | symbol_inserter_t const & |
---|
129 | operator()(IteratorT const &first_, IteratorT const &last) const |
---|
130 | { |
---|
131 | IteratorT first = first_; |
---|
132 | return add(first, last, data()); |
---|
133 | } |
---|
134 | |
---|
135 | private: |
---|
136 | symbol_inserter_t const &add; |
---|
137 | typename as_actor<InitT>::type data; |
---|
138 | }; |
---|
139 | |
---|
140 | template <typename T, typename CharT, typename InitT> |
---|
141 | inline |
---|
142 | symbols_with_data<T, InitT> |
---|
143 | symbols_gen(symbol_inserter<T, boost::spirit::impl::tst<T, CharT> > const &add_, |
---|
144 | InitT const &data_) |
---|
145 | { |
---|
146 | return symbols_with_data<T, InitT>(add_, data_); |
---|
147 | } |
---|
148 | |
---|
149 | /////////////////////////////////////////////////////////////////////////////// |
---|
150 | // The var_decl_list grammar parses variable declaration list |
---|
151 | |
---|
152 | struct var_decl_list : |
---|
153 | public grammar<var_decl_list, var_decl_closure::context_t> |
---|
154 | { |
---|
155 | template <typename ScannerT> |
---|
156 | struct definition |
---|
157 | { |
---|
158 | definition(var_decl_list const &self) |
---|
159 | { |
---|
160 | // pass variable type returned from 'type' to list closure member 0 |
---|
161 | decl = type[self.val = arg1] >> +space_p >> list(self.val); |
---|
162 | |
---|
163 | // m0 to access arg 0 of list --> passing variable type down to ident |
---|
164 | list = ident(list.val) >> *(',' >> ident(list.val)); |
---|
165 | |
---|
166 | // store identifier and type into the symbol table |
---|
167 | ident = (*alnum_p)[symbols_gen(symtab.add, ident.val)]; |
---|
168 | |
---|
169 | // the type of the decl is returned in type's closure member 0 |
---|
170 | type = |
---|
171 | str_p("int")[type.val = construct_<string>(arg1, arg2)] |
---|
172 | | str_p("real")[type.val = construct_<string>(arg1, arg2)] |
---|
173 | ; |
---|
174 | |
---|
175 | BOOST_SPIRIT_DEBUG_RULE(decl); |
---|
176 | BOOST_SPIRIT_DEBUG_RULE(list); |
---|
177 | BOOST_SPIRIT_DEBUG_RULE(ident); |
---|
178 | BOOST_SPIRIT_DEBUG_RULE(type); |
---|
179 | } |
---|
180 | |
---|
181 | rule<ScannerT> const& |
---|
182 | start() const { return decl; } |
---|
183 | |
---|
184 | private: |
---|
185 | typedef rule<ScannerT, var_decl_closure::context_t> rule_t; |
---|
186 | rule_t type; |
---|
187 | rule_t list; |
---|
188 | rule_t ident; |
---|
189 | symbols<declaration_type> symtab; |
---|
190 | |
---|
191 | rule<ScannerT> decl; // start rule |
---|
192 | }; |
---|
193 | }; |
---|
194 | |
---|
195 | /////////////////////////////////////////////////////////////////////////////// |
---|
196 | // main entry point |
---|
197 | int main() |
---|
198 | { |
---|
199 | var_decl_list decl; |
---|
200 | declaration_type type; |
---|
201 | char const *pbegin = "int var1"; |
---|
202 | |
---|
203 | if (parse (pbegin, decl[assign(type)]).full) { |
---|
204 | cout << endl |
---|
205 | << "Parsed variable declarations successfully!" << endl |
---|
206 | << "Detected type: " << declaration_type::vartype(type) |
---|
207 | << " (" << string(type) << ")" |
---|
208 | << endl; |
---|
209 | } else { |
---|
210 | cout << endl |
---|
211 | << "Parsing the input stream failed!" |
---|
212 | << endl; |
---|
213 | } |
---|
214 | return 0; |
---|
215 | } |
---|
216 | |
---|