Consider the following parser:

class test
{
public:
  static test from_string(const string &str); //throws!
};

template <typename Iterator = string::const_iterator>
struct test_parser : grammar<Iterator, test(), blank_type>
{
  test_parser() : test_parser::base_type(query)
  {
    query = id[_val = phx::bind(&test::from_string, qi::_1)];
    id = lexeme[*char_("a-zA-Z_0-9")];
  }
  rule<Iterator, test(), blank_type> query;
  rule<Iterator, string(), blank_type> id;
};

I'd like to catch exceptions that test::from_string might throw and to fail the match on exception. I couldn't find direct way to do this, so I'm trying to use an "adapter" function that would accept the context explicitly. But how to access the context and how to attach such an action to the grammar? Please, see the questions within the code:

template<class Context>
void match_test(const string &attr, Context &context, bool &mFlag)
{
  try
  {
    test t = test::from_string(attr);
    // how do I access the context to put t into _val?
  }
  catch(...)
  {
    mFlag = false;
  }
}

//...
test_parser() : test_parser::base_type(query)
{
  query = id[?match_test<?>? /*how to instantiate and use the above semantic action?*/];
  id = lexeme[*char_("a-zA-Z_0-9")];
}
有帮助吗?

解决方案

Like the commenter said, use

    query = id[
            phx::try_ [
                qi::_val = phx::bind(&test::from_string, qi::_1)
            ].catch_all [ 
                qi::_pass = false 
            ]
        ];

See it Live on Coliru

A version that compiles even with BOOST_SPIRIT_USE_PHOENIX_V3: Live on Coliru

    query = id[
            phx::try_ [
                qi::_val = phx::bind(&test::from_string, qi::_1)
            ].catch_all [ 
                qi::_pass = false 
            ],
            qi::_pass = qi::_pass // to appease the spirit expression compilation gods
        ];
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top