使用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
相关产品推荐
相关产品推荐

