如何将 std::vector<std::string> 转换为 boost::spirit 中结构的成员?
How to convert a std::vector<std::string> to be a member of a struct in boost::spirit?
我有一大块 Spirit 代码,通过使用 std::vector<std::string>
作为主要属性,它正确地将std::string input = "RED.MAGIC( 1, 2, 3 )[9].GREEN"
解析为一个简单的std::vector<std::string>
。
我想将std::vector<std::string>
替换为包含std::vector<std::string>
的结构my_rec
,但如果可能的话,继续使用自动生成器。
当我用-DUSE_MY_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 --------------------------------------------
沙盒.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;
}
如注释中链接的问题所示,为了分配给具有单个成员的改编结构,您需要在序列中使用qi::eps
。此外,还需要将中间fun_call
规则的属性更改为 std::vector<std::string>()
。
// #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;
}
您可以使用
boost::spirit::qi::as
将解析的数据转换为vector
,然后将其放入结构中。
fun_call %= as<std::vector<std::string>>()[...];
相关文章:
- 当为可变性配置时,boost::heap::d_ary_heap 保留的额外 std::list 的目的是什么?
- std::boost::asio::p ost / dispatch 使用哪个io_context?
- 我正在将一个 std::string 传递给一个 boost 函数,该函数对该类型进行常量引用,但该值发生了变化
- boost::interprocess::file_lock 与 std::ostream 一起使用时的错误行为
- 如何将 boost::hana::tuple 转换为 std::变体
- Boost.Asio:不能使用 std::bind() 来指定回调
- 如何使用 boost::future 重新抛出 std::exception_ptr 存储的原始异常?
- Boost Variant 是否提供与 std holds_alternative类似的功能?
- 使输出流式处理运算符适用于 boost::variant<std::vector<int>、int、double 的正确方法是什么>
- Boost Json 写入错误:调用 'boost::p roperty_tree::basic_ptree<std::__cxx11
- 在C++中使用std或boost库的Qtimer等价物是什么
- 在VC2015U3上,std::regex比boost::regex慢得多
- 如何正确地将 boost::optional<std::chrono::d uration> 作为函数参数?
- Hana BOOST _Hana_DEFINE_STRUCT不适用于std::unique_ptr
- std(boost)::文件系统::p ath 组件数
- 调整 C++ std/boost iostream 以提供对内存块的循环写入
- 如何停止std/boost::线程复制我的对象而不是传递引用
- Std:: boost::数组列表
- 对std/boost移动的调用不明确
- 如何将同质的fusion::向量转换为(std/boost)::数组