• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*=============================================================================
2     Copyright (c) 2001-2012 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 
8 #include <boost/detail/lightweight_test.hpp>
9 #include <boost/spirit/home/x3.hpp>
10 #include <boost/fusion/include/adapt_struct.hpp>
11 #include <boost/fusion/include/std_pair.hpp>
12 
13 #include <boost/variant.hpp>
14 #include <string>
15 #include <vector>
16 #include <cstring>
17 #include <iostream>
18 #include "test.hpp"
19 
20 using boost::spirit::x3::_val;
21 namespace x3 = boost::spirit::x3;
22 
23 struct f
24 {
25     template <typename Context>
operator ()f26     void operator()(Context const& ctx) const
27     {
28         _val(ctx) += _attr(ctx);
29     }
30 };
31 
32 
33 struct stationary : boost::noncopyable
34 {
stationarystationary35     explicit stationary(int i) : val{i} {}
operator =stationary36     stationary& operator=(int i) { val = i; return *this; }
37 
38     int val;
39 };
40 
41 
42 namespace check_stationary {
43 
44 boost::spirit::x3::rule<class a_r, stationary> const a;
45 boost::spirit::x3::rule<class b_r, stationary> const b;
46 
47 auto const a_def = '{' >> boost::spirit::x3::int_ >> '}';
48 auto const b_def = a;
49 
50 BOOST_SPIRIT_DEFINE(a, b)
51 
52 }
53 
54 namespace check_recursive {
55 
56 using node_t = boost::make_recursive_variant<
57                    int,
58                    std::vector<boost::recursive_variant_>
59                >::type;
60 
61 boost::spirit::x3::rule<class grammar_r, node_t> const grammar;
62 
63 auto const grammar_def = '[' >> grammar % ',' >> ']' | boost::spirit::x3::int_;
64 
65 BOOST_SPIRIT_DEFINE(grammar)
66 
67 }
68 
69 struct recursive_tuple
70 {
71     int value;
72     std::vector<recursive_tuple> children;
73 };
74 BOOST_FUSION_ADAPT_STRUCT(recursive_tuple,
75     value, children)
76 
77 // regression test for #461
78 namespace check_recursive_tuple {
79 
80 x3::rule<class grammar_r, recursive_tuple> const grammar;
81 auto const grammar_def = x3::int_ >> ('{' >> grammar % ',' >> '}' | x3::eps);
82 BOOST_SPIRIT_DEFINE(grammar)
83 
84 BOOST_SPIRIT_INSTANTIATE(decltype(grammar), char const*, x3::unused_type)
85 
86 }
87 
88 
main()89 int main()
90 {
91     using spirit_test::test_attr;
92     using spirit_test::test;
93 
94     using namespace boost::spirit::x3::ascii;
95     using boost::spirit::x3::rule;
96     using boost::spirit::x3::lit;
97     using boost::spirit::x3::eps;
98     using boost::spirit::x3::unused_type;
99 
100 
101     { // synth attribute value-init
102 
103         std::string s;
104         typedef rule<class r, std::string> rule_type;
105 
106         auto rdef = rule_type()
107             = alpha                 [f()]
108             ;
109 
110         BOOST_TEST(test_attr("abcdef", +rdef, s));
111         BOOST_TEST(s == "abcdef");
112     }
113 
114     { // synth attribute value-init
115 
116         std::string s;
117         typedef rule<class r, std::string> rule_type;
118 
119         auto rdef = rule_type() =
120             alpha /
121                [](auto& ctx)
122                {
123                   _val(ctx) += _attr(ctx);
124                }
125             ;
126 
127         BOOST_TEST(test_attr("abcdef", +rdef, s));
128         BOOST_TEST(s == "abcdef");
129     }
130 
131     {
132         auto r = rule<class r, int>{} = eps[([] (auto& ctx) {
133             using boost::spirit::x3::_val;
134             static_assert(std::is_same<std::decay_t<decltype(_val(ctx))>, unused_type>::value,
135                 "Attribute must not be synthesized");
136         })];
137         BOOST_TEST(test("", r));
138     }
139 
140     { // ensure no unneeded synthesization, copying and moving occurred
141         stationary st { 0 };
142         BOOST_TEST(test_attr("{42}", check_stationary::b, st));
143         BOOST_TEST_EQ(st.val, 42);
144     }
145 
146     {
147         using namespace check_recursive;
148         node_t v;
149         BOOST_TEST(test_attr("[4,2]", grammar, v));
150         BOOST_TEST((node_t{std::vector<node_t>{{4}, {2}}} == v));
151     }
152 
153     return boost::report_errors();
154 }
155