使用 Boost Spirit 和 Fusion 以关联方式解析结构

2024-06-18

我正在尝试将键值字符串解析为结构。一些键值可能不存在或者顺序不同,所以我想使用boost::fusion调整结构,然后解析它at_key<>指示。

#include <iostream>
#include <string>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/fusion/adapted.hpp>
#include <boost/fusion/sequence.hpp>

using namespace std;
namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;
namespace phx = boost::phoenix;

using boost::fusion::at_key;

typedef string::const_iterator iter_type;

struct Couple {
    int a;
    int b;
    Couple() : a(0), b(0) {}
};

namespace keys {
    struct first;
    struct second;
}

BOOST_FUSION_ADAPT_ASSOC_STRUCT(
    Couple,
    (int, a, keys::first)
    (int, b, keys::second)
    )


struct G: qi::grammar< iter_type, Couple(), ascii::space_type >
{
    G() : G::base_type( start_rule ) {
        using qi::_val;
        using qi::_1;
        using qi::_2;

        start_rule =
                        ( "first" >> qi::int_
                                [ at_key<keys::first>(_val) = _1 ]
                        )
                    ^
                        ( "second" >> qi::int_
                                [ at_key<keys::second>(_val) = _1 ]
                        );
    }

    qi::rule< iter_type, Couple(), ascii::space_type > start_rule;
};

int main() {
    Couple couple;
    string example = "second 2 first 1";
    iter_type begin( example.begin() );
    iter_type end( example.end() );

    // test at_key -- compiles with no error
    at_key<keys::second>(couple) = 5;

    bool ok = qi::phrase_parse( begin, end, G(), ascii::space, couple );
    if ( ok )
        cout << couple.a << " " << couple.b << endl;
    else
        cout << "Parse failed" << endl;

    return 0;
}

问题是代码无法编译(Boost 1.50.0、g++ 4.5.0、MinGW),显然在at_key<> rules:

In file included from D:\projects\workspace\boost/boost/fusion/support/category_of.hpp:10:0,
                 from D:\projects\workspace\boost/boost/fusion/include/category_of.hpp:10,
                 from D:\projects\workspace\boost/boost/proto/fusion.hpp:20,
                 from D:\projects\workspace\boost/boost/proto/core.hpp:21,
                 from D:\projects\workspace\boost/boost/proto/proto.hpp:12,
                 from D:\projects\workspace\boost/boost/spirit/home/support/meta_compiler.hpp:19,
                 from D:\projects\workspace\boost/boost/spirit/home/qi/meta_compiler.hpp:14,
                 from D:\projects\workspace\boost/boost/spirit/home/qi/action/action.hpp:14,
                 from D:\projects\workspace\boost/boost/spirit/home/qi/action.hpp:14,
                 from D:\projects\workspace\boost/boost/spirit/home/qi.hpp:14,
                 from D:\projects\workspace\boost/boost/spirit/include/qi.hpp:16,
                 from ..\src\spirit02_test.cpp:11:
