【问题标题】:Handling exception in semantic actions处理语义动作中的异常
【发布时间】:2013-10-28 08:34:15
【问题描述】:

考虑以下解析器:

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;
};

我想捕获test::from_string 可能抛出的异常,并在异常时使匹配失败。我找不到直接的方法来做到这一点,所以我试图使用一个可以明确接受上下文的“适配器”函数。但是如何访问上下文以及如何将这样的动作附加到语法上呢?请查看代码中的问题:

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")];
}

【问题讨论】:

  • 正如您在this excellent answer 中看到的,您需要使用boost::fusion::at_c&lt;0&gt;(context.attributes) = t;。我认为应该可行但我从未测试过的另一种选择是使用query = id[phx::try_[_val = phx::bind(&amp;test::from_string, qi::_1)].catch_all[_pass=false] ];
  • phx::try_[].catch_all[] 替代方案似乎仅适用于 phoenix v2。
  • @cv_and_he 也许......我们应该考虑在这里提交错误。我不明白为什么它不起作用,真的
  • @sehe 如果您将try_catch 放在一个序列中,例如添加std::cout &lt;&lt; phx::val("testing...") 或诸如qi::_1=qi::_1it compiles 之类的傻事。我知道的不够自信,但我认为处理语义动作的代码隐含地期望凤凰表达式的一些要求,而 try_catch 与它们不匹配。
  • @cv_and_he 干得好,我在我的答案中添加了一个解决方法。你愿意在名单上报告这个吗?我认为这可能只是 try_catch 表达式模板缺少的“语句”特征

标签: boost boost-spirit boost-spirit-qi


【解决方案1】:

如评论者所说,使用

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

Live on Coliru

即使使用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
        ];

【讨论】:

  • 我已经迁移到 V3,结果发现上面的解决方法不起作用:语义操作根本没有被调用。
  • @IgorR。您是否忘记包含相关标题?听起来像是标准逗号运算符行为的一个案例(又名 逗号运算符
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-04
  • 1970-01-01
  • 1970-01-01
  • 2020-06-26
  • 1970-01-01
相关资源
最近更新 更多