Ticket #9260: phx_3_crash_reproducer.cpp

File phx_3_crash_reproducer.cpp, 2.9 KB (added by stephan.menzel@…, 9 years ago)

reproducer

Line 
1#define BOOST_SPIRIT_USE_PHOENIX_V3
2#include <boost/fusion/adapted.hpp>
3#include <boost/spirit/include/qi.hpp>
4#include <boost/spirit/include/phoenix.hpp>
5
6namespace qi = boost::spirit::qi;
7namespace phx = boost::phoenix;
8
9// an enum defining possible operators
10typedef enum builtin_operator_tag {
11 OPERATOR_LT = 0,
12 OPERATOR_LTE,
13 OPERATOR_GT,
14 OPERATOR_GTE,
15 OPERATOR_EQ,
16 OPERATOR_NEQ
17} builtin_operator_number;
18
19// then the using statement in a rule with lots of local variables
20template <typename It, typename Skipper = qi::space_type>
21struct parser : qi::grammar<It, bool(), Skipper> {
22
23 parser() : parser::base_type(start) {
24
25 using namespace qi;
26
27 cmp_operators.add
28 (">", OPERATOR_GT )
29 (">=", OPERATOR_GTE)
30 ("=>", OPERATOR_GTE)
31 ("<", OPERATOR_LT )
32 ("=<", OPERATOR_LTE)
33 ("<=", OPERATOR_LTE)
34 ("==", OPERATOR_EQ )
35 ("!=", OPERATOR_NEQ);
36
37 condition = ( double_ >> lexeme [ cmp_operators ] >> double_ )
38 [
39 phx::switch_(_2)[
40 phx::case_<OPERATOR_GT> (_val = (_1 > _3)),
41 phx::case_<OPERATOR_GTE>(_val = (_1 >= _3)),
42 phx::case_<OPERATOR_LT> (_val = (_1 < _3)),
43 phx::case_<OPERATOR_LTE>(_val = (_1 <= _3)),
44 phx::case_<OPERATOR_EQ> (_val = (_1 == _3)),
45 phx::case_<OPERATOR_NEQ>(_val = (_1 != _3)),
46 phx::default_(_val = false)
47 ]
48 ];
49
50 enclosing %= condition[_a = _1] >> double_[_val = _a]; // works
51// enclosing %= condition[_a = _1] >> double_[_c = _1, _val = _a]; // crashes
52
53 start %= enclosing;
54
55 BOOST_SPIRIT_DEBUG_NODE(start);
56 }
57
58private:
59 qi::rule<It, bool(), Skipper> start;
60 qi::rule<It, bool(), Skipper> condition;
61 qi::rule<It, bool(), qi::locals<bool, unsigned int, double, std::string>, Skipper> enclosing;
62 qi::symbols<char, unsigned int> cmp_operators;
63};
64
65bool doParse(const std::string& input)
66{
67 typedef std::string::const_iterator It;
68
69 std::string::const_iterator begin = input.begin();
70 std::string::const_iterator end = input.end();
71
72 parser<It, qi::space_type> p;
73 bool data;
74
75 try
76 {
77 bool ok = qi::phrase_parse(begin, end, p, qi::space, data);
78 if (ok)
79 {
80 std::cout << "parse success\n";
81 std::cout << "data: " << std::boolalpha << data << "\n";
82 }
83 else std::cerr << "parse failed: '" << std::string(begin, end) << "'\n";
84
85 if (begin!=end) std::cerr << "trailing unparsed: '" << std::string(begin, end) << "'\n";
86 return ok;
87 } catch(const qi::expectation_failure<It>& e)
88 {
89 std::string frag(e.first, e.last);
90 std::cerr << e.what() << "'" << frag << "'\n";
91 }
92
93 return false;
94}
95
96
97int main()
98{
99 bool ok = doParse("2.0001 <= 2 1");
100 ok = doParse("2.0001 =< 2 2") && ok;
101 ok = doParse("2.0001 >= 2 3") && ok;
102 ok = doParse("2.0001 => 2 4") && ok;
103 return ok? 0 : 255;
104}
105
106
107
108