D:\projects\workspace\boost/boost/fusion/support/detail/category_of.hpp: In instantiation of 'boost::fusion::detail::fusion_category_of<const boost::phoenix::actor<boost::spirit::attribute<0> > >':
D:\projects\workspace\boost/boost/fusion/support/category_of.hpp:44:58:   instantiated from 'boost::fusion::extension::category_of_impl<boost::fusion::non_fusion_tag>::apply<const boost::phoenix::actor<boost::spirit::attribute<0> > >'
D:\projects\workspace\boost/boost/fusion/support/category_of.hpp:66:9:   instantiated from 'boost::fusion::traits::category_of<const boost::phoenix::actor<boost::spirit::attribute<0> > >'
D:\projects\workspace\boost/boost/fusion/support/category_of.hpp:73:9:   instantiated from 'boost::fusion::traits::is_associative<const boost::phoenix::actor<boost::spirit::attribute<0> > >'
D:\projects\workspace\boost/boost/mpl/if.hpp:67:11:   instantiated from 'boost::mpl::if_<boost::fusion::traits::is_associative<const boost::phoenix::actor<boost::spirit::attribute<0> > >, boost::fusion::result_of::key_of<mpl_::arg<1> >, boost::fusion::result_of::value_of<mpl_::arg<1> > >'
D:\projects\workspace\boost/boost/fusion/algorithm/query/find.hpp:45:9:   instantiated from 'boost::fusion::result_of::find<const boost::phoenix::actor<boost::spirit::attribute<0> >, keys::first>'
D:\projects\workspace\boost/boost/fusion/sequence/intrinsic/at_key.hpp:38:17:   instantiated from 'boost::fusion::extension::at_key_impl<boost::fusion::non_fusion_tag>::apply<const boost::phoenix::actor<boost::spirit::attribute<0> >, keys::first>'
D:\projects\workspace\boost/boost/fusion/sequence/intrinsic/at_key.hpp:71:9:   instantiated from 'boost::fusion::result_of::at_key<const boost::phoenix::actor<boost::spirit::attribute<0> >, keys::first>'
..\src\spirit02_test.cpp:54:35:   instantiated from here
D:\projects\workspace\boost/boost/fusion/support/detail/category_of.hpp:15:38: error: no type named 'category' in 'const struct boost::phoenix::actor<boost::spirit::attribute<0> >'
In file included from D:\projects\workspace\boost/boost/proto/args.hpp:21:0,
                 from D:\projects\workspace\boost/boost/proto/core.hpp:14,
                 from D:\projects\workspace\boost/boost/proto/proto.hpp:12,
                 from D:\projects\workspace\boost/boost/spirit/home/support/meta_compiler.hpp:19,
                 from D:\projects\workspace\boost/boost/spirit/home/qi/meta_compiler.hpp:14,
                 from D:\projects\workspace\boost/boost/spirit/home/qi/action/action.hpp:14,
                 from D:\projects\workspace\boost/boost/spirit/home/qi/action.hpp:14,
                 from D:\projects\workspace\boost/boost/spirit/home/qi.hpp:14,
                 from D:\projects\workspace\boost/boost/spirit/include/qi.hpp:16,
                 from ..\src\spirit02_test.cpp:11:
D:\projects\workspace\boost/boost/mpl/if.hpp: In instantiation of 'boost::mpl::if_<boost::fusion::traits::is_associative<const boost::phoenix::actor<boost::spirit::attribute<0> > >, boost::fusion::result_of::key_of<mpl_::arg<1> >, boost::fusion::result_of::value_of<mpl_::arg<1> > >':
D:\projects\workspace\boost/boost/fusion/algorithm/query/find.hpp:45:9:   instantiated from 'boost::fusion::result_of::find<const boost::phoenix::actor<boost::spirit::attribute<0> >, keys::first>'
D:\projects\workspace\boost/boost/fusion/sequence/intrinsic/at_key.hpp:38:17:   instantiated from 'boost::fusion::extension::at_key_impl<boost::fusion::non_fusion_tag>::apply<const boost::phoenix::actor<boost::spirit::attribute<0> >, keys::first>'
D:\projects\workspace\boost/boost/fusion/sequence/intrinsic/at_key.hpp:71:9:   instantiated from 'boost::fusion::result_of::at_key<const boost::phoenix::actor<boost::spirit::attribute<0> >, keys::first>'
..\src\spirit02_test.cpp:54:35:   instantiated from here
D:\projects\workspace\boost/boost/mpl/if.hpp:67:11: error: 'value' is not a member of 'boost::fusion::traits::is_associative<const boost::phoenix::actor<boost::spirit::attribute<0> > >'
D:\projects\workspace\boost/boost/mpl/if.hpp:70:41: error: 'value' is not a member of 'boost::fusion::traits::is_associative<const boost::phoenix::actor<boost::spirit::attribute<0> > >'
In file included from D:\projects\workspace\boost/boost/fusion/sequence/intrinsic.hpp:20:0,
                 from D:\projects\workspace\boost/boost/fusion/include/intrinsic.hpp:10,
                 from D:\projects\workspace\boost/boost/proto/fusion.hpp:22,
                 from D:\projects\workspace\boost/boost/proto/core.hpp:21,
                 from D:\projects\workspace\boost/boost/proto/proto.hpp:12,
                 from D:\projects\workspace\boost/boost/spirit/home/support/meta_compiler.hpp:19,
                 from D:\projects\workspace\boost/boost/spirit/home/qi/meta_compiler.hpp:14,
                 from D:\projects\workspace\boost/boost/spirit/home/qi/action/action.hpp:14,
                 from D:\projects\workspace\boost/boost/spirit/home/qi/action.hpp:14,
                 from D:\projects\workspace\boost/boost/spirit/home/qi.hpp:14,
                 from D:\projects\workspace\boost/boost/spirit/include/qi.hpp:16,
                 from ..\src\spirit02_test.cpp:11:
