rule4.cpp 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. /*=============================================================================
  2. Copyright (c) 2001-2011 Joel de Guzman
  3. Distributed under the Boost Software License, Version 1.0. (See accompanying
  4. file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  5. =============================================================================*/
  6. #include <boost/detail/lightweight_test.hpp>
  7. #include <boost/spirit/include/qi_operator.hpp>
  8. #include <boost/spirit/include/qi_char.hpp>
  9. #include <boost/spirit/include/qi_string.hpp>
  10. #include <boost/spirit/include/qi_numeric.hpp>
  11. #include <boost/spirit/include/qi_auxiliary.hpp>
  12. #include <boost/spirit/include/qi_directive.hpp>
  13. #include <boost/spirit/include/qi_nonterminal.hpp>
  14. #include <boost/spirit/include/qi_action.hpp>
  15. #include <boost/spirit/include/phoenix_core.hpp>
  16. #include <boost/spirit/include/phoenix_operator.hpp>
  17. #include <boost/spirit/include/phoenix_object.hpp>
  18. #include <boost/spirit/include/phoenix_bind.hpp>
  19. #include <boost/fusion/include/std_pair.hpp>
  20. #include <string>
  21. #include <cstring>
  22. #include <iostream>
  23. #include "test.hpp"
  24. int
  25. main()
  26. {
  27. using spirit_test::test_attr;
  28. using spirit_test::test;
  29. using namespace boost::spirit::ascii;
  30. using namespace boost::spirit::qi::labels;
  31. using boost::spirit::qi::locals;
  32. using boost::spirit::qi::rule;
  33. using boost::spirit::qi::int_;
  34. using boost::spirit::qi::uint_;
  35. using boost::spirit::qi::fail;
  36. using boost::spirit::qi::on_error;
  37. using boost::spirit::qi::debug;
  38. using boost::spirit::qi::lit;
  39. namespace phx = boost::phoenix;
  40. { // show that ra = rb and ra %= rb works as expected
  41. rule<char const*, int() > ra, rb;
  42. int attr;
  43. ra %= int_;
  44. BOOST_TEST(test_attr("123", ra, attr));
  45. BOOST_TEST(attr == 123);
  46. rb %= ra;
  47. BOOST_TEST(test_attr("123", rb, attr));
  48. BOOST_TEST(attr == 123);
  49. rb = ra;
  50. BOOST_TEST(test_attr("123", rb, attr));
  51. BOOST_TEST(attr == 123);
  52. }
  53. { // std::string as container attribute with auto rules
  54. rule<char const*, std::string()> text;
  55. text %= +(!char_(')') >> !char_('>') >> char_);
  56. std::string attr;
  57. BOOST_TEST(test_attr("x", text, attr));
  58. BOOST_TEST(attr == "x");
  59. // test deduced auto rule behavior
  60. text = +(!char_(')') >> !char_('>') >> char_);
  61. attr.clear();
  62. BOOST_TEST(test_attr("x", text, attr));
  63. BOOST_TEST(attr == "x");
  64. }
  65. { // error handling
  66. using namespace boost::spirit::ascii;
  67. using boost::phoenix::construct;
  68. using boost::phoenix::bind;
  69. rule<char const*> r;
  70. r = '(' > int_ > ',' > int_ > ')';
  71. on_error<fail>
  72. (
  73. r, std::cout
  74. << phx::val("Error! Expecting: ")
  75. << _4
  76. << phx::val(", got: \"")
  77. << construct<std::string>(_3, _2)
  78. << phx::val("\"")
  79. << std::endl
  80. );
  81. BOOST_TEST(test("(123,456)", r));
  82. BOOST_TEST(!test("(abc,def)", r));
  83. BOOST_TEST(!test("(123,456]", r));
  84. BOOST_TEST(!test("(123;456)", r));
  85. BOOST_TEST(!test("[123,456]", r));
  86. }
  87. { // specifying the encoding
  88. typedef boost::spirit::char_encoding::iso8859_1 iso8859_1;
  89. rule<char const*, iso8859_1> r;
  90. r = no_case['\xE1'];
  91. BOOST_TEST(test("\xC1", r));
  92. r = no_case[char_('\xE1')];
  93. BOOST_TEST(test("\xC1", r));
  94. r = no_case[char_("\xE5-\xEF")];
  95. BOOST_TEST(test("\xC9", r));
  96. BOOST_TEST(!test("\xFF", r));
  97. r = no_case["\xE1\xC1"];
  98. BOOST_TEST(test("\xC1\xE1", r));
  99. r = no_case[lit("\xE1\xC1")];
  100. BOOST_TEST(test("\xC1\xE1", r));
  101. }
  102. {
  103. typedef boost::variant<double, int> v_type;
  104. rule<const char*, v_type()> r1 = int_;
  105. v_type v;
  106. BOOST_TEST(test_attr("1", r1, v) && v.which() == 1 &&
  107. boost::get<int>(v) == 1);
  108. typedef boost::optional<int> ov_type;
  109. rule<const char*, ov_type()> r2 = int_;
  110. ov_type ov;
  111. BOOST_TEST(test_attr("1", r2, ov) && ov && boost::get<int>(ov) == 1);
  112. }
  113. // test handling of single element fusion sequences
  114. {
  115. using boost::fusion::vector;
  116. using boost::fusion::at_c;
  117. rule<const char*, vector<int>()> r = int_;
  118. vector<int> v(0);
  119. BOOST_TEST(test_attr("1", r, v) && at_c<0>(v) == 1);
  120. }
  121. {
  122. using boost::fusion::vector;
  123. using boost::fusion::at_c;
  124. rule<const char*, vector<unsigned int>()> r = uint_;
  125. vector<unsigned int> v(0);
  126. BOOST_TEST(test_attr("1", r, v) && at_c<0>(v) == 1);
  127. }
  128. ///////////////////////////////////////////////////////////////////////////
  129. {
  130. using boost::spirit::qi::int_;
  131. using boost::spirit::qi::_1;
  132. using boost::spirit::qi::_val;
  133. using boost::spirit::qi::space;
  134. using boost::spirit::qi::space_type;
  135. rule<const char*, int()> r1 = int_;
  136. rule<const char*, int(), space_type> r2 = int_;
  137. int i = 0;
  138. int j = 0;
  139. BOOST_TEST(test_attr("456", r1[_val = _1], i) && i == 456);
  140. BOOST_TEST(test_attr(" 456", r2[_val = _1], j, space) && j == 456);
  141. }
  142. #if 0 // disabling test (can't fix)
  143. {
  144. using boost::spirit::qi::lexeme;
  145. using boost::spirit::qi::alnum;
  146. rule<const char*, std::string()> literal_;
  147. literal_ = lexeme[ +(alnum | '_') ];
  148. std::string attr;
  149. BOOST_TEST(test_attr("foo_bar", literal_, attr) && attr == "foo_bar");
  150. std::cout << attr << std::endl;
  151. }
  152. #endif
  153. return boost::report_errors();
  154. }