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

使用长语法序列时Boost Spirit Qi解析出现编译错误

问题分析与解决方案

问题背景

需要解析以下格式的字符串:

CONNECT clk sda 1.020::1.030 0.200::0.00
CONNECT da doai 0.100::0.050 0.040::0.300

解析后通过回调函数传递令牌,但使用完整语法序列时触发编译错误,缩短语法序列(仅解析单个PIN和单个值)时编译正常。

无编译错误的短语法示例

解析目标字符串:

CONNECT clk 0.200::0.00
CONNECT da 0.040::0.300

对应语法代码:

auto connect_parser = qi::copy(qi::lit("CONNECT") >> qi::space >> pin_parser[boost::phoenix::bind(callback, "PIN1", qi::_1)] >> qi::space
                                >> val_parser >> qi::space
                               );

触发编译错误的长语法代码

void Parse(string const& input)
{
    string::const_iterator begin = input.begin(), end = input.end();

    auto pin_parser    = qi::copy(+(qi::char_("a-z")));
    auto val_parser    = qi::copy(qi::float_ >> ':' >> *(qi::float_) >> ':' >> qi::float_);

    auto connect_parser = qi::copy( 
                                qi::lit("CONNECT") >> qi::space >> pin_parser[boost::phoenix::bind(callback, "PIN1", qi::_1)] >> qi::space
                                >> pin_parser[boost::phoenix::bind(callback, "PIN2", qi::_1)] >> qi::space
                                >> val_parser >> qi::space >> val_parser >> qi::space
                               );

    bool is_succ = qi::parse(begin, end, +connect_parser);
    std::cout << "Succ " << is_succ << std::endl;
}

编译错误信息

spirit::tag::space, boost::spirit::char_encoding::standard> >, 0l> >, 2l>&>, 1l>]'
PASDFParser.cpp:81:62:   required from here
/calypto/tools/install/boost/boost_1_59_0/rhel7/m64/include/boost/fusion/container/vector/convert.hpp:27:13: error: invalid use of incomplete type 'struct boost::fusion::detail::barrier::as_vector<13>'
             type;
             ^
In file included from /calypto/tools/install/boost/boost_1_59_0/rhel7/m64/include/boost/fusion/container/vector/detail/as_vector.hpp:15:0,
                 from /calypto/tools/install/boost/boost_1_59_0/rhel7/m64/include/boost/fusion/container/vector/convert.hpp:11,
                 from /calypto/tools/install/boost/boost_1_59_0/rhel7/m64/include/boost/fusion/container/vector.hpp:30,
                 from /calypto/tools/install/boost/boost_1_59_0/rhel7/m64/include/boost/fusion/view/zip_view/detail/at_impl.hpp:12,
                 from /calypto/tools/install/boost/boost_1_59_0/rhel7/m64/include/boost/fusion/view/zip_view/zip_view.hpp:19,
                 from /calypto/tools/install/boost/boost_1_59_0/rhel7/m64/include/boost/fusion/view/zip_view.hpp:12,
                 from /calypto/tools/install/boost/boost_1_59_0/rhel7/m64/include/boost/fusion/sequence/intrinsic/swap.hpp:15,
                 from /calypto/tools/install/boost/boost_1_59_0/rhel7/m64/include/boost/fusion/sequence/intrinsic.hpp:23,
                 from /calypto/tools/install/boost/boost_1_59_0/rhel7/m64/include/boost/fusion/include/intrinsic.hpp:11,
                 from /calypto/tools/install/boost/boost_1_59_0/rhel7/m64/include/boost/proto/fusion.hpp:22,
                 from /calypto/tools/install/boost/boost_1_59_0/rhel7/m64/include/boost/proto/core.hpp:21,
                 from /calypto/tools/install/boost/boost_1_59_0/rhel7/m64/include/boost/proto/proto.hpp:12,
                 from /calypto/tools/install/boost/boost_1_59_0/rhel7/m64/include/boost/spirit/home/support/meta_compiler.hpp:19,
                 from /calypto/tools/install/boost/boost_1_59_0/rhel7/m64/include/boost/spirit/home/qi/meta_compiler.hpp:14,
                 from /calypto/tools/install/boost/boost_1_59_0/rhel7/m64/include/boost/spirit/home/qi/action/action.hpp:14,
                 from /calypto/tools/install/boost/boost_1_59_0/rhel7/m64/include/boost/spirit/home/qi/action.hpp:14,
                 from /calypto/tools/install/boost/boost_1_59_0/rhel7/m64/include/boost/spirit/home/qi.hpp:14,
                 from /calypto/tools/install/boost/boost_1_59_0/rhel7/m64/include/boost/spirit/include/qi.hpp:16,
                 from PASDFParser.h:17,
                 from PASDFParser.cpp:10:
/calypto/tools/install/boost/boost_1_59_0/rhel7/m64/include/boost/fusion/container/vector/detail/cpp03/as_vector.hpp:28:12: note: declaration of 'struct boost::fusion::detail::barrier::as_vector<13>'
     struct as_vector;

错误原因

你使用的Boost 1.59版本中,Boost Fusion的默认元编程序列长度上限为10(部分场景下为12)。当语法序列展开后的内部元素(包括解析器、动作、分隔符等)数量超过这个上限时,就会触发as_vector<N>的不完整类型错误——因为Boost预定义的Fusion Vector特化只覆盖到固定长度,超出后没有生成对应的模板实例。你的长语法序列展开后,内部组合的序列长度达到了13,超过了默认上限。

解决方案

方案1:提升Fusion序列长度上限

在包含任何Boost头文件之前,定义BOOST_FUSION_MAX_VECTOR_SIZE宏,设置一个足够大的值(比如20),强制Fusion生成对应长度的Vector特化:

#define BOOST_FUSION_MAX_VECTOR_SIZE 20
#include <boost/spirit/include/qi.hpp>
#include <boost/phoenix.hpp>
// 其他项目头文件

方案2:拆分语法,降低单序列元素数量

将复杂的语法拆分为更小的子规则,避免单个>>连接的序列过长,同时修正val_parser的错误写法(原写法会匹配任意数量的float,不符合目标格式的x::y结构):

namespace qi = boost::spirit::qi;
namespace phoenix = boost::phoenix;

void Parse(string const& input)
{
    string::const_iterator begin = input.begin(), end = input.end();

    auto pin_parser = qi::copy(+(qi::char_("a-z")));
    auto val_parser = qi::copy(qi::float_ >> "::" >> qi::float_); // 修正为匹配固定双冒号分隔符

    // 拆分出PIN解析子规则
    auto pins_parser = qi::copy(
        pin_parser[phoenix::bind(callback, "PIN1", qi::_1)] >> qi::space
        >> pin_parser[phoenix::bind(callback, "PIN2", qi::_1)] >> qi::space
    );

    // 拆分出值解析子规则
    auto vals_parser = qi::copy(
        val_parser >> qi::space >> val_parser >> qi::space
    );

    auto connect_parser = qi::copy(
        qi::lit("CONNECT") >> qi::space
        >> pins_parser
        >> vals_parser
    );

    bool is_succ = qi::parse(begin, end, +connect_parser);
    std::cout << "Succ " << is_succ << std::endl;
}

方案3:升级Boost版本

较新的Boost版本(如1.65及以上)中,Fusion的序列长度上限已大幅提升,且实现更灵活,不会轻易触发这类长度限制问题。如果项目允许,升级到新版本Boost可以一劳永逸解决该问题。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 21:45:06