• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
8 #include <boost/detail/lightweight_test.hpp>
9 #include <boost/spirit/include/qi_operator.hpp>
10 #include <boost/spirit/include/qi_char.hpp>
11 #include <boost/spirit/include/qi_string.hpp>
12 #include <boost/spirit/include/qi_numeric.hpp>
13 #include <boost/spirit/include/qi_auxiliary.hpp>
14 #include <boost/spirit/include/qi_directive.hpp>
15 #include <boost/spirit/include/qi_nonterminal.hpp>
16 #include <boost/spirit/include/qi_action.hpp>
17 #include <boost/spirit/include/phoenix_core.hpp>
18 #include <boost/spirit/include/phoenix_operator.hpp>
19 #include <boost/spirit/include/phoenix_object.hpp>
20 #include <boost/spirit/include/phoenix_bind.hpp>
21 #include <boost/fusion/include/std_pair.hpp>
22 
23 #include <string>
24 #include <cstring>
25 #include <iostream>
26 #include "test.hpp"
27 
28 int
main()29 main()
30 {
31     using spirit_test::test_attr;
32     using spirit_test::test;
33 
34     using namespace boost::spirit::ascii;
35     using namespace boost::spirit::qi::labels;
36     using boost::spirit::qi::locals;
37     using boost::spirit::qi::rule;
38     using boost::spirit::qi::int_;
39     using boost::spirit::qi::uint_;
40     using boost::spirit::qi::fail;
41     using boost::spirit::qi::on_error;
42     using boost::spirit::qi::debug;
43     using boost::spirit::qi::lit;
44 
45     namespace phx = boost::phoenix;
46 
47 
48     { // show that ra = rb and ra %= rb works as expected
49         rule<char const*, int() > ra, rb;
50         int attr;
51 
52         ra %= int_;
53         BOOST_TEST(test_attr("123", ra, attr));
54         BOOST_TEST(attr == 123);
55 
56         rb %= ra;
57         BOOST_TEST(test_attr("123", rb, attr));
58         BOOST_TEST(attr == 123);
59 
60         rb = ra;
61         BOOST_TEST(test_attr("123", rb, attr));
62         BOOST_TEST(attr == 123);
63     }
64 
65     { // std::string as container attribute with auto rules
66 
67         rule<char const*, std::string()> text;
68         text %= +(!char_(')') >> !char_('>') >> char_);
69         std::string attr;
70         BOOST_TEST(test_attr("x", text, attr));
71         BOOST_TEST(attr == "x");
72 
73         // test deduced auto rule behavior
74         text = +(!char_(')') >> !char_('>') >> char_);
75         attr.clear();
76         BOOST_TEST(test_attr("x", text, attr));
77         BOOST_TEST(attr == "x");
78     }
79 
80     { // error handling
81 
82         using namespace boost::spirit::ascii;
83         using boost::phoenix::construct;
84         using boost::phoenix::bind;
85 
86         rule<char const*> r;
87         r = '(' > int_ > ',' > int_ > ')';
88 
89         on_error<fail>
90         (
91             r, std::cout
92                 << phx::val("Error! Expecting: ")
93                 << _4
94                 << phx::val(", got: \"")
95                 << construct<std::string>(_3, _2)
96                 << phx::val("\"")
97                 << std::endl
98         );
99 
100         BOOST_TEST(test("(123,456)", r));
101         BOOST_TEST(!test("(abc,def)", r));
102         BOOST_TEST(!test("(123,456]", r));
103         BOOST_TEST(!test("(123;456)", r));
104         BOOST_TEST(!test("[123,456]", r));
105     }
106 
107     { // specifying the encoding
108 
109         typedef boost::spirit::char_encoding::iso8859_1 iso8859_1;
110         rule<char const*, iso8859_1> r;
111 
112         r = no_case['\xE1'];
113         BOOST_TEST(test("\xC1", r));
114         r = no_case[char_('\xE1')];
115         BOOST_TEST(test("\xC1", r));
116 
117         r = no_case[char_("\xE5-\xEF")];
118         BOOST_TEST(test("\xC9", r));
119         BOOST_TEST(!test("\xFF", r));
120 
121         r = no_case["\xE1\xC1"];
122         BOOST_TEST(test("\xC1\xE1", r));
123         r = no_case[lit("\xE1\xC1")];
124         BOOST_TEST(test("\xC1\xE1", r));
125     }
126 
127     {
128         typedef boost::variant<double, int> v_type;
129         rule<const char*, v_type()> r1 = int_;
130         v_type v;
131         BOOST_TEST(test_attr("1", r1, v) && v.which() == 1 &&
132             boost::get<int>(v) == 1);
133 
134         typedef boost::optional<int> ov_type;
135         rule<const char*, ov_type()> r2 = int_;
136         ov_type ov;
137         BOOST_TEST(test_attr("1", r2, ov) && ov && boost::get<int>(ov) == 1);
138     }
139 
140     // test handling of single element fusion sequences
141     {
142         using boost::fusion::vector;
143         using boost::fusion::at_c;
144         rule<const char*, vector<int>()> r = int_;
145 
146         vector<int> v(0);
147         BOOST_TEST(test_attr("1", r, v) && at_c<0>(v) == 1);
148     }
149 
150     {
151         using boost::fusion::vector;
152         using boost::fusion::at_c;
153         rule<const char*, vector<unsigned int>()> r = uint_;
154 
155         vector<unsigned int> v(0);
156         BOOST_TEST(test_attr("1", r, v) && at_c<0>(v) == 1);
157     }
158 
159     ///////////////////////////////////////////////////////////////////////////
160     {
161         using boost::spirit::qi::int_;
162         using boost::spirit::qi::_1;
163         using boost::spirit::qi::_val;
164         using boost::spirit::qi::space;
165         using boost::spirit::qi::space_type;
166 
167         rule<const char*, int()> r1 = int_;
168         rule<const char*, int(), space_type> r2 = int_;
169 
170         int i = 0;
171         int j = 0;
172         BOOST_TEST(test_attr("456", r1[_val = _1], i) && i == 456);
173         BOOST_TEST(test_attr("   456", r2[_val = _1], j, space) && j == 456);
174     }
175 
176 #if 0 // disabling test (can't fix)
177     {
178         using boost::spirit::qi::lexeme;
179         using boost::spirit::qi::alnum;
180 
181         rule<const char*, std::string()> literal_;
182         literal_ = lexeme[ +(alnum | '_') ];
183 
184         std::string attr;
185         BOOST_TEST(test_attr("foo_bar", literal_, attr) && attr == "foo_bar");
186         std::cout << attr << std::endl;
187     }
188 #endif
189 
190     return boost::report_errors();
191 }
192 
193