1 /*=============================================================================
2 Copyright (c) 2001-2011 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 #include <boost/detail/lightweight_test.hpp>
8 #include <boost/spirit/include/qi_string.hpp>
9 #include <boost/spirit/include/qi_char.hpp>
10 #include <boost/spirit/include/qi_action.hpp>
11 #include <boost/spirit/include/qi_auxiliary.hpp>
12 #include <boost/spirit/include/qi_directive.hpp>
13 #include <boost/spirit/include/qi_operator.hpp>
14 #include <boost/spirit/include/qi_nonterminal.hpp>
15 #include <boost/spirit/include/support_argument.hpp>
16 #include <boost/spirit/include/phoenix_core.hpp>
17 #include <boost/spirit/include/phoenix_operator.hpp>
18
19 #include <iostream>
20 #include "test.hpp"
21
22 // Custom string type with a C-style string conversion.
23 struct custom_string_c
24 {
custom_string_ccustom_string_c25 custom_string_c(char c) { str[0] = c; str[1] = '\0'; }
26
operator char*custom_string_c27 operator char*() { return str; }
operator char const*custom_string_c28 operator char const*() const { return str; }
29
30 private:
31 char str[2];
32 };
33
get_str(char const * str)34 std::string get_str(char const* str)
35 {
36 return std::string(str);
37 }
38
39 int
main()40 main()
41 {
42 using spirit_test::test;
43 using spirit_test::test_attr;
44 using boost::spirit::qi::symbols;
45 using boost::spirit::qi::rule;
46 using boost::spirit::qi::lazy;
47 using boost::spirit::qi::_r1;
48
49 { // construction from symbol array
50 char const* syms[] = {"Joel","Ruby","Tenji","Tutit","Kim","Joey"};
51 symbols<char, int> sym(syms);
52
53 BOOST_TEST((test("Joel", sym)));
54 BOOST_TEST((test("Ruby", sym)));
55 BOOST_TEST((test("Tenji", sym)));
56 BOOST_TEST((test("Tutit", sym)));
57 BOOST_TEST((test("Kim", sym)));
58 BOOST_TEST((test("Joey", sym)));
59 BOOST_TEST((!test("XXX", sym)));
60 }
61
62 { // construction from 2 arrays
63
64 char const* syms[] = {"Joel","Ruby","Tenji","Tutit","Kim","Joey"};
65 int data[] = {1,2,3,4,5,6};
66 symbols<char, int> sym(syms, data);
67
68 int i;
69 BOOST_TEST((test_attr("Joel", sym, i)));
70 BOOST_TEST(i == 1);
71 BOOST_TEST((test_attr("Ruby", sym, i)));
72 BOOST_TEST(i == 2);
73 BOOST_TEST((test_attr("Tenji", sym, i)));
74 BOOST_TEST(i == 3);
75 BOOST_TEST((test_attr("Tutit", sym, i)));
76 BOOST_TEST(i == 4);
77 BOOST_TEST((test_attr("Kim", sym, i)));
78 BOOST_TEST(i == 5);
79 BOOST_TEST((test_attr("Joey", sym, i)));
80 BOOST_TEST(i == 6);
81 BOOST_TEST((!test_attr("XXX", sym, i)));
82 }
83
84 { // allow std::string and other string types
85 symbols<> sym;
86
87 // const and non-const std::string
88 std::string a("abc");
89 std::string const b("def");
90 sym += a;
91 sym += b;
92 BOOST_TEST((test("abc", sym)));
93 BOOST_TEST((test("def", sym)));
94 sym = a;
95 BOOST_TEST((test("abc", sym)));
96 BOOST_TEST((!test("def", sym)));
97
98 // non-const C-style string
99 char arr[2]; arr[0] = 'a'; arr[1] = '\0';
100 sym = arr;
101 BOOST_TEST((test("a", sym)));
102 BOOST_TEST((!test("b", sym)));
103
104 // const and non-const custom string type
105 custom_string_c c('x');
106 custom_string_c const cc('y');
107 sym = c, cc;
108 BOOST_TEST((test("x", sym)));
109 BOOST_TEST((test("y", sym)));
110 BOOST_TEST((!test("z", sym)));
111 }
112
113 {
114 namespace phx = boost::phoenix;
115
116 symbols<char, int> sym;
117 sym.add
118 ("a", 1)
119 ("b", 2)
120 ;
121
122 rule<char const*, int(symbols<char, int>&)> r;
123 r %= lazy(_r1);
124
125 int i = 0;
126 BOOST_TEST(test_attr("a", r(phx::ref(sym)), i));
127 BOOST_TEST(i == 1);
128 BOOST_TEST(test_attr("b", r(phx::ref(sym)), i));
129 BOOST_TEST(i == 2);
130 BOOST_TEST(!test("c", r(phx::ref(sym))));
131 }
132
133 { // find
134
135 symbols<char, int> sym;
136 sym.add("a", 1)("b", 2);
137
138 BOOST_TEST(!sym.find("c"));
139
140 BOOST_TEST(sym.find("a") && *sym.find("a") == 1);
141 BOOST_TEST(sym.find("b") && *sym.find("b") == 2);
142
143 BOOST_TEST(sym.at("a") == 1);
144 BOOST_TEST(sym.at("b") == 2);
145 BOOST_TEST(sym.at("c") == 0);
146
147 BOOST_TEST(sym.find("a") && *sym.find("a") == 1);
148 BOOST_TEST(sym.find("b") && *sym.find("b") == 2);
149 BOOST_TEST(sym.find("c") && *sym.find("c") == 0);
150
151 symbols<char, int> const_sym(sym);
152
153 BOOST_TEST(const_sym.find("a") && *const_sym.find("a") == 1);
154 BOOST_TEST(const_sym.find("b") && *const_sym.find("b") == 2);
155 BOOST_TEST(const_sym.find("c") && *const_sym.find("c") == 0);
156 BOOST_TEST(!const_sym.find("d"));
157
158 char const *str1 = "all";
159 char const *first = str1, *last = str1 + 3;
160 BOOST_TEST(*sym.prefix_find(first, last) == 1 && first == str1 + 1);
161
162 char const *str2 = "dart";
163 first = str2; last = str2 + 4;
164 BOOST_TEST(!sym.prefix_find(first, last) && first == str2);
165 }
166
167 { // name
168 symbols <char, int> sym,sym2;
169 sym.name("test");
170 BOOST_TEST(sym.name()=="test");
171 sym2 = sym;
172 BOOST_TEST(sym2.name()=="test");
173
174 symbols <char,int> sym3(sym);
175 BOOST_TEST(sym3.name()=="test");
176 }
177
178 { // Substrings
179
180 symbols<char, int> sym;
181 BOOST_TEST(sym.at("foo") == 0);
182 sym.at("foo") = 1;
183 BOOST_TEST(sym.at("foo") == 1);
184 BOOST_TEST(sym.at("fool") == 0);
185 sym.at("fool") = 2;
186 BOOST_TEST(sym.find("foo") && *sym.find("foo") == 1);
187 BOOST_TEST(sym.find("fool") && *sym.find("fool") == 2);
188 BOOST_TEST(!sym.find("foolish"));
189 BOOST_TEST(!sym.find("foot"));
190 BOOST_TEST(!sym.find("afoot"));
191
192 char const *str, *first, *last;
193 str = "foolish"; first = str; last = str + 7;
194 BOOST_TEST(*sym.prefix_find(first, last) == 2 && first == str + 4);
195
196 first = str; last = str + 4;
197 BOOST_TEST(*sym.prefix_find(first, last) == 2 && first == str + 4);
198
199 str = "food"; first = str; last = str + 4;
200 BOOST_TEST(*sym.prefix_find(first, last) == 1 && first == str + 3);
201
202 first = str; last = str + 3;
203 BOOST_TEST(*sym.prefix_find(first, last) == 1 && first == str + 3);
204
205 first = str; last = str + 2;
206 BOOST_TEST(!sym.prefix_find(first, last) && first == str);
207 }
208
209 {
210 // remove bug
211
212 std::string s;
213 symbols<char, double> vars;
214
215 vars.add("l1", 12.0);
216 vars.add("l2", 0.0);
217 vars.remove("l2");
218 vars.find("l1");
219 double* d = vars.find("l1");
220 BOOST_TEST(d != 0);
221 }
222
223 { // test for proto problem with rvalue references (10-11-2011)
224 symbols<char, int> sym;
225 sym += get_str("Joel");
226 sym += get_str("Ruby");
227
228 BOOST_TEST((test("Joel", sym)));
229 BOOST_TEST((test("Ruby", sym)));
230 }
231
232 return boost::report_errors();
233 }
234