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

Boost Spirit链式成员访问的on_success处理器触发问题

解决Boost Spirit链式调用节点的逐次注释问题

你的问题核心在于:当前postfix规则是匹配整个链式表达式(比如a.b.c.d是一个完整的postfix匹配),所以绑定在postfix上的on_success只会在整个表达式解析完成时触发一次,仅处理最终生成的顶层节点(a.b.c.d),而中间生成的a.b、a.b.c这些节点没有机会触发注释逻辑。

要让每个链式步骤都触发annotateNode,我们需要把成员访问/函数调用的操作拆分为独立的子规则,并给这些子规则绑定on_success,这样每完成一次链式调用的解析,就会立即处理对应的中间节点。

具体实现步骤

1. 定义带参数的子规则

我们需要定义接受当前节点作为参数的子规则,用来处理单次成员访问或函数调用,生成新的节点:

// 子规则:接受当前节点(_r1),返回新的成员访问节点
qi::rule<Iterator, common_node(common_node), Skipper> member_access;
// 子规则:接受当前节点(_r1),返回新的函数调用节点
qi::rule<Iterator, common_node(common_node), Skipper> function_call;

2. 实现子规则的解析逻辑与语义动作

为每个子规则编写解析逻辑,同时在语义动作中基于传入的父节点生成新的AST节点:

// 处理成员访问(比如 .b)
member_access = (lit('.') > name_pure)
[
    _val = construct<common_node>(
        type_cmd_dot_call,
        key_this, construct<common_node>(_r1),  // 传入的父节点作为this
        key_propname, construct<std::wstring>(_1) // 成员名
    )
];

// 处理函数调用(比如 () 或 (param1, param2))
function_call = (lit('(') > paralistopt > lit(')'))
[
    _val = construct<common_node>(
        type_cmd_fnc_call,
        key_this, construct<common_node>(_r1),  // 传入的父节点作为this
        key_parameter, construct<std::vector<common_node>>(_1) // 参数列表
    )
];

3. 给子规则绑定on_success处理器

现在给每个子规则绑定annotateNode,这样每次子规则匹配完成(即生成一个新的链式节点),就会触发注释:

on_success(member_access, phoenix::bind(
    &annotateNode, 
    phoenix::ref(parserData), 
    _1, _3, // 匹配的起始/结束迭代器
    _val    // 新生成的链式节点(比如a.b)
));

on_success(function_call, phoenix::bind(
    &annotateNode, 
    phoenix::ref(parserData), 
    _1, _3, 
    _val
));

4. 修改原postfix规则调用子规则

最后,把原postfix规则修改为调用这些子规则,每次迭代都更新当前的节点值:

postfix = primary [_val=_1] >> *( 
    member_access(_val)[_val=_1]  // 传入当前节点,用返回的新节点更新_val
  | function_call(_val)[_val=_1] // 同理处理函数调用
);

效果说明

现在解析a.b.c.d时,流程会变成这样:

  1. 解析primary得到节点a,如果primary也需要注释,记得给它单独绑定on_success
  2. 匹配.b,调用member_access(a)生成a.b节点,触发member_access的on_success注释该节点,然后把_val更新为a.b
  3. 匹配.c,调用member_access(a.b)生成a.b.c节点,触发注释,更新_val
  4. 匹配.d,调用member_access(a.b.c)生成a.b.c.d节点,触发注释,更新_val
  5. 整个postfix规则完成(如果不需要重复注释最终节点,可以移除原postfix的on_success)

这样每个链式步骤生成的节点都会被单独注释,完全符合你的需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:55:40