• 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 namespace check_recursive_scoped {
70 
71 using check_recursive::node_t;
72 
73 x3::rule<class intvec_r, node_t> const intvec;
74 auto const grammar = intvec = '[' >> intvec % ',' >> ']' | x3::int_;
75 
76 }
77 
78 struct recursive_tuple
79 {
80     int value;
81     std::vector<recursive_tuple> children;
82 };
83 BOOST_FUSION_ADAPT_STRUCT(recursive_tuple,
84     value, children)
85 
86 // regression test for #461
87 namespace check_recursive_tuple {
88 
89 x3::rule<class grammar_r, recursive_tuple> const grammar;
90 auto const grammar_def = x3::int_ >> ('{' >> grammar % ',' >> '}' | x3::eps);
91 BOOST_SPIRIT_DEFINE(grammar)
92 
93 BOOST_SPIRIT_INSTANTIATE(decltype(grammar), char const*, x3::unused_type)
94 
95 }
96 
97 
main()98 int main()
99 {
100     using spirit_test::test_attr;
101     using spirit_test::test;
102 
103     using namespace boost::spirit::x3::ascii;
104     using boost::spirit::x3::rule;
105     using boost::spirit::x3::lit;
106     using boost::spirit::x3::eps;
107     using boost::spirit::x3::unused_type;
108 
109 
110     { // synth attribute value-init
111 
112         std::string s;
113         typedef rule<class r, std::string> rule_type;
114 
115         auto rdef = rule_type()
116             = alpha                 [f()]
117             ;
118 
119         BOOST_TEST(test_attr("abcdef", +rdef, s));
120         BOOST_TEST(s == "abcdef");
121     }
122 
123     { // synth attribute value-init
124 
125         std::string s;
126         typedef rule<class r, std::string> rule_type;
127 
128         auto rdef = rule_type() =
129             alpha /
130                [](auto& ctx)
131                {
132                   _val(ctx) += _attr(ctx);
133                }
134             ;
135 
136         BOOST_TEST(test_attr("abcdef", +rdef, s));
137         BOOST_TEST(s == "abcdef");
138     }
139 
140     {
141         auto r = rule<class r, int>{} = eps[([] (auto& ctx) {
142             using boost::spirit::x3::_val;
143             static_assert(std::is_same<std::decay_t<decltype(_val(ctx))>, unused_type>::value,
144                 "Attribute must not be synthesized");
145         })];
146         BOOST_TEST(test("", r));
147     }
148 
149     { // ensure no unneeded synthesization, copying and moving occurred
150         stationary st { 0 };
151         BOOST_TEST(test_attr("{42}", check_stationary::b, st));
152         BOOST_TEST_EQ(st.val, 42);
153     }
154 
155     {
156         using namespace check_recursive;
157         node_t v;
158         BOOST_TEST(test_attr("[4,2]", grammar, v));
159         BOOST_TEST((node_t{std::vector<node_t>{{4}, {2}}} == v));
160     }
161     {
162         using namespace check_recursive_scoped;
163         node_t v;
164         BOOST_TEST(test_attr("[4,2]", grammar, v));
165         BOOST_TEST((node_t{std::vector<node_t>{{4}, {2}}} == v));
166     }
167 
168     return boost::report_errors();
169 }
170