]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 | ||
7c673cae FG |
8 | #include <boost/detail/lightweight_test.hpp> |
9 | #include <boost/spirit/home/x3.hpp> | |
10 | #include <boost/fusion/include/vector.hpp> | |
11 | #include <boost/fusion/include/at.hpp> | |
12 | ||
13 | #include <string> | |
14 | #include <cstring> | |
15 | #include <iostream> | |
16 | #include "test.hpp" | |
17 | ||
18 | namespace x3 = boost::spirit::x3; | |
19 | ||
20 | int got_it = 0; | |
21 | ||
22 | struct my_rule_class | |
23 | { | |
24 | template <typename Iterator, typename Exception, typename Context> | |
25 | x3::error_handler_result | |
92f5a8d4 | 26 | on_error(Iterator&, Iterator const& last, Exception const& x, Context const&) |
7c673cae FG |
27 | { |
28 | std::cout | |
29 | << "Error! Expecting: " | |
30 | << x.which() | |
31 | << ", got: \"" | |
32 | << std::string(x.where(), last) | |
33 | << "\"" | |
34 | << std::endl | |
35 | ; | |
36 | return x3::error_handler_result::fail; | |
37 | } | |
38 | ||
39 | template <typename Iterator, typename Attribute, typename Context> | |
40 | inline void | |
41 | on_success(Iterator const&, Iterator const&, Attribute&, Context const&) | |
42 | { | |
43 | ++got_it; | |
44 | } | |
45 | }; | |
46 | ||
47 | int | |
48 | main() | |
49 | { | |
50 | using spirit_test::test_attr; | |
51 | using spirit_test::test; | |
52 | ||
53 | using namespace boost::spirit::x3::ascii; | |
54 | using boost::spirit::x3::rule; | |
55 | using boost::spirit::x3::int_; | |
56 | using boost::spirit::x3::lit; | |
57 | ||
58 | { // show that ra = rb and ra %= rb works as expected | |
59 | rule<class a, int> ra; | |
60 | rule<class b, int> rb; | |
61 | int attr; | |
62 | ||
63 | auto ra_def = (ra %= int_); | |
64 | BOOST_TEST(test_attr("123", ra_def, attr)); | |
65 | BOOST_TEST(attr == 123); | |
66 | ||
67 | auto rb_def = (rb %= ra_def); | |
68 | BOOST_TEST(test_attr("123", rb_def, attr)); | |
69 | BOOST_TEST(attr == 123); | |
70 | ||
71 | auto rb_def2 = (rb = ra_def); | |
72 | BOOST_TEST(test_attr("123", rb_def2, attr)); | |
73 | BOOST_TEST(attr == 123); | |
74 | } | |
75 | ||
76 | { // show that ra %= rb works as expected with semantic actions | |
77 | rule<class a, int> ra; | |
78 | rule<class b, int> rb; | |
79 | int attr; | |
80 | ||
92f5a8d4 | 81 | auto f = [](auto&){}; |
7c673cae FG |
82 | auto ra_def = (ra %= int_[f]); |
83 | BOOST_TEST(test_attr("123", ra_def, attr)); | |
84 | BOOST_TEST(attr == 123); | |
85 | ||
86 | auto ra_def2 = (rb = (ra %= int_[f])); | |
87 | BOOST_TEST(test_attr("123", ra_def2, attr)); | |
88 | BOOST_TEST(attr == 123); | |
89 | } | |
90 | ||
91 | ||
92 | { // std::string as container attribute with auto rules | |
93 | ||
94 | std::string attr; | |
95 | ||
96 | // test deduced auto rule behavior | |
97 | ||
98 | auto text = rule<class text, std::string>() | |
99 | = +(!char_(')') >> !char_('>') >> char_); | |
100 | ||
101 | attr.clear(); | |
102 | BOOST_TEST(test_attr("x", text, attr)); | |
103 | BOOST_TEST(attr == "x"); | |
104 | } | |
105 | ||
106 | { // error handling | |
107 | ||
108 | auto r = rule<my_rule_class, char const*>() | |
109 | = '(' > int_ > ',' > int_ > ')'; | |
110 | ||
111 | BOOST_TEST(test("(123,456)", r)); | |
112 | BOOST_TEST(!test("(abc,def)", r)); | |
113 | BOOST_TEST(!test("(123,456]", r)); | |
114 | BOOST_TEST(!test("(123;456)", r)); | |
115 | BOOST_TEST(!test("[123,456]", r)); | |
116 | ||
117 | BOOST_TEST(got_it == 1); | |
118 | } | |
119 | ||
120 | { | |
121 | typedef boost::variant<double, int> v_type; | |
122 | auto r1 = rule<class r1, v_type>() | |
123 | = int_; | |
124 | v_type v; | |
125 | BOOST_TEST(test_attr("1", r1, v) && v.which() == 1 && | |
126 | boost::get<int>(v) == 1); | |
127 | ||
128 | typedef boost::optional<int> ov_type; | |
129 | auto r2 = rule<class r2, ov_type>() | |
130 | = int_; | |
131 | ov_type ov; | |
132 | BOOST_TEST(test_attr("1", r2, ov) && ov && boost::get<int>(ov) == 1); | |
133 | } | |
134 | ||
135 | // test handling of single element fusion sequences | |
136 | { | |
137 | using boost::fusion::vector; | |
138 | using boost::fusion::at_c; | |
139 | auto r = rule<class r, vector<int>>() | |
140 | = int_; | |
141 | ||
142 | vector<int> v(0); | |
143 | BOOST_TEST(test_attr("1", r, v) && at_c<0>(v) == 1); | |
144 | } | |
145 | ||
146 | { // attribute compatibility test | |
147 | using boost::spirit::x3::rule; | |
148 | using boost::spirit::x3::int_; | |
149 | ||
150 | auto const expr = int_; | |
151 | ||
152 | short i; | |
153 | BOOST_TEST(test_attr("1", expr, i) && i == 1); // ok | |
154 | ||
155 | const rule< class int_rule, int > int_rule( "int_rule" ); | |
156 | auto const int_rule_def = int_; | |
157 | auto const start = int_rule = int_rule_def; | |
158 | ||
159 | short j; | |
160 | BOOST_TEST(test_attr("1", start, j) && j == 1); // error | |
161 | } | |
162 | ||
163 | return boost::report_errors(); | |
164 | } |