You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Boost Spirit X3如何条件化解析向量并处理可选后缀?

需求与正确实现

需求说明

要解析格式为(int ":" int )*的字符串,生成整数向量,规则如下:

  • 配对的第二个值是奇数时,把第一个值加入结果向量
  • 第二个值是偶数时,跳过该配对
  • : int部分可选,没写的话默认第二个值为1

你之前的错误尝试

尝试1:基础配对与向量生成(逻辑错误)

auto pair_ = x3::rule<class pair_, int>() 
           = x3::int_ >> ":" >> x3::int_;
auto vec   = x3::rule<class vec, std::vector<int>>() 
           = (*pair_[
               ([](auto &c){
                   if(x3::_attr(c).second % 2) 
                       x3::_val(c).push_back(x3::_attr(c).first);
               })
             ]);

问题:pair_规则的属性声明成了int,但实际是成对的整数,类型不匹配;同时语义动作的写法不符合X3规则,无法正确获取配对的两个值。

尝试2:处理可选后缀(类型不匹配)

auto pair_ = x3::rule<class pair_, int>() 
           = x3::int_ >> ((":" >> x3::int_) | x3::attr(1));

问题:同样是属性类型错误,x3::int_ >> (xxx | attr(1))生成的是std::pair<int, int>类型的属性,但规则声明成了int,导致解析时属性绑定失败。

示例输入输出

输入:10 11:0 12:3
预期输出:[10, 12]

正确代码实现

#include <boost/spirit/home/x3.hpp>
#include <vector>
#include <utility>
#include <iostream>

namespace x3 = boost::spirit::x3;

int main() {
    // 定义配对规则,属性为成对整数,处理可选的": int"(默认值1)
    auto pair_rule = x3::rule<class pair_tag, std::pair<int, int>>{} 
                   = x3::int_ >> ((":" >> x3::int_) | x3::attr(1));

    // 定义向量生成规则:遍历所有配对,筛选符合条件的加入结果
    auto vec_rule = x3::rule<class vec_tag, std::vector<int>>{} 
                  = *x3::omit[
                      pair_rule([](auto& ctx) {
                          const auto& pair = x3::_attr(ctx);
                          // 第二个值为奇数时,将第一个值加入结果
                          if (pair.second % 2 != 0) {
                              x3::_val(ctx).push_back(pair.first);
                          }
                      })
                    ];

    // 测试输入解析
    std::string input = "10 11:0 12:3";
    std::vector<int> result;
    auto iter = input.begin();
    const auto end = input.end();

    // 使用phrase_parse处理输入中的空白符
    bool parse_success = x3::phrase_parse(iter, end, vec_rule, x3::space, result);

    // 输出结果
    if (parse_success && iter == end) {
        std::cout << "[";
        for (size_t i = 0; i < result.size(); ++i) {
            if (i != 0) std::cout << ", ";
            std::cout << result[i];
        }
        std::cout << "]\n";
    } else {
        std::cout << "解析失败,剩余未解析内容:" << std::string(iter, end) << "\n";
    }

    return 0;
}

核心修正点

  1. 属性类型匹配:把pair_rule的属性明确声明为std::pair<int, int>,和规则生成的属性类型一致,避免绑定错误。
  2. 语义动作逻辑:在遍历每个配对时,直接获取配对的两个值,判断第二个值是否为奇数,符合条件就将第一个值加入结果向量。
  3. 空白处理:用phrase_parse配合x3::space,自动跳过输入中的空格分隔符,符合示例的输入格式。

内容的提问来源于stack exchange,提问作者Bubaya

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 16:40:33