rule4.cpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. /*=============================================================================
  2. Copyright (c) 2001-2015 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/home/x3.hpp>
  8. #include <boost/fusion/include/vector.hpp>
  9. #include <boost/fusion/include/at.hpp>
  10. #include <string>
  11. #include <cstring>
  12. #include <iostream>
  13. #include "test.hpp"
  14. namespace x3 = boost::spirit::x3;
  15. int got_it = 0;
  16. struct my_rule_class
  17. {
  18. template <typename Iterator, typename Exception, typename Context>
  19. x3::error_handler_result
  20. on_error(Iterator&, Iterator const& last, Exception const& x, Context const&)
  21. {
  22. std::cout
  23. << "Error! Expecting: "
  24. << x.which()
  25. << ", got: \""
  26. << std::string(x.where(), last)
  27. << "\""
  28. << std::endl
  29. ;
  30. return x3::error_handler_result::fail;
  31. }
  32. template <typename Iterator, typename Attribute, typename Context>
  33. inline void
  34. on_success(Iterator const&, Iterator const&, Attribute&, Context const&)
  35. {
  36. ++got_it;
  37. }
  38. };
  39. int
  40. main()
  41. {
  42. using spirit_test::test_attr;
  43. using spirit_test::test;
  44. using namespace boost::spirit::x3::ascii;
  45. using boost::spirit::x3::rule;
  46. using boost::spirit::x3::int_;
  47. using boost::spirit::x3::lit;
  48. { // show that ra = rb and ra %= rb works as expected
  49. rule<class a, int> ra;
  50. rule<class b, int> rb;
  51. int attr;
  52. auto ra_def = (ra %= int_);
  53. BOOST_TEST(test_attr("123", ra_def, attr));
  54. BOOST_TEST(attr == 123);
  55. auto rb_def = (rb %= ra_def);
  56. BOOST_TEST(test_attr("123", rb_def, attr));
  57. BOOST_TEST(attr == 123);
  58. auto rb_def2 = (rb = ra_def);
  59. BOOST_TEST(test_attr("123", rb_def2, attr));
  60. BOOST_TEST(attr == 123);
  61. }
  62. { // show that ra %= rb works as expected with semantic actions
  63. rule<class a, int> ra;
  64. rule<class b, int> rb;
  65. int attr;
  66. auto f = [](auto&){};
  67. auto ra_def = (ra %= int_[f]);
  68. BOOST_TEST(test_attr("123", ra_def, attr));
  69. BOOST_TEST(attr == 123);
  70. auto ra_def2 = (rb = (ra %= int_[f]));
  71. BOOST_TEST(test_attr("123", ra_def2, attr));
  72. BOOST_TEST(attr == 123);
  73. }
  74. { // std::string as container attribute with auto rules
  75. std::string attr;
  76. // test deduced auto rule behavior
  77. auto text = rule<class text, std::string>()
  78. = +(!char_(')') >> !char_('>') >> char_);
  79. attr.clear();
  80. BOOST_TEST(test_attr("x", text, attr));
  81. BOOST_TEST(attr == "x");
  82. }
  83. { // error handling
  84. auto r = rule<my_rule_class, char const*>()
  85. = '(' > int_ > ',' > int_ > ')';
  86. BOOST_TEST(test("(123,456)", r));
  87. BOOST_TEST(!test("(abc,def)", r));
  88. BOOST_TEST(!test("(123,456]", r));
  89. BOOST_TEST(!test("(123;456)", r));
  90. BOOST_TEST(!test("[123,456]", r));
  91. BOOST_TEST(got_it == 1);
  92. }
  93. {
  94. typedef boost::variant<double, int> v_type;
  95. auto r1 = rule<class r1, v_type>()
  96. = int_;
  97. v_type v;
  98. BOOST_TEST(test_attr("1", r1, v) && v.which() == 1 &&
  99. boost::get<int>(v) == 1);
  100. typedef boost::optional<int> ov_type;
  101. auto r2 = rule<class r2, ov_type>()
  102. = int_;
  103. ov_type ov;
  104. BOOST_TEST(test_attr("1", r2, ov) && ov && boost::get<int>(ov) == 1);
  105. }
  106. // test handling of single element fusion sequences
  107. {
  108. using boost::fusion::vector;
  109. using boost::fusion::at_c;
  110. auto r = rule<class r, vector<int>>()
  111. = int_;
  112. vector<int> v(0);
  113. BOOST_TEST(test_attr("1", r, v) && at_c<0>(v) == 1);
  114. }
  115. { // attribute compatibility test
  116. using boost::spirit::x3::rule;
  117. using boost::spirit::x3::int_;
  118. auto const expr = int_;
  119. short i;
  120. BOOST_TEST(test_attr("1", expr, i) && i == 1); // ok
  121. const rule< class int_rule, int > int_rule( "int_rule" );
  122. auto const int_rule_def = int_;
  123. auto const start = int_rule = int_rule_def;
  124. short j;
  125. BOOST_TEST(test_attr("1", start, j) && j == 1); // error
  126. }
  127. return boost::report_errors();
  128. }