• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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