D:\projects\workspace\boost/boost/fusion/sequence/intrinsic/at_key.hpp: In instantiation of 'boost::fusion::extension::at_key_impl<boost::fusion::non_fusion_tag>::apply<const boost::phoenix::actor<boost::spirit::attribute<0> >, keys::first>':
D:\projects\workspace\boost/boost/fusion/sequence/intrinsic/at_key.hpp:71:9:   instantiated from 'boost::fusion::result_of::at_key<const boost::phoenix::actor<boost::spirit::attribute<0> >, keys::first>'
..\src\spirit02_test.cpp:54:35:   instantiated from here
D:\projects\workspace\boost/boost/fusion/sequence/intrinsic/at_key.hpp:38:17: error: no type named 'type' in 'struct boost::fusion::result_of::find<const boost::phoenix::actor<boost::spirit::attribute<0> >, keys::first>'
..\src\spirit02_test.cpp: In constructor 'G::G()':
..\src\spirit02_test.cpp:54:35: error: no matching function for call to 'at_key(const boost::spirit::_val_type&)'
In file included from D:\projects\workspace\boost/boost/fusion/sequence/intrinsic.hpp:20:0,
                 from D:\projects\workspace\boost/boost/fusion/include/intrinsic.hpp:10,
                 from D:\projects\workspace\boost/boost/proto/fusion.hpp:22,
                 from D:\projects\workspace\boost/boost/proto/core.hpp:21,
                 from D:\projects\workspace\boost/boost/proto/proto.hpp:12,
                 from D:\projects\workspace\boost/boost/spirit/home/support/meta_compiler.hpp:19,
                 from D:\projects\workspace\boost/boost/spirit/home/qi/meta_compiler.hpp:14,
                 from D:\projects\workspace\boost/boost/spirit/home/qi/action/action.hpp:14,
                 from D:\projects\workspace\boost/boost/spirit/home/qi/action.hpp:14,
                 from D:\projects\workspace\boost/boost/spirit/home/qi.hpp:14,
                 from D:\projects\workspace\boost/boost/spirit/include/qi.hpp:16,
                 from ..\src\spirit02_test.cpp:11:
D:\projects\workspace\boost/boost/fusion/sequence/intrinsic/at_key.hpp: At global scope:
D:\projects\workspace\boost/boost/fusion/sequence/intrinsic/at_key.hpp: In instantiation of 'boost::fusion::extension::at_key_impl<boost::fusion::non_fusion_tag>::apply<const boost::phoenix::actor<boost::spirit::attribute<0> >, keys::second>':
D:\projects\workspace\boost/boost/fusion/sequence/intrinsic/at_key.hpp:71:9:   instantiated from 'boost::fusion::result_of::at_key<const boost::phoenix::actor<boost::spirit::attribute<0> >, keys::second>'
..\src\spirit02_test.cpp:58:36:   instantiated from here
D:\projects\workspace\boost/boost/fusion/sequence/intrinsic/at_key.hpp:38:17: error: no type named 'type' in 'struct boost::fusion::result_of::find<const boost::phoenix::actor<boost::spirit::attribute<0> >, keys::second>'
..\src\spirit02_test.cpp: In constructor 'G::G()':
..\src\spirit02_test.cpp:58:36: error: no matching function for call to 'at_key(const boost::spirit::_val_type&)'

