Ticket #6050: test_attr.cpp

File test_attr.cpp, 2.4 KB (added by oakad@…, 11 years ago)

A short example demonstrating a basic use case for the propoesed change.

Line 
1#include <boost/spirit/include/qi.hpp>
2#include <boost/spirit/include/phoenix_operator.hpp>
3
4namespace qi = boost::spirit::qi;
5
6template <typename P, typename T>
7void test_parser_attr(char const* input, P const& p, T& attr, bool full_match = true)
8{
9 using boost::spirit::qi::parse;
10
11 char const* f(input);
12 char const* l(f + strlen(f));
13 if (parse(f, l, p, attr) && (!full_match || (f == l)))
14 std::cout << "ok" << std::endl;
15 else
16 std::cout << "fail" << std::endl;
17}
18
19/* This test structure represents a primitive range limited type. */
20struct body_temp
21{
22 float t;
23};
24
25bool no_chance(false);
26
27namespace boost { namespace spirit { namespace traits
28{
29 template <>
30 struct transform_attribute<body_temp, float, qi::domain>
31 {
32 typedef float type;
33 static float pre(body_temp t) { return t.t; }
34 /* if parsed attribute is within desired range, than assign it,
35 * otherwise report failure.
36 */
37 static bool post(body_temp& t, float const &attr)
38 {
39 if (attr > 30.0 && attr < 45.0) {
40 t.t = attr;
41 return true;
42 }
43 else
44 return false;
45 }
46 static void fail(body_temp &t) { }
47 };
48}}}
49
50int main(int argc, char **argv)
51{
52 namespace qi = boost::spirit::qi;
53 using qi::float_;
54 using qi::omit;
55 using qi::rule;
56 using qi::attr_cast;
57 using boost::phoenix::ref;
58
59 body_temp d1 = { 36.6 }, d2 = { 36.6 };
60
61 rule<char const *, body_temp()> r;
62
63 /* Adapt qi::float_ parser to struct body_temp which represents a range
64 * limited numeric type. If range can not be accomodated, per conversion
65 * defined, the first alternative will fail, and second will be invoked,
66 * to set the error flag.
67 */
68 r %= attr_cast<body_temp>(float_) | omit[float_[ref(no_chance) = true]];
69
70 /* Supplied value is within range and will be parsed as appropriate
71 * range limited float.
72 */
73 test_parser_attr("40.0", r, d1);
74 std::cout << "parsed temp " << d1.t << " error flag " << no_chance
75 << std::endl;
76
77 no_chance = false;
78 /* Supplied value is not within allowed range, the parser will take the
79 * alternative choice to set the error flag.
80 */
81 test_parser_attr("20.0", r, d2);
82 std::cout << "parsed temp " << d2.t << " error flag " << no_chance
83 << std::endl;
84
85 return 0;
86}