• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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