C++ 如何转换std::vector<;标准::字符串>;成为boost::spirit中结构的成员?

C++ 如何转换std::vector<;标准::字符串>;成为boost::spirit中结构的成员?,c++,boost,boost-spirit,boost-fusion,C++,Boost,Boost Spirit,Boost Fusion,我有一段Spirit代码,它使用std::vector作为主要属性,将std::vector正确地解析为一个简单的std::vector 我想将std::vector替换为包含std::vector的结构my_rec,但如果可能,请继续使用自动生成器 当我使用-DUSE\u MY\u REC编译时,我会遇到一堆无法穿透的编译错误 编译并运行示例 /tmp$ g++ -g -std=c++11 sandbox.cpp -o sandbox && ./sandbox Finishe

我有一段Spirit代码,它使用
std::vector
作为主要属性,将
std::vector
正确地解析为一个简单的
std::vector

我想将
std::vector
替换为包含
std::vector
的结构
my_rec
,但如果可能,请继续使用自动生成器

当我使用
-DUSE\u MY\u REC
编译时,我会遇到一堆无法穿透的编译错误

编译并运行示例

/tmp$ g++ -g -std=c++11 sandbox.cpp -o sandbox && ./sandbox 
Finished.
MATCHED
/tmp$ g++ -DUSE_MY_REC -g -std=c++11 sandbox.cpp -o sandbox && ./sandbox
WALL OF COMPILE ERRORS --------------------------------------------
sandbox.cpp

// #define BOOST_SPIRIT_DEBUG
#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_fusion.hpp>
#include <boost/fusion/include/adapt_struct.hpp>

#include <string>
#include <iostream>

namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;

#ifdef USE_MY_REC
struct my_rec
{
    std::vector<std::string>    m_pieces;
};

BOOST_FUSION_ADAPT_STRUCT(
  my_rec,
  (std::vector<std::string>,  m_pieces)
)

typedef struct my_rec            MY_TYPE;
#else
typedef std::vector<std::string> MY_TYPE;
#endif

template <typename ITERATOR>
struct my_parser : 
    qi::grammar<ITERATOR, MY_TYPE(), ascii::space_type>
{
    my_parser() : 
        my_parser::base_type( start )
    {
        start %= ( color | fun_call ) % '.'
                ;

        color %=
                qi::string( "RED" )
                | qi::string( "GREEN" )
                | qi::string( "BLUE" )
                ;

        fun_call %= 
                qi::string( "MAGIC" )
                >> '('
                >> +qi::char_("0-9") % ','
                >> ')'
                >> '['
                >> +qi::char_("0-9")
                >> ']'
                ;
    }
    qi::rule<ITERATOR, MY_TYPE(),     ascii::space_type> start, fun_call;
    qi::rule<ITERATOR, std::string(), ascii::space_type> color;
};

