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/include/classic_core.hpp>
27 #include <boost/spirit/include/classic_symbols.hpp>
28 #include <boost/spirit/include/classic_closure.hpp>
29
30 #include <boost/spirit/include/phoenix1_tuples.hpp>
31 #include <boost/spirit/include/phoenix1_tuple_helpers.hpp>
32 #include <boost/spirit/include/phoenix1_primitives.hpp>
33
34 ///////////////////////////////////////////////////////////////////////////////
35 // used namespaces
36 using namespace BOOST_SPIRIT_CLASSIC_NS;
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
declaration_type()51 declaration_type() : type(vartype_unknown)
52 {
53 }
54 template <typename ItT>
declaration_type(ItT const & first,ItT const & last)55 declaration_type(ItT const &first, ItT const &last)
56 {
57 init(string(first, last-first-1));
58 }
declaration_type(declaration_type const & type_)59 declaration_type(declaration_type const &type_) : type(type_.type)
60 {
61 }
declaration_type(string const & type_)62 declaration_type(string const &type_) : type(vartype_unknown)
63 {
64 init(type_);
65 }
66
67 // access to the variable type
operator vartype const&() const68 operator vartype const &() const { return type; }
operator string()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
swap(declaration_type & s)80 void swap(declaration_type &s) { std::swap(type, s.type); }
81
82 protected:
init(string const & type_)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_CLASSIC_NS::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_CLASSIC_NS::impl::tst<T, char> >
120 symbol_inserter_t;
121
symbols_with_data(symbol_inserter_t const & add_,InitT const & data_)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 &
operator ()(IteratorT const & first_,IteratorT const & last) const129 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>
symbols_gen(symbol_inserter<T,BOOST_SPIRIT_CLASSIC_NS::impl::tst<T,CharT>> const & add_,InitT const & data_)143 symbols_gen(symbol_inserter<T, BOOST_SPIRIT_CLASSIC_NS::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 {
definitionvar_decl_list::definition158 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&
startvar_decl_list::definition182 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
main()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
217