| /*============================================================================= |
| 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; |
| } |
| |