1 // Copyright (c) 2001-2011 Hartmut Kaiser
2 // Copyright (c) 2001-2011 Joel de Guzman
3 // Copyright (c)      2010 Bryce Lelbach
4 //
5 // Distributed under the Boost Software License, Version 1.0. (See accompanying
6 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 
8 #include <boost/config/warning_disable.hpp>
9 #include <boost/detail/lightweight_test.hpp>
10 
11 #include <boost/mpl/print.hpp>
12 #include <boost/spirit/include/qi.hpp>
13 #include <boost/spirit/include/support_utree.hpp>
14 
15 #include <sstream>
16 
17 #include "test.hpp"
18 
check(boost::spirit::utree const & val,std::string expected)19 inline bool check(boost::spirit::utree const& val, std::string expected)
20 {
21     std::stringstream s;
22     s << val;
23     if (s.str() == expected + " ")
24         return true;
25 
26     std::cerr << "got result: " << s.str()
27               << ", expected: " << expected << std::endl;
28     return false;
29 }
30 
main()31 int main()
32 {
33     using spirit_test::test_attr;
34     using boost::spirit::utree;
35     using boost::spirit::utree_type;
36     using boost::spirit::utf8_string_range_type;
37     using boost::spirit::utf8_symbol_type;
38     using boost::spirit::utf8_string_type;
39 
40     using boost::spirit::qi::real_parser;
41     using boost::spirit::qi::strict_real_policies;
42     using boost::spirit::qi::digit;
43     using boost::spirit::qi::char_;
44     using boost::spirit::qi::string;
45     using boost::spirit::qi::int_;
46     using boost::spirit::qi::double_;
47     using boost::spirit::qi::space;
48     using boost::spirit::qi::space_type;
49     using boost::spirit::qi::rule;
50     using boost::spirit::qi::as;
51     using boost::spirit::qi::lexeme;
52 
53     // primitive data types
54     {
55         utree ut;
56         BOOST_TEST(test_attr("x", char_, ut) &&
57             ut.which() == utree_type::string_type && check(ut, "\"x\""));
58         ut.clear();
59         BOOST_TEST(test_attr("123", int_, ut) &&
60             ut.which() == utree_type::int_type && check(ut, "123"));
61         ut.clear();
62         BOOST_TEST(test_attr("123.45", double_, ut) &&
63             ut.which() == utree_type::double_type && check(ut, "123.45"));
64         ut.clear();
65 
66         rule<char const*, utf8_string_type()> r1 = lexeme[*char_];
67 
68         BOOST_TEST(test_attr("foo", r1, ut) &&
69             ut.which() == utree_type::string_type && check(ut, "\"foo\""));
70         ut.clear();
71 
72         rule<char const*, utf8_symbol_type()> r2 = lexeme[*char_];
73 
74         BOOST_TEST(test_attr("xyz", r2, ut) &&
75             ut.which() == utree_type::symbol_type && check(ut, "xyz"));
76     }
77 
78     // single character parsers
79     {
80         utree ut;
81 
82         // this rule returns a utree string
83         rule<char const*, utree()> r1 = char_("abc");
84 
85         // this rule forces a utree list to be returned
86         rule<char const*, utree::list_type()> r2 = char_("abc");
87 
88         BOOST_TEST(test_attr("a", r1, ut) &&
89             ut.which() == utree_type::string_type && check(ut, "\"a\""));
90         ut.clear();
91         BOOST_TEST(test_attr("a", r2, ut) &&
92             ut.which() == utree_type::list_type && check(ut, "( \"a\" )"));
93     }
94 
95     // sequences
96     {
97         using boost::spirit::qi::as_string;
98 
99         utree ut;
100         BOOST_TEST(test_attr("xy", char_ >> char_, ut) &&
101             ut.which() == utree_type::list_type && check(ut, "( \"x\" \"y\" )"));
102         ut.clear();
103         BOOST_TEST(test_attr("123 456", int_ >> int_, ut, space) &&
104             ut.which() == utree_type::list_type && check(ut, "( 123 456 )"));
105         ut.clear();
106         BOOST_TEST(test_attr("1.23 4.56", double_ >> double_, ut, space) &&
107             ut.which() == utree_type::list_type && check(ut, "( 1.23 4.56 )"));
108         ut.clear();
109         BOOST_TEST(test_attr("1.2ab", double_ >> *char_, ut) &&
110             ut.which() == utree_type::list_type && check(ut, "( 1.2 \"a\" \"b\" )"));
111         ut.clear();
112         BOOST_TEST(test_attr("ab1.2", *~digit >> double_, ut) &&
113             ut.which() == utree_type::list_type && check(ut, "( \"a\" \"b\" 1.2 )"));
114 
115         // forces a utree list
116         rule<char const*, utree::list_type()> r1 = double_;
117 
118         ut.clear();
119         BOOST_TEST(test_attr("1.2ab", r1 >> *char_, ut) &&
120             ut.which() == utree_type::list_type && check(ut, "( ( 1.2 ) \"a\" \"b\" )"));
121         ut.clear();
122         BOOST_TEST(test_attr("ab1.2", *~digit >> r1, ut) &&
123             ut.which() == utree_type::list_type && check(ut, "( \"a\" \"b\" ( 1.2 ) )"));
124         ut.clear();
125 
126         // implicitly a utree list, because of sequence attribute rules
127         rule<char const*, utree()> r2 = int_ >> char_("!") >> double_;
128 
129         BOOST_TEST(test_attr("17!3.14", r2, ut) &&
130             ut.which() == utree_type::list_type && check(ut, "( 17 \"!\" 3.14 )"));
131         ut.clear();
132 
133         rule<char const*, utree()> r3 = double_ >> as_string[string("foo")] >> int_;
134 
135         BOOST_TEST(test_attr("0.5foo5", r3, ut) &&
136             ut.which() == utree_type::list_type && check(ut, "( 0.5 \"foo\" 5 )"));
137     }
138 
139     {
140         utree ut;
141 
142         rule<char const*, utree()> r1 = char_;
143         rule<char const*, utree::list_type()> r2 = double_;
144         rule<char const*, utree::list_type()> r3 = char_;
145 
146         BOOST_TEST(test_attr("a25.5b", r1 >> r2 >> r3, ut));
147         BOOST_TEST(ut.which() == utree_type::list_type);
148         BOOST_TEST(check(ut, "( \"a\" ( 25.5 ) ( \"b\" ) )"));
149         ut.clear();
150 
151         BOOST_TEST(test_attr("a25.5b", r3 >> r2 >> r1, ut));
152         BOOST_TEST(ut.which() == utree_type::list_type);
153         BOOST_TEST(check(ut, "( ( \"a\" ) ( 25.5 ) \"b\" )"));
154         ut.clear();
155 
156         BOOST_TEST(test_attr("a25.5b", char_ >> r2 >> r3, ut));
157         BOOST_TEST(ut.which() == utree_type::list_type);
158         BOOST_TEST(check(ut, "( \"a\" ( 25.5 ) ( \"b\" ) )"));
159         ut.clear();
160 
161         BOOST_TEST(test_attr("a25.5b", r3 >> r2 >> char_, ut));
162         BOOST_TEST(ut.which() == utree_type::list_type);
163         BOOST_TEST(check(ut, "( ( \"a\" ) ( 25.5 ) \"b\" )"));
164         ut.clear();
165 
166 #if defined(BOOST_CLANG)
167 #pragma clang diagnostic push
168 #pragma clang diagnostic ignored "-Woverloaded-shift-op-parentheses"
169 #endif
170 
171         BOOST_TEST(test_attr("a25.5b", r1 > r2 >> r3, ut));
172         BOOST_TEST(ut.which() == utree_type::list_type);
173         BOOST_TEST(check(ut, "( \"a\" ( 25.5 ) ( \"b\" ) )"));
174         ut.clear();
175 
176         BOOST_TEST(test_attr("a25.5b", r3 >> r2 > r1, ut));
177         BOOST_TEST(ut.which() == utree_type::list_type);
178         BOOST_TEST(check(ut, "( ( \"a\" ) ( 25.5 ) \"b\" )"));
179         ut.clear();
180 
181         BOOST_TEST(test_attr("a25.5b", char_ > r2 >> r3, ut));
182         BOOST_TEST(ut.which() == utree_type::list_type);
183         BOOST_TEST(check(ut, "( \"a\" ( 25.5 ) ( \"b\" ) )"));
184         ut.clear();
185 
186         BOOST_TEST(test_attr("a25.5b", r3 >> r2 > char_, ut));
187         BOOST_TEST(ut.which() == utree_type::list_type);
188         BOOST_TEST(check(ut, "( ( \"a\" ) ( 25.5 ) \"b\" )"));
189 
190 #if defined(BOOST_CLANG)
191 #pragma clang diagnostic pop
192 #endif
193     }
194 
195     return boost::report_errors();
196 }
197 
198