parameters.cpp 6.5 KB

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