c++ - Spirit::Boost编译错误可能与单元素 fusion 序列有关

标签 c++ boost boost-spirit boost-fusion

当我编译以下代码时出现此错误:

boost\spirit\home\qi\detail\assign_to.hpp(164): error C2440: 'static_cast' : cannot convert from 'const wchar_t' to 'element_type'

第 164 行正上方的注释如下:

// This handles the case where the attribute is a single element fusion
// sequence. We silently assign to the only element and treat it as the
// attribute to parse the results into.

我已阅读帖子“Spirit Qi attribute propagation issue with single-member struct”,因此将 qi::eps 添加到所有规则中。但是,这并不能解决问题,所以我也尝试了上面文章中的解决方法 #1 和 #3,但也无济于事。因此,我完全不确定该错误是否与单元素 fusion 序列有关...

我该如何解决这个问题?

-马里奥

#pragma once

#include <string>
#include <vector>

#define BOOST_SPIRIT_UNICODE
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/qi_alternative.hpp>

namespace nsunic = boost::spirit::unicode;
namespace nsqi = boost::spirit::qi;


namespace overmath
{
    struct identifier
    {
        std::wstring name;
    };

    struct assignment
    {
        identifier variable_reference;
        identifier expression;
    };

    struct statement
    {
        assignment assign;
    };

    struct statement_list
    {
        std::vector<statement> statements;
    };

    struct function
    {
        identifier name;
        statement_list slist;
    };

    struct program
    {
        std::vector<function> functions;
    };

}

BOOST_FUSION_ADAPT_STRUCT(
    overmath::identifier,
    (std::wstring, name)
)

BOOST_FUSION_ADAPT_STRUCT(
    overmath::assignment,
    (overmath::identifier, variable_reference)
    (overmath::identifier, expression)
)

BOOST_FUSION_ADAPT_STRUCT(
    overmath::statement,
    (overmath::assignment, assign)
)

BOOST_FUSION_ADAPT_STRUCT(
    overmath::statement_list,
    (std::vector<overmath::statement>, statements)
)

BOOST_FUSION_ADAPT_STRUCT(
    overmath::function,
    (overmath::identifier, name)
    (overmath::statement_list, slist)
)

BOOST_FUSION_ADAPT_STRUCT(
    overmath::program,
    (std::vector<overmath::function>, functions)
)


namespace overmath
{



    template<typename Iterator> struct function_parser : nsqi::grammar<Iterator, program(), nsqi::space_type>
    {
        function_parser() : function_parser::base_type(program)
        {
            identifier %=
                nsqi::eps
                >> +nsqi::alnum;

            assignment %=
                nsqi::eps
                >> identifier
                >> nsqi::char_('=')
                >> identifier;

            statement %=
                nsqi::eps
                >> assignment;

            statement_list %=
                nsqi::eps
                >> +statement;

            function %=
                nsqi::eps
                >> nsqi::lit("def")
                >> identifier
                >> nsqi::char_('(')
                >> nsqi::char_(')')
                >> statement_list
                >> nsqi::lit("enddef");

            program %=
                nsqi::eps
                >> +function;
        }

        nsqi::rule<Iterator, identifier()> identifier;
        nsqi::rule<Iterator, assignment(), nsqi::space_type> assignment;
        nsqi::rule<Iterator, statement(), nsqi::space_type> statement;
        nsqi::rule<Iterator, statement_list(), nsqi::space_type> statement_list;
        nsqi::rule<Iterator, function(), nsqi::space_type> function;
        nsqi::rule<Iterator, program(), nsqi::space_type> program;
    };


    template<typename Iterator> std::wstring parse(Iterator first, Iterator last)
    {
        using nsqi::phrase_parse;

        program f;
        function_parser<Iterator> fp;

        auto b = phrase_parse(first, last, fp, nsqi::space, f);
        if(b)
        {
            return std::wstring(L"OK");
        }
        return std::wstring(L"FAIL");
    }

}

最佳答案

你的一些规则有一个常见的问题,即在你链接的问题中解释的适应结构中有一些类似容器的东西作为单个元素,但是你已经通过添加 qi::eps 回避了它(即使它并不是真正需要的)。

您的代码的错误是由于您的 assignment规则。它的属性为 overmath::assignment这基本上是 your_attr=tuple<identifier,identifier> .如果我们分析它的综合属性,我们会发现它是 synt_attr=tuple<identifier,wchar_t,identifier> .当 Spirit 解析您的规则时,它会尝试将综合属性分配给您的属性。它将 synt_attr 的第一个元素分配给 your_attr(标识符到标识符,没问题),然后它尝试分配第二个元素(wchar_t 到标识符)但它不起作用。由于标识符是一个改编的结构(基本上是一个 fusion 序列 tuple<wstring> ),它使 wchar_t 成为一个单一的元素序列 tuple<wchar_t>并尝试分配它(wchar_t 到 wstring,但失败),导致错误。

所以问题是您有一个不应该存在的额外 wchar_t。这是由于您使用了 char_('=') , 如果你使用 lit('=') (甚至 omit[char_('=')] )它应该可以工作。

关于c++ - Spirit::Boost编译错误可能与单元素 fusion 序列有关,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34135919/

相关文章:

c++ - 使类不可 move 的用例(如果有)是什么?

c++ - Boost C++ - 搜索 spirit 符号表

c++ - 通过 unique_ptr 访问 std::array

C++设计相关问题

c++ - CMake 的 FindBoost 功能的输出可以静音吗?

c++ - 升压.x3 : attribute accumulates between alternatives

C++ boost::lambda::ret 等价于 phoenix

c# - 未导出成员函数时从 C# 调用 C++ native /非托管成员函数

c++ - 设置输出引脚上忽略的媒体类型

c++ - 在 ptr_list 中 boost shared_ptr