【问题标题】:Boost::spirit::qi - How do I build a parse rule that sets a property?Boost::spirit::qi - 如何构建一个设置属性的解析规则?
【发布时间】:2017-12-06 19:44:46
【问题描述】:

我想建立一个规则,从解析的行中接收一些参数,然后将一些参数设置为常量。那可能吗?下面是一个(无效)示例来说明我正在尝试做的事情。我想我在这里错误地使用了_r1,但我不确定如何做正确的事情。假设我不想在将 r 发送到解析器之前对其进行修改。

#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/qi_plus.hpp>
#include <boost/spirit/include/qi_sequence.hpp>
#include <boost/spirit/include/qi_string.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/phoenix_object.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/fusion/adapted/struct/adapt_struct.hpp>
#include <boost/phoenix/bind/bind_function.hpp>
#include <string>

using namespace boost::spirit::qi;
struct Sample
{
    int a;
    int b;
};
BOOST_FUSION_ADAPT_STRUCT(Sample, a , b)

const rule<std::string::const_iterator, Sample()> AnythingAndOne = int_ >> eps[_r1.b = 1] >> eoi;


int main()
{
    std::string z("3");
    Sample r;
    parse(z.begin(), z.end(), AnythingAndOne, r);
    return 0;
}

【问题讨论】:

  • _r1inherited attribute 的占位符。您没有声明任何继承的属性。你在这里是什么意思?
  • 我的意思是解析一个 int,然后将另一个 int 设置为一个常量值(在本例中为一个)。所以我会从“3”取回 Sample a = {3,1}。
  • 您可以通过在规则中的元组中添加一个固定的 int 来做到这一点吗?
  • 当然。我会简单很多。谢谢澄清。几分钟后发布
  • 谢谢你,你真的帮了大忙。

标签: c++11 boost boost-spirit boost-spirit-qi


【解决方案1】:

再次,参考Boost Spirit: "Semantic actions are evil"?,我会避免语义操作。

使用qi::attr可以直接合成特定的属性值:

Live On Coliru

#include <boost/spirit/include/qi.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/fusion/include/io.hpp>

struct Sample {
    int a;
    int b;
};
BOOST_FUSION_ADAPT_STRUCT(Sample, a , b)

namespace qi = boost::spirit::qi;

int main()
{
    std::string const z("3");
    Sample r;
    qi::rule<std::string::const_iterator, Sample()> AnythingAndOne
         = qi::int_ >> qi::attr(1) >> qi::eoi;

    if (parse(z.begin(), z.end(), AnythingAndOne, r))
        std::cout << "Parsed: " << boost::fusion::as_vector(r) << "\n";
    else
        std::cout << "Parse failed\n";
}

打印

Parsed: (3 1)

【讨论】:

  • 完美。这解决了我的问题。我不希望使用它,但是我知道如何,您如何使用语义操作来做到这一点?
  • (很明显,非语义动作版本将进入产品代码)
  • 为了好玩,举个更复杂的例子:showing how you can achieve quite complex logic without actions。对于语义动作,常规占位符qi::_1 指的是主题解析器,qi::val 指的是声明的属性,所有动作都需要延迟演员,例如this equivalent demo using semantic actions
  • 哦,是的,不,我很清楚您可以在解析器中使用 ors 玩的游戏。这就是为什么我喜欢这种东西。
  • OHHHHH 使用命名空间现在我明白了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-11
  • 1970-01-01
  • 1970-01-01
  • 2011-01-26
  • 1970-01-01
相关资源
最近更新 更多