with.cpp 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. /*=============================================================================
  2. Copyright (c) 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 "test.hpp"
  9. namespace x3 = boost::spirit::x3;
  10. struct my_tag;
  11. struct my_rule_class
  12. {
  13. template <typename Iterator, typename Exception, typename Context>
  14. x3::error_handler_result
  15. on_error(Iterator&, Iterator const&, Exception const&, Context const& context)
  16. {
  17. x3::get<my_tag>(context)++;
  18. return x3::error_handler_result::fail;
  19. }
  20. template <typename Iterator, typename Attribute, typename Context>
  21. inline void
  22. on_success(Iterator const&, Iterator const&, Attribute&, Context const& context)
  23. {
  24. x3::get<my_tag>(context)++;
  25. }
  26. };
  27. int
  28. main()
  29. {
  30. using spirit_test::test_attr;
  31. using spirit_test::test;
  32. using boost::spirit::x3::rule;
  33. using boost::spirit::x3::int_;
  34. using boost::spirit::x3::with;
  35. { // injecting data into the context in the grammar
  36. int val = 0;
  37. auto r = rule<my_rule_class, char const*>() =
  38. '(' > int_ > ',' > int_ > ')'
  39. ;
  40. auto start =
  41. with<my_tag>(std::ref(val)) [ r ]
  42. ;
  43. BOOST_TEST(test("(123,456)", start));
  44. BOOST_TEST(!test("(abc,def)", start));
  45. BOOST_TEST(val == 2);
  46. }
  47. { // injecting non-const lvalue into the context
  48. int val = 0;
  49. auto const r = int_[([](auto& ctx){
  50. x3::get<my_tag>(ctx) += x3::_attr(ctx);
  51. })];
  52. BOOST_TEST(test("123,456", with<my_tag>(val)[r % ',']));
  53. BOOST_TEST(579 == val);
  54. }
  55. { // injecting rvalue into the context
  56. auto const r1 = int_[([](auto& ctx){
  57. x3::get<my_tag>(ctx) += x3::_attr(ctx);
  58. })];
  59. auto const r2 = rule<struct my_rvalue_rule_class, int>() =
  60. x3::lit('(') >> (r1 % ',') >> x3::lit(')')[([](auto& ctx){
  61. x3::_val(ctx) = x3::get<my_tag>(ctx);
  62. })];
  63. int attr = 0;
  64. BOOST_TEST(test_attr("(1,2,3)", with<my_tag>(100)[r2], attr));
  65. BOOST_TEST(106 == attr);
  66. }
  67. { // injecting const/non-const lvalue and rvalue into the context
  68. struct functor {
  69. int operator()(int& val) {
  70. return val * 10; // non-const ref returns 10 * injected val
  71. }
  72. int operator()(int const& val) {
  73. return val; // const ref returns injected val
  74. }
  75. };
  76. auto f = [](auto& ctx){
  77. x3::_val(ctx) = x3::_attr(ctx) + functor()(x3::get<my_tag>(ctx));
  78. };
  79. auto const r = rule<struct my_rule_class2, int>() = int_[f];
  80. int attr = 0;
  81. int const cval = 10;
  82. BOOST_TEST(test_attr("5", with<my_tag>(cval)[r], attr));
  83. BOOST_TEST(15 == attr); // x3::get returns const ref to cval
  84. attr = 0;
  85. int val = 10;
  86. BOOST_TEST(test_attr("5", with<my_tag>(val)[r], attr));
  87. BOOST_TEST(105 == attr); // x3::get returns ref to val
  88. attr = 0;
  89. BOOST_TEST(test_attr("5", with<my_tag>(10)[r], attr));
  90. // x3::get returns ref to member variable of with_directive
  91. BOOST_TEST(105 == attr);
  92. }
  93. return boost::report_errors();
  94. }