C++ Boost Spirit X3:如何恢复规则的匹配和不匹配结果

C++ Boost Spirit X3:如何恢复规则的匹配和不匹配结果,c++,c++14,boost-spirit-x3,C++,C++14,Boost Spirit X3,考虑以下示例文本行: “你好:世界2020:tag1:tag2:tag3” 我想设计一个spirit X3解析器,它可以提取: 内容:=“你好:世界2020” 标记:={tag1,tag2,tag3} 问题:内容在匹配标记后被定义为剩余字符序列(不包括eol),我不知道如何编写一个规则来合成两个属性:一个表示提取的标记,另一个表示剩余字符(内容) 到目前为止,我已经编写了提取标记的规则: 。。。 名称空间ast{ 结构样本{ std::u32string内容; std::向量标签; }; //推

考虑以下示例文本行:

“你好世界2020:tag1:tag2:tag3”

我想设计一个spirit X3解析器,它可以提取:

  • 内容:=“你好世界2020”
  • 标记:={tag1,tag2,tag3}
  • 问题:内容在匹配标记后被定义为剩余字符序列(不包括eol),我不知道如何编写一个规则来合成两个属性:一个表示提取的标记,另一个表示剩余字符(内容)

    到目前为止,我已经编写了提取标记的规则:

    。。。
    名称空间ast{
    结构样本{
    std::u32string内容;
    std::向量标签;
    };
    //推进核聚变。。。。。
    }
    名称空间语法{
    使用x3=boost::spirit::x3;
    使用x3::unicode::lit;
    使用x3::unicode::char\ux;
    使用x3::unicode::alnum;
    自动常数标签
    =x3::规则{“标记”}
    %=
    照明(U):
    >>
    +(alnum|lit(U“)| lit(U@”)| lit(U“#”)lit(U“%”)
    ;
    自动常量标记
    =x3::规则>照明(U):”;
    }
    
    但被困在这里:

    
    自动常量示例\u规则=
    =x3::规则{“样本”}
    = ?? // 类似于(+char|-(eol|tags);
    
    我确信有一个非常优雅的解决方案。与此同时,一个混乱的解决方案:

  • 将每个采样行作为单个字符串单元进行分析
  • 使用语义操作从每个匹配的字符串单元中筛选出标记
  • 放弃字符串单元中的筛选标记,只保留内容
  • 样本_ast.h

    #prgama一次
    #包括
    名称空间ast{
    结构样本{
    std::u32string内容;
    std::向量标签;
    };
    }
    
    样本h

    \pgrama一次
    #包括
    #包括
    #包括
    #包括“样本水电站”
    //标记属性被故意忽略。
    //它将被合成
    //手动使用语义操作
    BOOST\u FUSION\u ADAPT\u STRUCT(ast::示例,内容)
    名称空间语法{
    名称空间详细信息{
    使用x3=boost::spirit::x3;
    使用x3::unicode::char\ux;
    使用x3::eol;
    使用x3::eoi;
    使用x3::词素;
    自动常数采样线
    =x3::规则{“采样线”}
    =词素[+(字符-(eol | eoi));
    自动筛选标签=/*..为清晰起见,定义移到下一页*/
    自动常量样本
    =x3::规则{“样本”}
    =%过滤器标签[采样线];
    }}
    名称空间语法{
    使用语法::细节::示例;
    }
    
    筛选标签定义 从右到左迭代匹配的数据 冒号分隔标记,直到找到无效的标记字符 遇到或已耗尽所有字符。
    pos_saved
    用于跟踪开始 标记列表的一部分,用于丢弃标记 从内容中收集后放入ast

    auto-filter_-tags=[](自动和上下文)
    {
    auto&attr=_attr(上下文);//内容字符串
    auto&val=_val(上下文);//ast::sample
    std::stack mem;
    auto pos=attr.rbegin();
    auto&const pos_end=attr.rend();
    auto pos_saved=atrr.end();
    做{
    //标记开始或结束
    如果(*pos==U':'){
    if(mem.empty()){//tag start
    记忆推送(U’:’);
    }
    else{//标记结束
    //标记关闭状态:
    //当前标记的所有字符
    //准备转入
    //ast。
    std::u32string标签;
    而(mem.top()!=':'){
    //因为我们正在反向迭代数据
    //标签不会倒着
    tag.push_back(mem.top());
    mem.pop();
    } 
    val.tags.向后推(tag);
    //更新的起始偏移量
    //那个标签
    pos_saved=pos.base();
    } 
    }else{//是否标记字符
    使用u=spirit::char\u编码::unicode;
    如果(!mem.empty()){
    if(u::isalnum(*pos))mem.push(*pos);//找到标记字符
    else break;//找到无效的标记字符
    }
    否则{
    //标记列表后但内容结束前的空格
    如果(u::isspace(*pos)pos_saved=pos.base();
    }
    }              
    }而(++pos!=pos_end);
    如果(pos_saved!=attr.end())attr.erase(pos_saved,attr.end());
    if(attr.empty())\u pass(context)=false;
    };
    
    我确信有一个非常优雅的解决方案。与此同时,一个混乱的解决方案:

  • 将每个采样行作为单个字符串单元进行分析
  • 使用语义操作从每个匹配的字符串单元中筛选出标记
  • 放弃字符串单元中的筛选标记,只保留内容
  • 样本_ast.h

    #prgama一次
    #包括
    名称空间ast{
    结构样本{
    std::u32string内容;
    std::向量标签;
    };
    }
    
    样本h

    \pgrama一次
    #包括
    #包括
    #包括
    #包括“样本水电站”
    //标记属性被故意忽略。
    //它将被合成
    //手动使用语义操作
    BOOST\u FUSION\u ADAPT\u STRUCT(ast::示例,内容)
    名称空间语法{
    名称空间详细信息{
    使用x3=boost::spirit::x3;
    使用x3::unicode::char\ux;
    使用x3::eol;
    使用x3::eoi;
    使用x3::词素;
    自动常数采样线
    =x3::规则{“采样线”}
    =词素[+(字符-(eol | eoi));
    自动筛选标签=/*..为清晰起见,定义移到下一页*/
    自动常量样本
    =x3::规则{“samp”