1 /*=============================================================================
2 Copyright (c) 2001-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
8 #include <boost/detail/lightweight_test.hpp>
9 #include <boost/spirit/home/x3.hpp>
10
11 #include <string>
12 #include <cstring>
13 #include <iostream>
14 #include "test.hpp"
15
16 namespace x3 = boost::spirit::x3;
17
18 struct check_no_rule_injection_parser
19 : x3::parser<check_no_rule_injection_parser>
20 {
21 typedef x3::unused_type attribute_type;
22 static bool const has_attribute = false;
23
24 template <typename Iterator, typename Context
25 , typename RuleContext, typename Attribute>
parsecheck_no_rule_injection_parser26 bool parse(Iterator&, Iterator const&, Context const&,
27 RuleContext&, Attribute&) const
28 {
29 static_assert(std::is_same<Context, x3::unused_type>::value,
30 "no rule definition injection should occur");
31 return true;
32 }
33 } const check_no_rule_injection{};
34
35 int
main()36 main()
37 {
38 using spirit_test::test_attr;
39 using spirit_test::test;
40
41 using namespace boost::spirit::x3::ascii;
42 using boost::spirit::x3::rule;
43 using boost::spirit::x3::lit;
44 using boost::spirit::x3::unused_type;
45 using boost::spirit::x3::_attr;
46
47 { // context tests
48
49 char ch;
50 auto a = rule<class a, char>() = alpha;
51
52 // this semantic action requires the context
53 auto f = [&](auto& ctx){ ch = _attr(ctx); };
54 BOOST_TEST(test("x", a[f]));
55 BOOST_TEST(ch == 'x');
56
57 // this semantic action requires the (unused) context
58 auto f2 = [&](auto&){ ch = 'y'; };
59 BOOST_TEST(test("x", a[f2]));
60 BOOST_TEST(ch == 'y');
61
62 // the semantic action may optionally not have any arguments at all
63 auto f3 = [&]{ ch = 'z'; };
64 BOOST_TEST(test("x", a[f3]));
65 BOOST_TEST(ch == 'z');
66
67 BOOST_TEST(test_attr("z", a, ch)); // attribute is given.
68 BOOST_TEST(ch == 'z');
69 }
70
71 { // auto rules tests
72
73 char ch = '\0';
74 auto a = rule<class a, char>() = alpha;
75 auto f = [&](auto& ctx){ ch = _attr(ctx); };
76
77 BOOST_TEST(test("x", a[f]));
78 BOOST_TEST(ch == 'x');
79 ch = '\0';
80 BOOST_TEST(test_attr("z", a, ch)); // attribute is given.
81 BOOST_TEST(ch == 'z');
82
83 ch = '\0';
84 BOOST_TEST(test("x", a[f]));
85 BOOST_TEST(ch == 'x');
86 ch = '\0';
87 BOOST_TEST(test_attr("z", a, ch)); // attribute is given.
88 BOOST_TEST(ch == 'z');
89 }
90
91 { // auto rules tests: allow stl containers as attributes to
92 // sequences (in cases where attributes of the elements
93 // are convertible to the value_type of the container or if
94 // the element itself is an stl container with value_type
95 // that is convertible to the value_type of the attribute).
96
97 std::string s;
98 auto f = [&](auto& ctx){ s = _attr(ctx); };
99
100 {
101 auto r = rule<class r, std::string>()
102 = char_ >> *(',' >> char_)
103 ;
104
105 BOOST_TEST(test("a,b,c,d,e,f", r[f]));
106 BOOST_TEST(s == "abcdef");
107 }
108
109 {
110 auto r = rule<class r, std::string>()
111 = char_ >> *(',' >> char_);
112 s.clear();
113 BOOST_TEST(test("a,b,c,d,e,f", r[f]));
114 BOOST_TEST(s == "abcdef");
115 }
116
117 {
118 auto r = rule<class r, std::string>()
119 = char_ >> char_ >> char_ >> char_ >> char_ >> char_;
120 s.clear();
121 BOOST_TEST(test("abcdef", r[f]));
122 BOOST_TEST(s == "abcdef");
123 }
124 }
125
126 {
127 BOOST_TEST(test("", rule<class a>{} = check_no_rule_injection));
128 BOOST_TEST(test("", rule<class a>{} %= check_no_rule_injection));
129 }
130
131 return boost::report_errors();
132 }
133