如果我使用更简单的规则(没有关联性),一切都会编译并正常工作,但这个解决方案有点脆弱:

    // A non-associative solution
    //start_rule %= ( ("first" >> qi::int_) ^ ("second" >> qi::int_) );

为什么我不能使用at_key在语义动作中?有没有更好的方法将“关联”解析为非关联结构?


您需要 at_key 的惰性版本。这为此打补丁 http://boost.2283326.n4.nabble.com/Lazy-at-key-for-phoenix-2-td3746575.html遗憾的是还没有进入精神:

/*=============================================================================
    Copyright (c) 2005-2008 Hartmut Kaiser
    Copyright (c) 2005-2007 Joel de Guzman
    Copyright (c) 2011      Michael Caisse

    Distributed under the Boost Software License, Version 1.0. (See accompanying
    file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
==============================================================================*/
#ifndef PHOENIX_SEQUENCE_AT_KEY_HPP
#define PHOENIX_SEQUENCE_AT_KEY_HPP

#include <boost/fusion/include/at_key.hpp>
#include <boost/spirit/home/phoenix/core/actor.hpp>
#include <boost/spirit/home/phoenix/core/compose.hpp>
#include <boost/type_traits/remove_reference.hpp>

namespace boost { namespace phoenix
{
    template <typename Key>
    struct at_key_eval
    {
        template <typename Env, typename Tuple>
        struct result
        {
            typedef typename Tuple::template result<Env>::type tuple;
            typedef typename
                fusion::result_of::at_key<
                    typename remove_reference<tuple>::type, Key
                >::type
            type;
        };

        template <typename RT, typename Env, typename Tuple>
        static RT
        eval(Env const& env, Tuple const& t)
        {
            return fusion::at_key<Key>(t.eval(env));
        }
    };

    template <typename Key, typename Tuple>
    inline actor<typename as_composite<at_key_eval<Key>, Tuple>::type>
    at_key(Tuple const& tup)
    {
        return compose<at_key_eval<Key> >(tup);
    }

}}

#endif

如果添加的话就可以使用boost::phoenix::at_key:

using boost::phoenix::at_key;

事情会按预期编译和工作。链接的补丁也修改了boost/spirit/home/phoenix/fusion.hpp当然,要包含这个新标头。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 Boost Spirit 和 Fusion 以关联方式解析结构 的相关文章

