我的目标是“动态”构建由简单的排列表达式组成的表达式,但我无法使其完全正常运行。即这两个序列表明它不能按预期工作:
-b btoken -c ctoken -d dtoken -a atoken
-c ctoken -d dtoken -a atoken -b btoken
最终目标是能够动态构建可以解析不同类型的表达式:int,float,double ...... 您的建议值得赞赏: - )
#define BOOST_SPIRIT_DEBUG
#define BOOST_SPIRIT_USE_PHOENIX_V3
#include <iostream>
#include <iomanip>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
namespace qi = boost::spirit::qi;
namespace ph = boost::phoenix;
namespace ascii = boost::spirit::ascii;
typedef qi::rule<std::string::const_iterator,ascii::space_type> mrule_t;
typedef qi::rule<std::string::const_iterator,std::string() > wrule_t;
struct TStruct
{
mrule_t rule_;
template<typename T,typename R>
TStruct( T& rVar,const std::string&name, const R& rule ) :
rule_( qi::lit(name) >> rule[ ph::ref(rVar) = qi::_1 ] )
{
rule_.name(name);
}
};
bool mparse(const std::string& line,std::vector< TStruct >& args )
{
mrule_t parser = qi::eps(false);
for( const auto &argsx : args )
parser = argsx.rule_.copy() ^ parser.copy();
// BOOST_SPIRIT_DEBUG_NODES( (parser) );
auto f = begin(line), l=end(line);
return qi::phrase_parse( f, l, parser, ascii::space ) && f==l;
}
int main()
{
wrule_t rword=+~ascii::space;
std::string par1,par2,par3,par4;
std::vector< TStruct > args{
{ par1, "-a", rword },
{ par2, "-b", rword },
{ par3, "-c", rword },
{ par4, "-d", rword }
};
std::vector< std::string > inputs{
"-a atoken -b btoken -c ctoken -d dtoken",
"-b btoken -c ctoken -d dtoken -a atoken",
"-b btoken -c ctoken -d dtoken",
"-b btoken -c ctoken",
"-c ctoken -d dtoken -a atoken -b btoken",
"-d dtoken -a atoken -b btoken -c ctoken",
"-a atoken",
"-b btoken",
"-c ctoken",
"-d dtoken"
};
for ( const auto& input : inputs )
{
std::cout << "processing input:" << input << std::endl;
par1=par2=par3=par4="";
if( mparse( input,args ) )
{
std::cout << "par1:" << par1 << std::endl;
std::cout << "par2:" << par2 << std::endl;
std::cout << "par3:" << par3 << std::endl;
std::cout << "par4:" << par4 << std::endl;
}
std::cout << std::endl;
}
return 0;
}
答案 0 :(得分:2)
保护@cv_and_he从未来过度热心的mods(作为社区维基,因为这超出了我的理解)的回答值得评论:
#define BOOST_SPIRIT_USE_PHOENIX_V3
#include <iostream>
#include <iomanip>
#include <memory>
#include <boost/spirit/include/qi_core.hpp>
#include <boost/spirit/include/qi_nonterminal.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
namespace qi = boost::spirit::qi;
namespace ph = boost::phoenix;
namespace ascii = boost::spirit::ascii;
typedef qi::rule<std::string::const_iterator,ascii::space_type> mrule_t;
typedef qi::rule<std::string::const_iterator,std::string() > wrule_t;
struct TStruct
{
mrule_t rule_;
template<typename T, typename R>
TStruct( T& rVar,const std::string&name, const R& rule ) :
rule_( rule[ ph::ref(rVar) = qi::_1 ] )
{
rule_.name(name);
qi::debug(rule_);
}
};
bool mparse(const std::string& line, const std::vector<TStruct>& args )
{
qi::symbols<char,const mrule_t*> options;
for( const auto &argsx : args )
options.add(argsx.rule_.name(),&(argsx.rule_));
auto f = begin(line), l=end(line);
qi::rule<std::string::const_iterator,qi::locals<const mrule_t*>,ascii::space_type> parser = options[qi::_a=qi::_1] >> qi::lazy(*qi::_a);
return qi::phrase_parse( f, l, +parser, ascii::space ) && f==l;
}
int main()
{
wrule_t rword=+~ascii::space;
std::string par1,par2,par3,par4;
std::vector< TStruct > args{
{ par1, "-a", rword },
{ par2, "-b", rword },
{ par3, "-c", rword },
{ par4, "-d", rword }
};
std::vector< std::string > inputs{
"-a atoken -b btoken -c ctoken -d dtoken",
"-b btoken -c ctoken -d dtoken -a atoken",
"-b btoken -c ctoken -d dtoken",
"-b btoken -c ctoken",
"-c ctoken -d dtoken -a atoken -b btoken",
"-d dtoken -a atoken -b btoken -c ctoken",
"-a atoken",
"-b btoken",
"-c ctoken",
"-d dtoken"
};
for ( const auto& input : inputs )
{
std::cout << "processing input:" << input << std::endl;
par1=par2=par3=par4="";
if( mparse( input,args ) )
{
std::cout << "par1:" << par1 << std::endl;
std::cout << "par2:" << par2 << std::endl;
std::cout << "par3:" << par3 << std::endl;
std::cout << "par4:" << par4 << std::endl;
std::cout << std::endl << std::endl;
}
std::cout << std::endl;
}
return 0;
}