c++ - Boost Spirit Qi Custom Syntesized Attribute(通过语义操作设置结构属性的特定成员)

标签 c++ attributes boost-spirit boost-spirit-qi synthesize

假设我有一个我想用灵气解析成的结构,它是这样定义的:

struct data_
{
    bool export;
    std::wstring name;

    data_() : export(false) {}
};

此外,假设结构已适应这样的融合:

BOOST_FUSION_ADAPT_STRUCT(
    data_,
    (bool, export)
    (std::wstring, name)
)

关联的规则是:

qi::rule<Iterator, data_(), skipper<Iterator> > rule_data;

rule_data = -lexeme["SpecialText" >> !(alnum | '_')] [ boost::phoenix::at_c<0> = true ] // If this string is found, , set "export" to true
            > lexeme["Name" >> !(alnum | '_')] // this is supposed to go into the "name" member

到目前为止,这个编译非常好。但是,“name”现在仍然是空的!

所以本质上,我要问的是:鉴于“SpecialText”在“Name”之前,我将如何正确合成一个用于“export”的 bool 属性,而不是一个字符串?

编辑 在为此烦恼之后,我偶然发现了“matches[]”解析器,它似乎可以满足我的要求。

尽管如此,问题仍然存在于一般形式,例如,如果我想返回某个字符串或其他数据类型而不是bool。 本质上,如何通过语义操作设置结构属性的特定成员。

最佳答案

如何设置结构成员。

选项 1(phx::bind)

给定一个结构S

struct S
{
    int         field1;
    std::string field2;
    int         target_field;
    bool        field3;
};

您可以像这样分配给一个字段(例如 target_field):

rule<It, S()> p = int_ [ phx::bind(&S::target_field, _val) = _1 ];

现在,您可以通过执行以下操作使 bind 更具可读性:

auto target_field_ = phx::bind(&S::target_field, _val);

p = int_ [ target_field_ = _1 ];

概念验证: live on Coliru

#include "boost/spirit/include/qi.hpp"
#include "boost/spirit/include/phoenix.hpp"

namespace qi  = boost::spirit::qi;
namespace phx = boost::phoenix;
typedef std::string::const_iterator It;

struct S
{
    int         field1;
    std::string field2;
    int         target_field;
    bool        field3;
};

int main()
{
    const std::string input("42");
    It f(begin(input)), l(end(input));

    S instance;

    using namespace qi;
    rule<It, S()> p = int_ [ phx::bind(&S::target_field, _val) = _1 ];

    // or, alternatively:
    auto target_field_ = phx::bind(&S::target_field, _val);
    p = int_ [ target_field_ = _1 ];

    if (parse(f, l, p, instance))
        std::cout << "Parsed: " << instance.target_field;
}

选项 2(融合序列)

您可以使用适应将结构视为融合序列:

#include "boost/fusion/adapted/struct.hpp"

BOOST_FUSION_ADAPT_STRUCT(S, (int, field1)(std::string, field2)(int, target_field)(bool, field3))

现在您可以在语义操作中对这些序列使用 phoenix lazy 函数:

rule<It, S()> p = int_ [ phx::at_c<2>(_val) = _1 ];

我不喜欢这种风格(因为它会将一个富有表现力的结构“降级”为......各种元组),但它可能会派上用场。 <强> Live on Coliru

关于c++ - Boost Spirit Qi Custom Syntesized Attribute(通过语义操作设置结构属性的特定成员),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18602818/

相关文章:

c++ - vector 对第一个元素的范围

c++ - C++中全局与本地包含文件的顺序如何

c++ - 非急切克林星 boost 灵气

c++ - 使用 Boost Spirit 和 Fusion 以关联方式解析结构

C++ 将 SQLVARCHAR 转换为字符串

c++ - 如何删除冗余输出

C#使用数据源隐藏datagridview中的属性

python - 为什么我必须将 "from module import"与 python 中的电子邮件模块一起使用?

python - python'function'对象没有属性'GzipFile'

c++ - 为什么 nvcc 无法使用 boost::spirit 编译 CUDA 文件?