int
main( int argc, char* argv[] )
{
    namespace qi    = boost::spirit::qi;
    namespace ascii = boost::spirit::ascii;

    MY_TYPE                  v;
    std::string              str = "RED.MAGIC( 1, 2, 3 )[9].GREEN";
    std::vector<std::string> exp = {{ "RED", "MAGIC", "1", "2", "3", "9", "GREEN" }};
    auto                     it  = str.begin(), end = str.end();
    my_parser<decltype(it)>  g;

    if( qi::phrase_parse( it, end, g, ascii::space, v ) && it==end ) 
    {
        std::cout << "Finished." << std::endl;
#ifndef USE_MY_REC
        if ( !std::equal( v.begin(), v.end(), exp.begin() ))
        {
            std::cout << "MISMATCH" << std::endl;
            for( const auto& x : v )
                std::cout << x << std::endl;
        } else {
            std::cout << "MATCHED" << std::endl;
        }
#endif
    } else
        std::cout << "Error." << std::endl;

    return 0;
}
/#定义BOOST_SPIRIT_调试
#包括
#包括
#包括
#包括
#包括
#包括
名称空间qi=boost::spirit::qi;
名称空间ascii=boost::spirit::ascii;
#如果使用我的记录
结构我的记录
{
std::向量m_片段;
};
增强融合适应结构(
我的记录,
(标准::向量,m_块)
)
typedef struct my_rec my_TYPE;
#否则
typedef std::vector MY_TYPE;
#恩迪夫
模板
结构my_解析器:
语法
{
我的语法分析器():
my_解析器::基本_类型(开始)
{
开始%=(颜色|趣味呼叫)%”
;
颜色%=
qi::字符串(“红色”)
|qi::字符串(“绿色”)
|qi::字符串(“蓝色”)
;
趣味电话%=
qi::字符串(“魔术”)
>> '('
>>+qi::字符(“0-9”)%,'
>> ')'
>> '['
>>+qi::字符(0-9)
>> ']'
;
}
qi::规则开始,有趣的呼叫;
规则颜色;
};
int
main(int argc,char*argv[])
{
名称空间qi=boost::spirit::qi;
名称空间ascii=boost::spirit::ascii;
MY_v型;
std::string str=“RED.MAGIC(1,2,3)[9].GREEN”;
向量exp={{“红色”、“魔法”、“1”、“2”、“3”、“9”、“绿色”};
auto it=str.begin(),end=str.end();
我的(g);
if(qi::phrase_parse(it,end,g,ascii::space,v)&&it==end)
{

std::cout您可以使用
boost::spirit::qi::as
将解析数据转换为
向量,然后将其放入您的结构中

fun_call %= as<std::vector<std::string>>()[...];
fun_call%=as()[…];

如注释中链接的问题所示,为了分配给具有单个成员的自适应结构,您需要按顺序使用
qi::eps
。此外,您还需要将中间
fun\u调用的属性更改为
std::vector()

/#定义BOOST_SPIRIT_调试
#包括
#包括
#包括
#包括
#包括
#包括
名称空间qi=boost::spirit::qi;
名称空间ascii=boost::spirit::ascii;
结构我的记录
{
std::向量m_片段;
};
增强融合适应结构(
我的记录,
(标准::向量,m_块)
)
typedef struct my_rec my_TYPE;
模板
结构my_解析器:
语法
{
我的语法分析器():
my_解析器::基本_类型(开始)
{
start%=qi::eps>>(color | fun_call)%'.//添加qi::eps以使单成员结构的自适应工作
;
颜色%=
qi::字符串(“红色”)
|qi::字符串(“绿色”)
|qi::字符串(“蓝色”)
;
趣味电话%=
qi::字符串(“魔术”)
>> '('
>>+qi::字符(“0-9”)%,'
>> ')'
>> '['
>>+qi::字符(0-9)
>> ']'
;
}
qi::规则开始;
qi::rule fun_call;//将此规则的属性更改为vector
规则颜色;
};
int
main(int argc,char*argv[])
{
名称空间qi=boost::spirit::qi;
名称空间ascii=boost::spirit::ascii;
MY_v型;
std::string str=“RED.MAGIC(1,2,3)[9].GREEN”;
std::vector exp;
exp.push_back(“红色”);
exp.push_back(“魔术”);
exp.push_back(“1”);
exp.push_back(“2”);
exp.push_back(“3”);
exp.push_back(“9”);
exp.push_back(“绿色”);
auto it=str.begin(),end=str.end();
我的(g);
if(qi::phrase_parse(it,end,g,ascii::space,v)&&it==end)
{

std::cout.+1是一个有趣的发现,但不确定是否可行,因为在我的实际代码中,start深深嵌入在我的实际解析规则中(不像这个玩具示例中那样在开头)-不确定eps在那里是否正常(eps不总是强制匹配吗?)…+1作为一个有效的解决方案-尝试看看我们是否也可以以某种方式取笑调用my_rec…好的-在复杂的解析(真实代码)中深入调整此解决方案是可以的。ty-接受。
// #define BOOST_SPIRIT_DEBUG
#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_fusion.hpp>
#include <boost/fusion/include/adapt_struct.hpp>

#include <string>
#include <iostream>

namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;


struct my_rec
{
    std::vector<std::string>    m_pieces;
};

BOOST_FUSION_ADAPT_STRUCT(
  my_rec,
  (std::vector<std::string>,  m_pieces)
)

typedef struct my_rec            MY_TYPE;


template <typename ITERATOR>
struct my_parser : 
    qi::grammar<ITERATOR, MY_TYPE(), ascii::space_type>
{
    my_parser() : 
        my_parser::base_type( start )
    {
        start %= qi::eps >>( color | fun_call ) % '.' //add qi::eps to make the adaptation of the single member struct work
                ;

        color %=
                qi::string( "RED" )
                | qi::string( "GREEN" )
                | qi::string( "BLUE" )
                ;

        fun_call %= 
                qi::string( "MAGIC" )
                >> '('
                >> +qi::char_("0-9") % ','
                >> ')'
                >> '['
                >> +qi::char_("0-9")
                >> ']'
                ;
    }
    qi::rule<ITERATOR, MY_TYPE(),     ascii::space_type> start;
    qi::rule<ITERATOR, std::vector<std::string>(), ascii::space_type> fun_call; //changed this rule's attribute to vector<string>
    qi::rule<ITERATOR, std::string(), ascii::space_type> color;
};

int
main( int argc, char* argv[] )
{
    namespace qi    = boost::spirit::qi;
    namespace ascii = boost::spirit::ascii;

    MY_TYPE                  v;
    std::string              str = "RED.MAGIC( 1, 2, 3 )[9].GREEN";
    std::vector<std::string> exp;
    exp.push_back("RED");
    exp.push_back("MAGIC");
    exp.push_back("1");
    exp.push_back("2");
    exp.push_back("3");
    exp.push_back("9");
    exp.push_back("GREEN");
    auto                     it  = str.begin(), end = str.end();
    my_parser<decltype(it)>  g;

    if( qi::phrase_parse( it, end, g, ascii::space, v ) && it==end ) 
    {
        std::cout << "Finished." << std::endl;

        if ( !std::equal( v.m_pieces.begin(), v.m_pieces.end(), exp.begin() ))
        {
            std::cout << "MISMATCH" << std::endl;
            for( const auto& x : v.m_pieces )
                std::cout << x << std::endl;
        } else {
            std::cout << "MATCHED" << std::endl;
        }

    } else
        std::cout << "Error." << std::endl;

    return 0;
}