Question

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")];
}
Was it helpful?

Solution

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
        ];
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top