#define BOOST_SPIRIT_USE_PHOENIX_V3 #include #include #include namespace qi = boost::spirit::qi; namespace phx = boost::phoenix; // an enum defining possible operators typedef enum builtin_operator_tag { OPERATOR_LT = 0, OPERATOR_LTE, OPERATOR_GT, OPERATOR_GTE, OPERATOR_EQ, OPERATOR_NEQ } builtin_operator_number; // then the using statement in a rule with lots of local variables template struct parser : qi::grammar { parser() : parser::base_type(start) { using namespace qi; cmp_operators.add (">", OPERATOR_GT ) (">=", OPERATOR_GTE) ("=>", OPERATOR_GTE) ("<", OPERATOR_LT ) ("=<", OPERATOR_LTE) ("<=", OPERATOR_LTE) ("==", OPERATOR_EQ ) ("!=", OPERATOR_NEQ); condition = ( double_ >> lexeme [ cmp_operators ] >> double_ ) [ phx::switch_(_2)[ phx::case_ (_val = (_1 > _3)), phx::case_(_val = (_1 >= _3)), phx::case_ (_val = (_1 < _3)), phx::case_(_val = (_1 <= _3)), phx::case_ (_val = (_1 == _3)), phx::case_(_val = (_1 != _3)), phx::default_(_val = false) ] ]; enclosing %= condition[_a = _1] >> double_[_val = _a]; // works // enclosing %= condition[_a = _1] >> double_[_c = _1, _val = _a]; // crashes start %= enclosing; BOOST_SPIRIT_DEBUG_NODE(start); } private: qi::rule start; qi::rule condition; qi::rule, Skipper> enclosing; qi::symbols cmp_operators; }; bool doParse(const std::string& input) { typedef std::string::const_iterator It; std::string::const_iterator begin = input.begin(); std::string::const_iterator end = input.end(); parser p; bool data; try { bool ok = qi::phrase_parse(begin, end, p, qi::space, data); if (ok) { std::cout << "parse success\n"; std::cout << "data: " << std::boolalpha << data << "\n"; } else std::cerr << "parse failed: '" << std::string(begin, end) << "'\n"; if (begin!=end) std::cerr << "trailing unparsed: '" << std::string(begin, end) << "'\n"; return ok; } catch(const qi::expectation_failure& e) { std::string frag(e.first, e.last); std::cerr << e.what() << "'" << frag << "'\n"; } return false; } int main() { bool ok = doParse("2.0001 <= 2 1"); ok = doParse("2.0001 =< 2 2") && ok; ok = doParse("2.0001 >= 2 3") && ok; ok = doParse("2.0001 => 2 4") && ok; return ok? 0 : 255; }