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

Boost Qi解析器为何在文本结束前停止解析?

问题分析与解决方案

核心问题:term规则的文法定义错误

你当前的term规则采用备选分支(|)定义:

term = factor[_val = _1] | (factor[_val = _1] >> "&&" >> factor)[_val = _val && _1];

Boost Spirit的备选分支是按顺序尝试匹配的,第一个分支factor[_val = _1]会优先匹配成功(比如解析完$32后就满足条件),导致整个term规则直接结束,完全不会尝试后续的&& $33部分,这就是解析在&& $33处停止的原因。

修正方案

逻辑与(&&)是左结合的运算符,正确的文法应该用**重复匹配(Kleene星号)**来实现连续的&&表达式,修改term规则如下:

term = factor[_val = _1] >> *("&&" >> factor)[_val = _val && _1];

这个写法的逻辑是:

  1. 先匹配第一个factor,将结果赋值给_val
  2. 重复匹配"&&" >> factor,每次匹配成功后,将当前_val与新的factor结果做逻辑与运算,更新_val
  3. 重复0次时,就等价于单个factor,自然覆盖了原规则的第一个分支

修正后的完整文法代码

template<typename iterator>
struct composite : qi::grammar<iterator, bool()>
{
    composite() : composite::base_type(start)
    {
        using qi::lit;
        using qi::_val;
        using qi::_1;
        using qi::long_;
        using ascii::char_;
        using phx::ref;
        using phx::val;

        stepid  = long_[ref(longv) = _1, _val = _1];
        // 优化stepref:直接传递stepid的结果给evaluate_step,避免依赖成员变量的时序问题
        stepref = (lit("$") >> stepid)[phx::bind(&evaluate_step, _1, ref(boolv)), _val = ref(boolv)];

        // 修正后的term规则
        term    = factor[_val = _1] >> *("&&" >> factor)[_val = _val && _1];

        factor  = stepref[_val = _1] | ("!" >> stepref)[_val = !_1];

        start = term[_val = _1];
    }

    qi::rule<iterator, long()> stepid;
    qi::rule<iterator, bool()> stepref;
    qi::rule<iterator, bool()> term;
    qi::rule<iterator, bool()> factor;
    qi::rule<iterator, bool()> start;

    long longv;
    bool boolv;
};

额外建议

  1. 后续扩展支持||和括号时,要遵循运算符优先级:括号 > ! > && > ||,需要新增expr规则处理||,保持term处理&&,factor处理括号和!,比如:
    expr = term[_val = _1] >> *("||" >> term)[_val = _val || _1];
    factor = stepref[_val = _1] | ("!" >> factor)[_val = !_1] | ("(" >> expr >> ")")[_val = _1];
    start = expr[_val = _1];
    
  2. 成员变量longv和boolv会在多次解析时被覆盖,建议将evaluate_step的结果直接绑定到_val,避免依赖全局/成员状态,比如:
    stepref = lit("$") >> long_[_val = phx::bind(&evaluate_step, _1)];
    
    这样可以去掉longv和boolv两个成员变量,让文法更健壮。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 22:07:12