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

使用Boost Spirit解析Spice网表仅获首行结果的问题排查

Boost Spirit解析Spice网表的问题

网表内容

V1 N001 N002 10
R1 N001 N002 24.9

已定义的结构体

struct ElementStatement {
  boost::optional<std::string> element_label;
  boost::optional<std::string> element_node1;
  boost::optional<std::string> element_node2;
  boost::optional<double> element_value;
};

struct SpiceNetlist {
  std::vector<ElementStatement> element_statements;
//to be expanded
};

问题描述

使用Boost Spirit编写解析代码后,能成功解析所有字符,但仅能获取第一行元件结果;尝试将element_statements规则改为std::vector类型时出现编译错误。

问题原因与解决方法

1. 结构体未适配Boost Fusion

Boost Spirit需要将结构体暴露给Fusion框架,才能正确将解析结果映射到结构体或其容器中。缺少适配宏会导致vector类型的规则编译失败。

添加适配宏:

#include <boost/fusion/include/adapt_struct.hpp>

BOOST_FUSION_ADAPT_STRUCT(
    ElementStatement,
    (boost::optional<std::string>, element_label)
    (boost::optional<std::string>, element_node1)
    (boost::optional<std::string>, element_node2)
    (boost::optional<double>, element_value)
)

2. 规则未定义重复匹配逻辑

原规则可能仅匹配单个ElementStatement,未处理多行重复的情况,导致只解析第一行。需要用*(零或多次)或+(一次或多次)定义重复匹配,同时处理换行符作为分隔。

修正后的规则示例:

#include <boost/spirit/include/qi.hpp>

namespace qi = boost::spirit::qi;

template <typename Iterator>
struct SpiceGrammar : qi::grammar<Iterator, SpiceNetlist(), qi::blank_type> {
    SpiceGrammar() : SpiceGrammar::base_type(netlist) {
        // 单个元件语句规则:匹配标签、两个节点、数值
        element_statement = 
            qi::lexeme[qi::alpha >> *qi::alnum] >>  // 元件标签(如V1、R1)
            qi::lexeme[*qi::alnum] >>               // 节点1
            qi::lexeme[*qi::alnum] >>               // 节点2
            qi::double_;                            // 参数值

        // 网表规则:匹配零或多个元件语句,每行一个
        netlist = *(element_statement >> qi::eol);
    }

    qi::rule<Iterator, ElementStatement(), qi::blank_type> element_statement;
    qi::rule<Iterator, SpiceNetlist(), qi::blank_type> netlist;
};

3. 语义动作绑定错误

如果手动为vector规则绑定语义动作,错误的赋值方式会导致编译失败,需使用push_back而非直接赋值:

错误示例:

// 错误:直接赋值给vector
netlist = element_statement[phoenix::ref(netlist.element_statements) = _1];

正确示例:

#include <boost/phoenix.hpp>
namespace phoenix = boost::phoenix;

// 正确:将每个解析结果push_back到vector
netlist = *(element_statement[phoenix::push_back(phoenix::ref(netlist.element_statements), _1)] >> qi::eol);

4. 未正确处理空白/换行

解析时需要指定空白符跳过规则(如qi::blank_type),确保换行符和空格被正确处理,避免剩余输入无法匹配。

修正后的解析逻辑示例

#include <string>
#include <vector>

int main() {
    std::string input = "V1 N001 N002 10\nR1 N001 N002 24.9";
    SpiceNetlist netlist;
    SpiceGrammar<std::string::iterator> grammar;

    auto it = input.begin();
    bool success = qi::phrase_parse(it, input.end(), grammar, qi::blank, netlist);

    if (success && it == input.end()) {
        // 解析成功,netlist.element_statements包含两个ElementStatement实例
    }
    return 0;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 10:43:16