/*============================================================================= 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 #include #include #if defined(_MSC_VER) /*&& !defined(__COMO__)*/ #pragma warning(disable: 4244) #pragma warning(disable: 4355) #endif // defined(_MSC_VER) && !defined(__COMO__) #include #include #include #include #include #include /////////////////////////////////////////////////////////////////////////////// // 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 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 { member1 val; }; /////////////////////////////////////////////////////////////////////////////// // // symbols_with_data // // Helper class for inserting an item with data into a symbol table // /////////////////////////////////////////////////////////////////////////////// template class symbols_with_data { public: typedef symbol_inserter > symbol_inserter_t; symbols_with_data(symbol_inserter_t const &add_, InitT const &data_) : add(add_), data(as_actor::convert(data_)) { } template 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::type data; }; template inline symbols_with_data symbols_gen(symbol_inserter > const &add_, InitT const &data_) { return symbols_with_data(add_, data_); } /////////////////////////////////////////////////////////////////////////////// // The var_decl_list grammar parses variable declaration list struct var_decl_list : public grammar { template 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_(arg1, arg2)] | str_p("real")[type.val = construct_(arg1, arg2)] ; BOOST_SPIRIT_DEBUG_RULE(decl); BOOST_SPIRIT_DEBUG_RULE(list); BOOST_SPIRIT_DEBUG_RULE(ident); BOOST_SPIRIT_DEBUG_RULE(type); } rule const& start() const { return decl; } private: typedef rule rule_t; rule_t type; rule_t list; rule_t ident; symbols symtab; rule 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; }