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