Spirit :: Boost编译错误可能与单个元素融合序列有关

时间:2015-12-07 14:27:10

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

当我编译以下代码时,我收到此错误:

  

boost \ spirit \ home \ qi \ detail \ assign_to.hpp(164):错误C2440:'static_cast':无法从'const wchar_t'转换为'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的解决方法,但也无济于事。因此,我不确定错误是否与单个元素融合序列有关......

如何解决这个问题?

-Mario

#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");
    }

}

1 个答案:

答案 0 :(得分:0)

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

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

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