随机推荐

  • 如何在 Spring 中从 application.properties 重新加载 @Value 属性? [复制]

    这个问题在这里已经有答案了 我有一个spring boot应用 在run文件夹下 有一个额外的配置文件 dir config application properties 当应用程序启动时 它使用文件中的值并将它们注入到 Value my
  • jQuery Mobile:$(...).listview 不是函数

    我正在尝试在 UL 中动态插入 LI 元素后刷新 jQuery Mobile 中的列表视图 每当我尝试 myUL listview refresh 在控制台上我收到错误 未捕获的类型错误 listview 不是函数 我该如何解决这个问题 确
  • R闪亮数据表在开始时不显示记录(行)

    我正在构建一个带有数据表的闪亮应用程序 我想要的是启动时不显示任何记录 行 这样您只能看到表格顶部的过滤器 当您开始输入时 会显示行 我在数据表中找不到选项 这可能吗 下面是示例代码 shinyApp ui navbarPage title
  • 有没有办法拥有租户特定的 JWT 令牌

    我目前正在开发一个 SPA 应用程序 角度 后端使用 Python Flask API 该应用程序将支持多个租户 我对安全概念有点挣扎 我目前正在使用 jwt extend 颁发的 JWT 令牌对所有租户都有效 我当然可以从令牌中获取用户
  • 如何在 MySQL 中求和时间?

    正如您在图片中看到的 我有一份停机报告 显示了所选工厂在选定日期的停机时间 现在我想添加所有的值 Time Duration 列并将其显示在附近的单独显示中 TOTAL TIME DURATION 例如 在图像中 所选日期为 2015 年
  • IE Facebook 应用程序 iFrame 上的会话丢失

    当用户使用 Internet Explorer 时 我的 Facebook 应用程序出现问题 我的应用程序作为 Canvas 页面加载到 iFrame 中 回发后 Cookie 和 Session 将丢失 Firefox 根本不会发生这种情
  • 如何序列化为日期时间

    努力获取任何时区的日期时间 我使用 DateTimeOffset 字符串和 XmlElement 属性 当我这样做时 我收到以下错误 InvalidOperationException 日期时间 是一个无效值 XmlElementAttri
  • cxf 解组错误:意外元素

    我正在尝试使用 SOAP 服务 使用 maven cxf codegen plugin 生成存根 大多数服务一切都很好 除了一个丑陋的服务 在这种情况下 当调用时 服务会发送正确的响应 但我生成的存根无法解组它 生成一个异常 例如 为了简短
  • 行类型 Spark 数据集的编码器

    我想写一个编码器Row https spark apache org docs 2 0 0 api java index html org apache spark sql Row html输入 DataSet 用于我正在执行的地图操作 本
  • 如何从客户端设置 HTMLEditorExtender HTML

    我无法让它工作 这是我在另一个线程中找到的代码 但它对我不起作用 我得到 set content 不是函数 find set content whatever 这仍然有效吗 我还尝试设置它扩展的文本框的值 尝试设置两者的 InnerHtml
  • 从通用对象访问字段变量

    我有两节课ClassOne and ClassTwo 更新公共字段data i e public class ClassOne public byte data new byte 10 Thread that updates data an
  • Swift 2.0:协议扩展:具有相同函数签名的两个协议编译错误

    鉴于这两个协议及其扩展 protocol FirstDelegate func someFunc protocol SecondDelegate func someFunc extension FirstDelegate func some
  • 如何让Maxima的输出更干净?

    我想利用 Maxima 作为后端来解决 LaTeX 输入文件中使用的一些计算 我执行了以下步骤 Step 1 下载并安装 Maxima Step 2 创建一个名为的批处理文件cas bat 例如 如下 rem cas bat echo of
  • 在一元上下文中使用 Data.Map

    我正在操作的地图具有单子键 类型为IO Double 我需要使用findMax在这张地图上 我可以用吗liftM为了这 Map findMax Map fromList f x X f y Y f z Z Here f x有类型IO Dou
  • 获取预转译源代码的 Karma 代码覆盖率

    我使用 Karma 来运行测试 使用 webpack 来捆绑文件 并使用 babel 进行 es6 gt es5 转译 我已经运行了测试并生成了代码覆盖率 但代码覆盖率数字是针对转译后的源文件的 是否有办法获得原始源文件的代码覆盖率 我尝试
  • 3D 旋转 - 透视

    public class MainActivity extends Activity LinearLayout rotator protected void onCreate Bundle savedInstanceState super
  • 如何阻止ubuntu在使用apt安装或更新软件包时弹出“Daemons using outdatedlibraries”? [关闭]

    Closed 这个问题是与编程或软件开发无关 help closed questions 目前不接受答案 我最近新安装了 Ubuntu 22 04 LTS 我发现每次使用 apt 安装或更新软件包时 它都会询问我有关Which servic
  • 在 .NET 的同一解决方案中使用两个 IoC 容器的缺点?

    我正在开发一个项目 该项目使用来自其他开发人员的一组库 该库使用结构图 http structuremap github io作为 IoC 容器 我有代码库 我们合并这些库的应用程序使用统一容器 https learn microsoft
  • 回形针:样式取决于模型(has_many 多态图像)

    我已将模型设置为使用多态图像模型 这工作正常 但是我想知道是否可以更改每个模型的 styles 设置 找到了一些使用 STI 模型 Art has many images as gt imageable Image belongs to i
  • 使用 Boost Spirit 和 Fusion 以关联方式解析结构

    我正在尝试将键值字符串解析为结构 一些键值可能不存在或者顺序不同 所以我想使用boost fusion调整结构 然后解析它at key lt gt 指示 include