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

如何修改Boost Spirit规则,排除PureData对象的保留关键字解析

修改Boost Spirit规则以跳过PureData特殊保留名对象

需求与背景

我需要将PureData中的对象记录解析为通用PdObject结构体,相关定义与对象语法如下:

PdObject结构体与PureData对象语法

描述:定义PureData通用对象
语法:

#X obj [x_pos] [y_pos] [object_name] [p1] [p2] [p3] [...];

参数:

  • [x_pos]:窗口内水平位置
  • [y_pos]:窗口内垂直位置
  • [object_name]:对象名称(可选)
  • [p1] [p2] [p3] [...]:对象参数(可选)
    示例:
#X obj 55 50;
#X obj 132 72 trigger bang float;

已编写并测试可用的Boost Spirit规则,但存在bng、tgl、nbx等特殊保留名称的对象(示例如下),这类对象需要由另一规则解析为不同结构体,因此需要修改现有规则,使其不匹配这类保留名对象,留待其他语法处理:

#X obj 92 146 bng 20 250 50 0 empty empty empty 0 -10 0 12 #fcfcfc #000000 #000000;

现有Boost Spirit规则

template <typename Iterator> struct PdObjectGrammar : qi::grammar<Iterator, PdObject()> { 
    PdObjectGrammar() : PdObjectGrammar::base_type(start) { 
        using namespace qi; 
        start = skip(space)[objectRule]; 
        pdStringRule = +(('\\'  >> space) | (graph-lit(";"))); 
        objectRule = "#X obj" >> int_ >> int_ >> -(pdStringRule) >> *(pdStringRule) >> ";"; 
        BOOST_SPIRIT_DEBUG_NODES((start)(objectRule)(pdStringRule))
    }
    private: 
    qi::rule<Iterator, std::string()> pdStringRule; 
    qi::rule<Iterator, PdObject()> start; 
    qi::rule<Iterator, PdObject(), qi::space_type> objectRule; 
};

修改方案

核心思路是在匹配对象名称时排除指定的保留词,具体修改步骤如下:

  1. 定义保留名规则:创建匹配所有需要跳过的保留名称的规则,确保精确匹配完整单词。
  2. 修改字符串匹配逻辑:在pdStringRule前添加逻辑非判断,若当前输入是保留名则匹配失败,让整个objectRule对这类特殊对象不生效。

修改后的规则代码:

template <typename Iterator> struct PdObjectGrammar : qi::grammar<Iterator, PdObject()> { 
    PdObjectGrammar() : PdObjectGrammar::base_type(start) { 
        using namespace qi; 

        // 定义需要跳过的特殊保留名称,可按需扩展
        reserved_names = lit("bng") | lit("tgl") | lit("nbx");

        // 修改pdStringRule:先检查是否为保留名,是则匹配失败,否则正常匹配字符串
        pdStringRule = !(reserved_names) >> +(('\\' >> space) | (graph - lit(";"))); 

        objectRule = "#X obj" >> int_ >> int_ >> -(pdStringRule) >> *(pdStringRule) >> ";"; 
        start = skip(space)[objectRule]; 

        BOOST_SPIRIT_DEBUG_NODES((start)(objectRule)(pdStringRule)(reserved_names))
    }
    private: 
    qi::rule<Iterator, std::string()> pdStringRule; 
    qi::rule<Iterator, PdObject()> start; 
    qi::rule<Iterator, PdObject(), qi::space_type> objectRule; 
    qi::rule<Iterator()> reserved_names; // 保留名匹配规则
};

关键修改说明

  • reserved_names使用lit()确保只匹配完整的保留名称,避免部分匹配的情况。
  • !(reserved_names)是逻辑非操作,当输入为保留名时,pdStringRule匹配失败,进而导致整个objectRule匹配失败,这类特殊对象就会留给其他语法规则处理。

完整测试代码

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

#include <string> 
#include <vector>
#include <fstream>

namespace qi = boost::spirit::qi;

struct PdObject {
    int xPos;
    int yPos;
    std::string name;
    std::vector<std::string> params;
};

BOOST_FUSION_ADAPT_STRUCT(
    PdObject,
    xPos,
    yPos,
    name,
    params
)

template <typename Iterator> struct PdObjectGrammar : qi::grammar<Iterator, PdObject()> { 
    PdObjectGrammar() : PdObjectGrammar::base_type(start) { 
        using namespace qi; 

        // 定义特殊保留名称
        reserved_names = lit("bng") | lit("tgl") | lit("nbx");

        // 修改后的pdStringRule,排除保留名
        pdStringRule = !(reserved_names) >> +(('\\' >> space) | (graph - lit(";"))); 

        objectRule = "#X obj" >> int_ >> int_ >> -(pdStringRule) >> *(pdStringRule) >> ";"; 
        start = skip(space)[objectRule]; 

        BOOST_SPIRIT_DEBUG_NODES((start)(objectRule)(pdStringRule)(reserved_names))
    }
    private: 
    qi::rule<Iterator, std::string()> pdStringRule; 
    qi::rule<Iterator, PdObject()> start; 
    qi::rule<Iterator, PdObject(), qi::space_type> objectRule; 
    qi::rule<Iterator()> reserved_names;
};

int main(int argc, char** argv)
{
    if(argc != 2)
    {
        std::cout << "Usage: "  << argv[0] << " <PatchFile>" << std::endl;
        exit(1); 
    }

    std::ifstream inputFile(argv[1]); 
    std::string inputString(std::istreambuf_iterator<char>(inputFile), {}); 

    PdObject msg;
    PdObjectGrammar<std::string::iterator> parser; 

    bool success = qi::phrase_parse(inputString.begin(), inputString.end(), parser, boost::spirit::ascii::space, msg); 
    std::cout << "Success: " << success << std::endl;

    return 0; 
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 05:42:55