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 #define BOOST_SPIRIT_X3_DEBUG
8
9 #include <boost/detail/lightweight_test.hpp>
10 #include <boost/spirit/home/x3.hpp>
11 #include <boost/fusion/include/std_pair.hpp>
12 #include <boost/fusion/include/vector.hpp>
13
14 #include <vector>
15 #include <string>
16 #include <cstring>
17 #include <iostream>
18 #include "test.hpp"
19
20 struct my_error_handler
21 {
22 template <typename Iterator, typename Exception, typename Context>
23 boost::spirit::x3::error_handler_result
operator ()my_error_handler24 operator()(Iterator&, Iterator const& last, Exception const& x, Context const&) const
25 {
26 std::cout
27 << "Error! Expecting: "
28 << x.which()
29 << ", got: \""
30 << std::string(x.where(), last)
31 << "\""
32 << std::endl;
33 return boost::spirit::x3::error_handler_result::fail;
34 }
35 };
36
37 struct my_attribute
38 {
39 bool alive = true;
40
accessmy_attribute41 void access() const
42 {
43 BOOST_TEST(alive);
44 }
~my_attributemy_attribute45 ~my_attribute()
46 {
47 alive = false;
48 }
49
operator <<(std::ostream & os,my_attribute const & attr)50 friend std::ostream & operator << (std::ostream & os, my_attribute const & attr)
51 {
52 attr.access();
53 return os << "my_attribute";
54 }
55 };
56
57 int
main()58 main()
59 {
60 using spirit_test::test_attr;
61 using spirit_test::test;
62
63 using namespace boost::spirit::x3::ascii;
64 using boost::spirit::x3::rule;
65 using boost::spirit::x3::symbols;
66 using boost::spirit::x3::int_;
67 using boost::spirit::x3::alpha;
68
69 { // basic tests
70
71 auto a = rule<class a>("a") = 'a';
72 auto b = rule<class b>("b") = 'b';
73 auto c = rule<class c>("c") = 'c';
74
75 {
76 auto start = *(a | b | c);
77 BOOST_TEST(test("abcabcacb", start));
78 }
79
80 {
81 rule<class start> start("start");
82 auto start_def =
83 start = (a | b) >> (start | b);
84
85 BOOST_TEST(test("aaaabababaaabbb", start_def));
86 BOOST_TEST(test("aaaabababaaabba", start_def, false));
87 }
88 }
89
90 { // basic tests w/ skipper
91
92 auto a = rule<class a>("a") = 'a';
93 auto b = rule<class b>("b") = 'b';
94 auto c = rule<class c>("c") = 'c';
95
96 {
97 auto start = *(a | b | c);
98 BOOST_TEST(test(" a b c a b c a c b ", start, space));
99 }
100
101 {
102 rule<class start> start("start");
103 auto start_def =
104 start = (a | b) >> (start | b);
105
106 BOOST_TEST(test(" a a a a b a b a b a a a b b b ", start_def, space));
107 BOOST_TEST(test(" a a a a b a b a b a a a b b a ", start_def, space, false));
108 }
109 }
110
111 { // std::container attributes
112
113 typedef boost::fusion::vector<int, char> fs;
114 rule<class start, std::vector<fs>> start("start");
115 auto start_def =
116 start = *(int_ >> alpha);
117
118 BOOST_TEST(test("1 a 2 b 3 c", start_def, space));
119 }
120
121 { // error handling
122
123 auto r_def = '(' > int_ > ',' > int_ > ')';
124 auto r = r_def.on_error(my_error_handler());
125
126 BOOST_TEST(test("(123,456)", r));
127 BOOST_TEST(!test("(abc,def)", r));
128 BOOST_TEST(!test("(123,456]", r));
129 BOOST_TEST(!test("(123;456)", r));
130 BOOST_TEST(!test("[123,456]", r));
131 }
132
133 {
134 symbols<my_attribute> a{{{ "a", my_attribute{} }}};
135
136 auto b = rule<struct b, my_attribute>("b") = a;
137
138 my_attribute attr;
139
140 BOOST_TEST(test_attr("a", b, attr));
141 }
142
143 return boost::report_errors();
144 }
145