keywords.cpp 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. /*=============================================================================
  2. Copyright (c) 2001-2011 Joel de Guzman
  3. http://spirit.sourceforge.net/
  4. Distributed under the Boost Software License, Version 1.0. (See accompanying
  5. file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. =============================================================================*/
  7. //[reference_includes
  8. #include <boost/spirit/include/qi.hpp>
  9. #include <boost/spirit/include/phoenix_core.hpp>
  10. #include <boost/spirit/include/phoenix_operator.hpp>
  11. #include <boost/fusion/include/adapt_struct.hpp>
  12. #include <boost/spirit/repository/include/qi_kwd.hpp>
  13. #include <boost/spirit/repository/include/qi_keywords.hpp>
  14. #include <iostream>
  15. #include <string>
  16. #include <cstdlib>
  17. #include <iterator>
  18. //]
  19. //[reference_test
  20. template <typename P>
  21. void test_parser(
  22. char const* input, P const& p, bool full_match = true)
  23. {
  24. using boost::spirit::qi::parse;
  25. char const* f(input);
  26. char const* l(f + strlen(f));
  27. if (parse(f, l, p) && (!full_match || (f == l)))
  28. std::cout << "ok" << std::endl;
  29. else
  30. std::cout << "fail" << std::endl;
  31. }
  32. template <typename P>
  33. void test_phrase_parser(
  34. char const* input, P const& p, bool full_match = true)
  35. {
  36. using boost::spirit::qi::phrase_parse;
  37. using boost::spirit::qi::ascii::space;
  38. char const* f(input);
  39. char const* l(f + strlen(f));
  40. if (phrase_parse(f, l, p, space) && (!full_match || (f == l)))
  41. std::cout << "ok" << std::endl;
  42. else
  43. std::cout << "fail" << std::endl;
  44. }
  45. //]
  46. //[reference_test_attr
  47. template <typename P, typename T>
  48. void test_parser_attr(
  49. char const* input, P const& p, T& attr, bool full_match = true)
  50. {
  51. using boost::spirit::qi::parse;
  52. char const* f(input);
  53. char const* l(f + strlen(f));
  54. if (parse(f, l, p, attr) && (!full_match || (f == l)))
  55. std::cout << "ok" << std::endl;
  56. else
  57. std::cout << "fail" << std::endl;
  58. }
  59. template <typename P, typename T>
  60. void test_phrase_parser_attr(
  61. char const* input, P const& p, T& attr, bool full_match = true)
  62. {
  63. using boost::spirit::qi::phrase_parse;
  64. using boost::spirit::qi::ascii::space;
  65. char const* f(input);
  66. char const* l(f + strlen(f));
  67. if (phrase_parse(f, l, p, space, attr) && (!full_match || (f == l)))
  68. std::cout << "ok" << std::endl;
  69. else
  70. std::cout << "fail" << std::endl;
  71. }
  72. //]
  73. //[reference_keyword_list_test_data_structure
  74. // Data structure definitions to test the kwd directive
  75. // and the keywords list operator
  76. struct person {
  77. std::string name;
  78. int age;
  79. double size;
  80. std::vector<std::string> favorite_colors;
  81. };
  82. std::ostream &operator<<(std::ostream &os, const person &p)
  83. {
  84. os<<"Person : "<<p.name<<", "<<p.age<<", "<<p.size<<std::endl;
  85. std::copy(p.favorite_colors.begin(),p.favorite_colors.end(),std::ostream_iterator<std::string>(os,"\n"));
  86. return os;
  87. }
  88. BOOST_FUSION_ADAPT_STRUCT( person,
  89. (std::string, name)
  90. (int, age)
  91. (double, size)
  92. (std::vector<std::string>, favorite_colors)
  93. )
  94. //]
  95. int
  96. main()
  97. {
  98. // keyword_list
  99. {
  100. //[reference_using_declarations_keyword_list
  101. using boost::spirit::repository::qi::kwd;
  102. using boost::spirit::qi::inf;
  103. using boost::spirit::ascii::space_type;
  104. using boost::spirit::ascii::char_;
  105. using boost::spirit::qi::double_;
  106. using boost::spirit::qi::int_;
  107. using boost::spirit::qi::rule;
  108. //]
  109. //[reference_keyword_list_rule_declarations
  110. rule<const char *, std::string(), space_type> parse_string;
  111. rule<const char *, person(), space_type> no_constraint_person_rule, constraint_person_rule;
  112. parse_string %= '"'> *(char_-'"') > '"';
  113. //]
  114. //[reference_keyword_list_no_constraint_rule
  115. no_constraint_person_rule %=
  116. kwd("name")['=' > parse_string ]
  117. / kwd("age") ['=' > int_]
  118. / kwd("size") ['=' > double_ > 'm']
  119. ;
  120. //]
  121. //[reference_keyword_list
  122. //`Parsing a keyword list:
  123. // Let's declare a small list of people for which we want to collect information.
  124. person John,Mary,Mike,Hellen,Johny;
  125. test_phrase_parser_attr(
  126. "name = \"John\" \n age = 10 \n size = 1.69m "
  127. ,no_constraint_person_rule
  128. ,John); // full in orginal order
  129. std::cout<<John;
  130. test_phrase_parser_attr(
  131. "age = 10 \n size = 1.69m \n name = \"Mary\""
  132. ,no_constraint_person_rule
  133. ,Mary); // keyword oder doesn't matter
  134. std::cout<<Mary;
  135. test_phrase_parser_attr(
  136. "size = 1.69m \n name = \"Mike\" \n age = 10 "
  137. ,no_constraint_person_rule
  138. ,Mike); // still the same result
  139. std::cout<<Mike;
  140. /*`The code above will print:[teletype]
  141. Person : John, 10, 1.69
  142. Person : Mary, 10, 1.69
  143. Person : Mike, 10, 1.69
  144. */
  145. //]
  146. //[reference_keyword_list_constraint_rule
  147. /*`The parser definition below uses the kwd directive occurrence constraint variants to
  148. make sure that the name and age keyword occur only once and allows the favorite color
  149. entry to appear 0 or more times. */
  150. constraint_person_rule %=
  151. kwd("name",1) ['=' > parse_string ]
  152. / kwd("age" ,1) ['=' > int_]
  153. / kwd("size" ,1) ['=' > double_ > 'm']
  154. / kwd("favorite color",0,inf) [ '=' > parse_string ]
  155. ;
  156. //]
  157. //[reference_keyword_list_constraints
  158. // Here all the give constraint are resepected : parsing will succeed.
  159. test_phrase_parser_attr(
  160. "name = \"Hellen\" \n age = 10 \n size = 1.80m \n favorite color = \"blue\" \n favorite color = \"green\" "
  161. ,constraint_person_rule
  162. ,Hellen);
  163. std::cout<<Hellen;
  164. // Parsing this string will fail because the age and size minimum occurrence requirements aren't met.
  165. test_phrase_parser_attr(
  166. "name = \"Johny\" \n favorite color = \"blue\" \n favorite color = \"green\" "
  167. ,constraint_person_rule
  168. ,Johny );
  169. /*`Parsing the first string will succeed but fail for the second string as the
  170. occurrence constraints aren't met. This code should print:[teletype]
  171. Person : Hellen, 10, 1.8
  172. blue
  173. green
  174. */
  175. //]
  176. }
  177. return 0;
  178. }