• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*=============================================================================
2     Copyright (c) 2015 Joel de Guzman
3 
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 #include <boost/detail/lightweight_test.hpp>
8 #include <boost/spirit/home/x3.hpp>
9 #include "test.hpp"
10 
11 namespace x3 = boost::spirit::x3;
12 
13 struct my_tag;
14 
15 struct my_rule_class
16 {
17     template <typename Iterator, typename Exception, typename Context>
18     x3::error_handler_result
on_errormy_rule_class19     on_error(Iterator&, Iterator const&, Exception const&, Context const& context)
20     {
21         x3::get<my_tag>(context)++;
22         return x3::error_handler_result::fail;
23     }
24 
25     template <typename Iterator, typename Attribute, typename Context>
26     inline void
on_successmy_rule_class27     on_success(Iterator const&, Iterator const&, Attribute&, Context const& context)
28     {
29         x3::get<my_tag>(context)++;
30     }
31 };
32 
33 int
main()34 main()
35 {
36     using spirit_test::test_attr;
37     using spirit_test::test;
38 
39     using boost::spirit::x3::rule;
40     using boost::spirit::x3::int_;
41     using boost::spirit::x3::with;
42 
43 // read from a mutable field is not allowed on these compilers
44 #if (!defined(_MSC_VER) || _MSC_VER >= 1910) && \
45     (!defined(__clang__) || __clang_major__ >= 7)
46     BOOST_SPIRIT_ASSERT_CONSTEXPR_CTORS(with<my_tag>(0)['x']);
47 #endif
48     {
49         constexpr int i = 0;
50         BOOST_SPIRIT_ASSERT_CONSTEXPR_CTORS(with<my_tag>(i)['x']);
51     }
52 
53     { // injecting data into the context in the grammar
54 
55         int val = 0;
56         auto r = rule<my_rule_class, char const*>() =
57             '(' > int_ > ',' > int_ > ')'
58             ;
59 
60         auto start =
61             with<my_tag>(std::ref(val)) [ r ]
62             ;
63 
64         BOOST_TEST(test("(123,456)", start));
65         BOOST_TEST(!test("(abc,def)", start));
66         BOOST_TEST(val == 2);
67     }
68 
69     { // injecting non-const lvalue into the context
70         int val = 0;
71         auto const r  = int_[([](auto& ctx){
72             x3::get<my_tag>(ctx) += x3::_attr(ctx);
73         })];
74         BOOST_TEST(test("123,456", with<my_tag>(val)[r % ',']));
75         BOOST_TEST(579 == val);
76     }
77 
78     { // injecting rvalue into the context
79         auto const r1 = int_[([](auto& ctx){
80             x3::get<my_tag>(ctx) += x3::_attr(ctx);
81         })];
82         auto const r2 = rule<struct my_rvalue_rule_class, int>() =
83             x3::lit('(') >> (r1 % ',') >> x3::lit(')')[([](auto& ctx){
84                 x3::_val(ctx) = x3::get<my_tag>(ctx);
85             })];
86         int attr = 0;
87         BOOST_TEST(test_attr("(1,2,3)", with<my_tag>(100)[r2], attr));
88         BOOST_TEST(106 == attr);
89     }
90 
91     { // injecting const/non-const lvalue and rvalue into the context
92         struct functor {
93             int operator()(int& val) {
94                 return val * 10; // non-const ref returns 10 * injected val
95             }
96             int operator()(int const& val) {
97                 return val; // const ref returns injected val
98             }
99         };
100 
101         auto f = [](auto& ctx){
102             x3::_val(ctx) = x3::_attr(ctx) + functor()(x3::get<my_tag>(ctx));
103         };
104         auto const r = rule<struct my_rule_class2, int>() = int_[f];
105 
106         int attr = 0;
107         int const cval = 10;
108         BOOST_TEST(test_attr("5", with<my_tag>(cval)[r], attr));
109         BOOST_TEST(15 == attr); // x3::get returns const ref to cval
110 
111         attr = 0;
112         int val = 10;
113         BOOST_TEST(test_attr("5", with<my_tag>(val)[r], attr));
114         BOOST_TEST(105 == attr); // x3::get returns ref to val
115 
116         attr = 0;
117 
118         BOOST_TEST(test_attr("5", with<my_tag>(10)[r], attr));
119         // x3::get returns ref to member variable of with_directive
120         BOOST_TEST(105 == attr);
121     }
122 
123     return boost::report_errors();
124 }
125