【发布时间】:2012-11-30 20:51:46
【问题描述】:
我有一段 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 --------------------------------------------
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;
}
【问题讨论】:
-
+1 是一个有趣的发现,但不确定是否可行,因为在我的真实代码中,start 深深嵌入在我的真实解析规则中(不像这个玩具示例那样在开头) - 不确定是否eps 还可以(不是 eps 总是强制匹配吗?)...
标签: c++ boost boost-spirit boost-fusion