Boost :: Spirit :: Qi如何将内联的解析器表达式转换为独立的语法,以及如何解压缩由它们生成的元组?

如何解决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>()
>
{
    typedef boost::fusion::vector4<bool,bool> attribute_type;

    FourBools() : base_type(start_)
    {
        using boost::spirit::bool_;

        start_
            =   \"4bools:\"
            >> 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> a)
{

}
int main()
{
    namespace phx = boost::phoenix;
    namespace spirit = boost::spirit;

    std::string const input(\"4bools: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)
这样的内联版本可以正常工作。 在我看来,这个版本似乎也返回了一个元组,并且以某种方式无法用上述方法打包,这与返回一个语法的语法不同。 我该如何处理?     

解决方法

        如果您没有发布完整,连贯的副本,则几乎不可能诊断出问题。可能是语法错误,可能是缺少的“ 6”,谁知道..? 这是一个可行的演示;希望您可以将其用作参考来找出您的代码出了什么问题:
///// 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>()
>
{
    typedef boost::fusion::vector4<bool,bool> attribute_type;

    FourBools() : base_type(start_)
    {
        using boost::spirit::bool_;

        start_
            =   \"4bools:\"
                >> 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>

typedef FourBools::attribute_type attr_t;

struct verify_same
{
    explicit verify_same(attr_t const& expected) : expected_(expected) { }

    void verify(attr_t const& actual) const
    {
        using boost::fusion::at_c;

        std::cout << std::boolalpha
            << \"same as expected: \" << (actual == expected_)
            << \"\\nactual values: \"
            << at_c<0>(actual) << \' \'
            << at_c<1>(actual) << \' \'
            << at_c<2>(actual) << \' \'
            << at_c<3>(actual) << \'\\n\';
    }

private:
    attr_t expected_;
};

int main()
{
    namespace phx = boost::phoenix;
    namespace spirit = boost::spirit;

    std::string const input(\"4bools:true,true,false;\");
    verify_same const vs(attr_t(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(&verify_same::verify,phx::cref(vs),spirit::_1)]
    );
    if (!success)
        std::cout << \"parse() failed\\n\";
    else if (first != last)
        std::cout << \"didn\'t consume all input\\n\";
    std::cout.flush();
}
顺便说一句,我认为使用具有纯同质类型的元组是很奇怪的。我个人将语法的综合属性更改为
boost::array<bool,4>
。 编辑(响应OP的编辑):有好消息,坏消息和更多好消息。 这是个好消息:Boost.Fusion具有功能,只需很少的代码即可完成您想做的事情:
boost::fusion::fused<>
。这将采用带有多个参数的可调用类型(包括自由函数指针和成员函数指针),并将该可调用类型包装在采用Fusion序列的函子中;调用此仿函数时,它将采用Fusion序列并将其解压缩,将元组的各个元素作为单独的参数转发给包装的可调用类型。 因此,鉴于我已经发布的语法以及以下内容:
#include <string>
#include <ios>
#include <iostream>
#include <boost/fusion/include/at_c.hpp>
#include <boost/fusion/include/make_fused.hpp>
#include <boost/spirit/include/phoenix_bind.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_fusion.hpp>
#include <boost/spirit/include/qi_action.hpp>
#include <boost/spirit/include/qi_parse.hpp>

typedef FourBools::attribute_type attr_t;

void free_func_taking_tuple(attr_t const& tup)
{
    using boost::fusion::at_c;

    std::cout << std::boolalpha
        << \"inside free_func_taking_tuple() :: \"
        << at_c<0>(tup) << \' \'
        << at_c<1>(tup) << \' \'
        << at_c<2>(tup) << \' \'
        << at_c<3>(tup) << \'\\n\';
}

void free_func_taking_bools(
    bool const a,bool const b,bool const c,bool const d
)
{
    std::cout << std::boolalpha
        << \"inside free_func_taking_bools() :: \"
        << a << \' \'
        << b << \' \'
        << c << \' \'
        << d << \'\\n\';
}
boost::spirit::qi::parse()
可以这样称呼:
namespace phx = boost::phoenix;
namespace spirit = boost::spirit;
using boost::fusion::make_fused;

// calls free_func_taking_tuple,nothing new here
spirit::qi::parse(
    first,fourBools[phx::bind(free_func_taking_tuple,spirit::_1)]
);

// calls free_func_taking_bools,using boost::fusion::fused<> to unpack the tuple
// into separate arguments
spirit::qi::parse(
    first,fourBools[phx::bind(make_fused(&free_func_taking_bools),spirit::_1)]
);
这是一个坏消息:Boost.Fusion的可调用类型包装程序依赖于TR1 / C ++ 11
result_of
协议,而Boost.Phoenix v2实现了Boost.Lambda
result_of
协议–它们不兼容。结果,您必须自己解压缩元组元素:
namespace phx = boost::phoenix;
namespace spirit = boost::spirit;

spirit::qi::parse(
    first,fourBools[phx::bind(
        free_func_taking_bools,phx::at_c<0>(spirit::_1),phx::at_c<1>(spirit::_1),phx::at_c<2>(spirit::_1),phx::at_c<3>(spirit::_1)
    )]
);
!但是,还有更多好消息:Boost.Phoenix v3将在Boost 1.47中发布,并实现TR1 / C ++ 11
result_of
协议。因此,从Boost 1.47开始,您将可以使用ѭ9并节省一些繁琐的样板。     ,        作为一般说明,我建议在此处阅读Spirit网站上有关属性处理的文章。这些构成了随库一起分发的在线文档的很好的附录。     ,        
qi::_bool >> qi::_bool >>  qi::_bool >> qi::_bool
的属性是
std::vector<bool>
或任何其他stl容器,如参考中所述:http://www.boost.org/doc/libs/1_46_0/libs/spirit/doc/html/spirit/qi/ quick_reference / compound_attribute_rules.html。 该表的第一行就是这种情况:)     

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-