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