1 | #include <boost/spirit/include/qi.hpp>
|
---|
2 | #include <boost/spirit/include/phoenix_operator.hpp>
|
---|
3 |
|
---|
4 | namespace qi = boost::spirit::qi;
|
---|
5 |
|
---|
6 | template <typename P, typename T>
|
---|
7 | void 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. */
|
---|
20 | struct body_temp
|
---|
21 | {
|
---|
22 | float t;
|
---|
23 | };
|
---|
24 |
|
---|
25 | bool no_chance(false);
|
---|
26 |
|
---|
27 | namespace 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 |
|
---|
50 | int 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 | }
|
---|