Boost :: Spirit :: Qi。如何将内联的解析器表达式转换为独立的语法,以及如何解压缩由它们生成的元组?
|
我正在使用QI和Phoenix,我想编写一个小的语法,该语法返回4个布尔值,这些布尔值将用作语义动作内函数调用的参数。
我有几个需要这些功能的函数,到目前为止,我已经使用了这种方法:
( qi::_bool >> qi::_bool >> qi::_bool >> qi::_bool)
[px::bind(&Bool4Function, spirit::_val, spirit::_1, spirit::_2, spirit::_3, spirit::_4)]
尽管可以单独使用,但即使在“使用”命名空间部分的情况下,在各处使用它还是很丑陋和令人困惑的。
这就是为什么我想将此表达式提取为独立语法的原因。
因此,我尝试了这一点(将信用额转到ildjarn作为测试平台):
///// grammar implementation /////
#include <boost/fusion/include/vector10.hpp>
#include <boost/spirit/include/qi_bool.hpp>
#include <boost/spirit/include/qi_char_.hpp>
#include <boost/spirit/include/qi_grammar.hpp>
#include <boost/spirit/include/qi_operator.hpp>
#include <boost/spirit/include/qi_rule.hpp>
#include <boost/spirit/include/qi_string.hpp>
struct FourBools : boost::spirit::qi::grammar<
char const*,
boost::fusion::vector4<bool, bool, bool, bool>()
>
{
typedef boost::fusion::vector4<bool, bool, bool, bool> attribute_type;
FourBools() : base_type(start_)
{
using boost::spirit::bool_;
start_
= \"4bools:\"
>> bool_ >> \',\'
>> bool_ >> \',\'
>> bool_ >> \',\'
>> bool_ >> \';\'
;
}
private:
boost::spirit::qi::rule<
base_type::iterator_type,
base_type::sig_type
> start_;
};
FourBools const fourBools;
///// demonstration of use /////
#include <string>
#include <ios>
#include <iostream>
#include <boost/fusion/include/at_c.hpp>
#include <boost/spirit/include/phoenix_bind.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/qi_action.hpp>
#include <boost/spirit/include/qi_parse.hpp>
void noDice(bool a, bool b, bool c, bool d)
{
}
void worksFine(boost::fusion::vector4<bool, bool, bool, bool> a)
{
}
int main()
{
namespace phx = boost::phoenix;
namespace spirit = boost::spirit;
std::string const input(\"4bools:true,true,true,false;\");
char const* first = input.c_str();
char const* const last = first + input.size();
bool const success = spirit::qi::parse(
first, last,
fourBools[phx::bind(&noDice, spirit::_1)]
);
if (!success)
std::cout << \"parse() failed\\n\";
else if (first != last)
std::cout << \"didn\'t consume all input\\n\";
std::cout.flush();
}
除非将fourBools[phx::bind(&noDice, spirit::_1)]
替换为fourBools[phx::bind(&worksFine, spirit::_1)]
,否则不会编译。
这就是说,我的问题是要解开参数以匹配要调用的函数的签名,因为参数的数量在签名级别上有所不同(一个元组四个布尔,而四个布尔独立)。
是否可以直接使用phoenix占位符解压缩,而不是编写将元组转换为需要它们分开的现有函数的单独参数的包装器?
如果是的话,其语法将是什么?
毕竟,当由spirit::_1 - spirit::_4,
占位符“解压”时,像( qi::_bool >> qi::_bool >> qi::_bool >> qi::_bool)
这样的内联版本可以正常工作。
在我看来,这个版本似乎也返回了一个元组,并且以某种方式无法用上述方法打包,这与返回一个语法的语法不同。
我该如何处理?
没有找到相关结果
已邀请:
3 个回复
犀寺扦
顺便说一句,我认为使用具有纯同质类型的元组是很奇怪的。我个人将语法的综合属性更改为
。 编辑(响应OP的编辑):有好消息,坏消息和更多好消息。 这是个好消息:Boost.Fusion具有功能,只需很少的代码即可完成您想做的事情:
。这将采用带有多个参数的可调用类型(包括自由函数指针和成员函数指针),并将该可调用类型包装在采用Fusion序列的函子中;调用此仿函数时,它将采用Fusion序列并将其解压缩,将元组的各个元素作为单独的参数转发给包装的可调用类型。 因此,鉴于我已经发布的语法以及以下内容:
可以这样称呼:
这是一个坏消息:Boost.Fusion的可调用类型包装程序依赖于TR1 / C ++ 11
协议,而Boost.Phoenix v2实现了Boost.Lambda
协议–它们不兼容。结果,您必须自己解压缩元组元素:
!但是,还有更多好消息:Boost.Phoenix v3将在Boost 1.47中发布,并实现TR1 / C ++ 11
协议。因此,从Boost 1.47开始,您将可以使用ѭ9并节省一些繁琐的样板。
了驳
妒垮
的属性是
或任何其他stl容器,如参考中所述:http://www.boost.org/doc/libs/1_46_0/libs/spirit/doc/html/spirit/qi/ quick_reference / compound_attribute_rules.html。 该表的第一行就是这种情况:)