- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我正在尝试将一个简单的命令行解析器与没有语义操作的 SPIRIT 放在一起。我正在使用 BOOST 1.52,但我想避免使用 C++11 功能。语法具有以下句法:
[-p num1] [-j] [--jobs num2] str1 str2
可选参数可以是任意顺序。我成功地只解析了可选参数。一旦我添加了额外的强制性两个字符串解析器,它就会中断。即使我尝试明确写下“rstart”属性并避免使用“auto”进行类型推导,它也会崩溃。非常感谢任何帮助或建议!
#include <iostream>
#include <string>
#include <vector>
#include <iterator>
#include <boost/spirit/include/qi.hpp>
#include <boost/optional.hpp>
#include <boost/fusion/include/boost_tuple.hpp>
bool parse_line( const std::string&str,bool useStart1 )
{
bool rc=false;
namespace qi = boost::spirit::qi;
using boost::spirit::ascii::space_type;
using boost::spirit::ascii::space;
using boost::spirit::ascii::char_;
std::string::const_iterator iter( str.begin() );
std::size_t num1 =88;
bool bool1 =false;
std::size_t num2 =88;
std::string str1,str2;
qi::rule< std::string::const_iterator,std::string() > rstring=+~space;
qi::rule< std::string::const_iterator,std::size_t() ,space_type >
rOption1=qi::lit( "-p" ) >> qi::int_;
qi::rule< std::string::const_iterator,bool() ,space_type >
rOption2=qi::lit( "-j" ) >> qi::attr(true);
qi::rule< std::string::const_iterator,std::size_t() ,space_type >
rOption3=qi::lit( "--jobs" ) >> qi::int_;
#if defined(AAA)
qi::rule< std::string::const_iterator,
boost::spirit::ascii::space_type,
boost::tuple< boost::optional<std::size_t>,
boost::optional<bool>,
boost::optional<std::size_t >
>
>
#endif
auto rstart1 = ( rOption1 ^ rOption2 ^ rOption3 ) ;
auto rstart2 = ( rOption1 ^ rOption2 ^ rOption3 ) >> rstring >> rstring;
if( useStart1 )
qi::phrase_parse( iter,str.end(),
( qi::lit( "-p" ) >> qi::int_ ) ^
( qi::lit( "-j" ) >> qi::attr(true) ) ^
( qi::lit( "--jobs" ) >> qi::int_ ),space,num1,bool1,num2);
else
{
// qi::phrase_parse(
// iter,str.end(),rstart2,space,num1,bool1,num2,str1,str2);
}
if(iter==str.begin())
iter=str.begin(); //NOP
else
if(iter!=str.end())
std::cerr<<"syntax error: "<<std::string(iter,str.end())<<"!\n\n";
else
rc=true;
std::cout << "num1:" << num1 << std::endl;
std::cout << "bool1:"<< bool1 << std::endl;
std::cout << "num2:" << num2 << std::endl;
std::cout << "str1:" << str1 << std::endl;
std::cout << "str2:" << str2 << std::endl;
return rc;
}
int main( int argc,char**argv )
{
std::vector< std::string > testData1;
testData1.push_back( "-p 100 -j" );
testData1.push_back( "-j -p 100 --jobs 16" );
testData1.push_back( "--jobs 16 -j -p 100" );
for( std::vector< std::string >::const_iterator it=testData1.begin();
it!=testData1.end(); ++it )
{
std::cout << "\nparsing string:" << *it << std::endl;
parse_line( *it,true );
}
std::vector< std::string > testData2;
testData2.push_back( "-p 100 -j ifile ofile" );
testData2.push_back( "-j -p 100 --jobs 16 ifile ofile" );
testData2.push_back( "--jobs 16 -j -p 100 ifile ofile" );
for( std::vector< std::string >::const_iterator it=testData2.begin();
it!=testData2.end(); ++it )
{
std::cout << "\nparsing string:" << *it << std::endl;
parse_line( *it,false );
}
return 0;
}
最佳答案
您面临的问题是您的组合规则的属性基本上是:
tuple< tuple<size_t,bool,size_t>, std::string, std::string >
通过将您的变量一个一个地放在对 phrase_parse 的调用中,您基本上:
tuple< size_t, bool, size_t, std::string, std::string >
由于属性传播在 spirit 上的工作方式,这就是正在发生的事情:
整体tuple<size_t,bool,size_t>
被分配给你的 num1(忽略 bool 和第二个 size_t),在那个 spirit 试图将第一个字符串分配给你的 bool 之后,导致你有错误。
我认为解决此问题的最简洁方法是创建一个自定义结构来保存反射(reflect)规则结构的结果。
#include <iostream>
#include <string>
#include <vector>
#include <iterator>
#include <boost/spirit/include/qi.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
struct optional_command_line_options
{
int num1;
bool bool1;
int num2;
};
struct command_line_options
{
optional_command_line_options opt;
std::string str1;
std::string str2;
};
BOOST_FUSION_ADAPT_STRUCT(
optional_command_line_options,
(int, num1)
(bool, bool1)
(int, num2)
)
BOOST_FUSION_ADAPT_STRUCT(
command_line_options,
(optional_command_line_options, opt)
(std::string, str1)
(std::string, str2)
)
bool parse_line( const std::string&str )
{
bool rc=false;
namespace qi = boost::spirit::qi;
using boost::spirit::ascii::space;
using boost::spirit::ascii::char_;
std::string::const_iterator iter( str.begin() );
command_line_options options;
options.opt.num1=88;
options.opt.bool1=false;
options.opt.num2=88;
qi::rule< std::string::const_iterator, std::string() > rstring=+~space;
qi::rule<std::string::const_iterator, boost::spirit::ascii::space_type,optional_command_line_options() > trule;
trule=
( qi::lit( "-p" ) >> qi::int_ ) ^
( qi::lit( "-j" ) >> qi::attr(true) ) ^
( qi::lit( "--jobs" ) >> qi::int_ )
;
qi::rule< std::string::const_iterator, boost::spirit::ascii::space_type, command_line_options() >arule;
arule = -trule >> rstring >> rstring;
bool result=qi::phrase_parse( iter,str.end(),
arule,
space,
options
);
if(result && iter==str.end())
{
std::cout << "Parse successful." << std::endl;
rc=true;
}
else
{
std::cerr<<"syntax error: "<<std::string(iter,str.end())<<"!\n\n";
}
std::cout << std::boolalpha;
std::cout << "num1:" << options.opt.num1 << std::endl;
std::cout << "bool1:"<< options.opt.bool1 << std::endl;
std::cout << "num2:" << options.opt.num2 << std::endl;
std::cout << "str1:" << options.str1 << std::endl;
std::cout << "str2:" << options.str2 << std::endl;
return rc;
}
int main( int /*argc*/,char**/*argv*/ )
{
std::vector< std::string > testData;
testData.push_back( "-p 100 -j ifile ofile" );
testData.push_back( "-j -p 100 --jobs 16 ifile ofile" );
testData.push_back( "--jobs 16 -j -p 100 ifile ofile" );
testData.push_back( "--jobs 16 -p 100 ifile ofile" );
testData.push_back( "ifile ofile" );
for( std::vector< std::string >::const_iterator it=testData.begin();
it!=testData.end(); ++it )
{
std::cout << "\nparsing string:" << *it << std::endl;
parse_line( *it );
}
return 0;
}
PS:您不能直接分配给用 auto
声明的规则在不使用 boost::proto::deep_copy 的情况下嵌入文字(例如字符串或数字);
auto trule = boost::proto::deep_copy(qi::lit( "-p" ) >> qi::int_);
有一个名为 BOOST_SPIRIT_AUTO 的宏可以使它更易于使用:
#define BOOST_SPIRIT_AUTO(domain_, name, expr) \
typedef boost::proto::result_of:: \
deep_copy<BOOST_TYPEOF(expr)>::type name##_expr_type; \
BOOST_SPIRIT_ASSERT_MATCH( \
boost::spirit::domain_::domain, name##_expr_type); \
BOOST_AUTO(name, boost::proto::deep_copy(expr));
BOOST_SPIRIT_AUTO(qi,trule,qi::lit( "-p" ) >> qi::int_);
关于c++ - boost::spirit::qi 排列解析器和综合属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15998059/
假设我们要解析一个内积表达式并得到结果。 "SUM({1, 2, 3} .* {4, 5, 6})" qi::_1 和 qi::_2 非常方便地在解析器中引用第 i 个属性。 void Test(st
无法弄清楚为什么这条规则 unary_msg 不起作用,它说属性类型是 qi::unused_type 但这对我来说毫无意义。为什么 boost 会这样折磨我? template struct g3:
从测试中我可以得到 qi::uint_parser()与 qi::uint_ 相同.他们从 0 解析整数至 UINT_MAX . 我不明白的是qi::uint_parser需要 std::numeri
bool EqnExprEvaluator::SetEqn(const std::string& eqnStr) { typedef std::string::const_iterator
我一直在使用 Boost 库中的 Spirit Qi 用 C++ 编写语法。作为该语言的新手,很难习惯该库的语法和怪癖,但现在我有点了解它的工作原理。 我在使用 qi::lexeme 时遇到错误。我的
我需要跟踪一些项目在我使用提升灵气解析的文本中的位置。我找到了 this example并适应这样: #include #include #include #include #include
我想做的是在运行时从 ABNF 语法文件创建一个解析器。我已经在 qi::grammar 中实现了所有 ABNF 规则,如下所示: typedef /*qi::rule or struct conta
我在boost_1.59中使用spirit来解析类c语言(名为stone,最初由java编写)。但是我在使用 boost::spirit::qi 解析 c 风格的字符串时遇到了麻烦。整个代码位于 co
我正在用 Boost.Spirit 做一个 IRC 消息解析器,但是当我尝试解析一个输入时我遇到了一个(很长的)错误。我遵循了“Roman Numerals”示例。此外,我将 g++4.7 与 -st
如何解析可能包含 double 或 int 的字符串,具体取决于是否设置了点。例如。 6.0是double类型,6是int类型。规则是 rule,skipper> r = qi::double_|qi
在 boost::spirit::traits::transform_attribute 中指示解析失败的正确方法是什么?我可以抛出任何旧的异常,还是它要我做的特定事情? namespace boos
我正在尝试使用 qi 创建通用解析器元素,因为不幸的是(必须支持 MSVC)无法使用 X3。这个想法是有一个模板化的结构: template struct parse_type; 我可以这样使用: t
我正在尝试创建一个返回 function 的规则通过柯里化(Currying) Phoenix 表达式构造。例如, start = int_[_val = xxx]; rule start; 应该做什
我正在解析一个文本文件,可能有几 GB 的大小,由以下几行组成: 11 0.1 14 0.78 532 -3.5 基本上,每行一个整数和一个 float 。整数应该是有序的并且是非负的。我想验证数据是
我想提出一个让我陷入困境的主题,并提出了一个关于齐::符号。 这一切都始于我查看新的野兽图书馆并阅读 atutorial example 它以一个从 http 路径猜测 mime 类型的函数开始扩展。
我有一段 boost::spirit::qi 代码可以匹配 "M7.x.y.z" 或 "M7.x.y.z ",但我想要一个在前一个输入上失败的解析器。 我想我需要在其中插入 qi::lexeme[]
我正在尝试为一种语言的多个子集定义一些 Boost::spirit::qi 解析器,代码重复最少。为此,我创建了一些基本的规则构建函数。原来的解析器工作正常,但一旦我开始使用组合函数,我的解析器似乎就
假设我有一个简单的类型foo: struct foo { void bar(int) { // do something } }; 我想使用 Boost.Qi 来解析字符串中的整数字段,并使用结果值调
(免责声明,我正在学习提升精神) 我正在尝试解析这样的表达式:F( 1 ) 并希望将 1 作为字符串(“1”而不是数字(与 qi::int_ 一起使用))。 我试过这样的事情(这是错误的,但也许我的方
假设我有两个用逗号分隔的 double 来解析返回它们的总和。在 Haskell 中我可能会这样做: import Data.Attoparsec.Text import Data.Text (pac
我是一名优秀的程序员,十分优秀!