Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/jpa/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++11 普通语法的Boost spirit编译错误_C++11_Compiler Errors_Boost Spirit - Fatal编程技术网

C++11 普通语法的Boost spirit编译错误

C++11 普通语法的Boost spirit编译错误,c++11,compiler-errors,boost-spirit,C++11,Compiler Errors,Boost Spirit,我正在尝试使用以下规则编译解析器: else_statement = lit("else") > statement; if_statement = lit("if") >> '(' >> expression >> ')' >> statement >> -else_statement; else\u语句的属性是语句,它使用的语句规则也是如此。if_语句的属性是一个结构,其成员分别为expression、st

我正在尝试使用以下规则编译解析器:

else_statement =
    lit("else") > statement;

if_statement =
    lit("if") >> '(' >> expression >> ')' >> statement >> -else_statement;
else\u语句
的属性是
语句
,它使用的
语句
规则也是如此。
if_语句
的属性是一个结构,其成员分别为
expression
statement
和可选的
语句(
boost::optional

使用以下
BOOST\u FUSION\u ADAPT\u STRUCT

BOOST_FUSION_ADAPT_STRUCT(ast::statement, m_statement_node)
BOOST_FUSION_ADAPT_STRUCT(ast::if_statement, m_condition, m_then, m_else)
其中
m_statement_node
是一个
boost::variant
,用于可能的不同语句

我希望如果存在
else\u语句
,它将被放入
boost::optional
,因为
else\u语句
的属性是
语句
。如果我在
else\u语句
规则中注释掉
lit(“else”)>
,这个就行了!但是随着
lit(“else”)
present出现了一些奇怪的情况:现在boost::spirit正在尝试将
语句
放入可选的
语句(boost::variant)的成员中,该语句显然不会编译,因为它只需要a或B

产生的编译错误如下所示:

/usr/include/boost/variant/variant.hpp:1534:38: error: no matching function for call to ‘boost::variant<ast::A, ast::B>::initializer::initialize(void*, const ast::statement&)’

自动属性传播规则在包含单个元素的融合序列中存在一些问题。您可以通过声明以下内容来解决此问题:

rule<ast::statement_node> statement;
然后为其添加一个值:

statement = (a | b) >> attr(42);
这也消除了混淆

// File: so.cpp
// Compile as: g++ -std=c++11 so.cpp
//#define BOOST_SPIRIT_DEBUG

#include <boost/spirit/include/qi.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/fusion/include/std_pair.hpp>
#include <boost/optional/optional_io.hpp>
#include <iostream>
#include <string>
#include <vector>

namespace ast
{

    struct A { int a; friend std::ostream& operator<<(std::ostream& os, A const&) { return os << "A"; } };
    struct B { int b; friend std::ostream& operator<<(std::ostream& os, B const&) { return os << "B"; } };
    struct expression { int e; friend std::ostream& operator<<(std::ostream& os, expression const&) { return os << "expression"; } };

    using statement_node = boost::variant<A, B>;

    struct statement
    {
        statement_node m_statement_node;
        int dummy;

        friend std::ostream& operator<<(std::ostream& os, statement const& statement)
        { return os << "STATEMENT:" << statement.m_statement_node; }
    };

    struct if_statement
    {
        expression m_condition;
        statement m_then;
        boost::optional<statement> m_else;

        friend std::ostream& operator<<(std::ostream& os, if_statement const& if_statement)
        {
            os << "IF_STATEMENT:" << if_statement.m_condition << "; " << if_statement.m_then;
            if (if_statement.m_else)
                os << "; " << if_statement.m_else;
            return os;
        }
    };

} // namespace ast

    BOOST_FUSION_ADAPT_STRUCT(ast::expression, e)
    BOOST_FUSION_ADAPT_STRUCT(ast::A, a)
    BOOST_FUSION_ADAPT_STRUCT(ast::B, b)
    BOOST_FUSION_ADAPT_STRUCT(ast::statement, m_statement_node, dummy)
    BOOST_FUSION_ADAPT_STRUCT(ast::if_statement, m_condition, m_then, m_else)

    namespace client
{

    namespace qi = boost::spirit::qi;
    namespace ascii = boost::spirit::ascii;

    template <typename Iterator>
        class test_grammar : public qi::grammar<Iterator, ast::if_statement(), qi::space_type>
    {
        private:
            template<typename T> using rule = qi::rule<Iterator, T(), qi::space_type>;

            rule<ast::A>            a;
            rule<ast::B>            b;
            rule<ast::statement> statement;
            rule<ast::statement> else_statement;
            rule<ast::if_statement> if_statement;
            rule<int>               expression;

        public:
            test_grammar() : test_grammar::base_type(if_statement, "result_grammar")
        {
            using namespace qi;

            statement = (a | b) >> attr(42);

            else_statement = lit("else") > statement;

            if_statement = lit("if") >> '(' >> expression >> ')' >> statement >> -else_statement;

            expression = int_;

            a = 'A' >> attr(1);
            b = 'B' >> attr(2);

            BOOST_SPIRIT_DEBUG_NODES( (statement) (else_statement) (if_statement) (expression) (a) (b));
        }
    };

} // namespace client

int main()
{
    for (std::string const input : {
                "if (1) A else B",
            }) 
    {
        using iterator_type = std::string::const_iterator;
        using test_grammar  = client::test_grammar<iterator_type>;
        namespace qi        = boost::spirit::qi;

        test_grammar program;
        iterator_type iter = input.begin(), end = input.end();
        ast::if_statement out;
        bool r = qi::phrase_parse(iter, end, program, qi::space, out);

        if (!r || iter != end)
        {
            std::cerr << "Parsing failed." << std::endl;
            return 1;
        }
        std::cout << "Parsed: " << out << std::endl;
    }
}
背景 但是,请注意,如果您错误地将
else\u语句
规则的长度也设置为相同的长度,则会得到相同的混淆:

else_statement = lit("else") > statement > attr(42); // this is wrong
当然,这实际上没有什么意义,但错误消息确实有助于解释引擎盖下的真正问题(如果“上游”融合序列看起来“兼容”,那么它是“解构”的传播)。qi/nonterminal/rule.hpp中的相关注释:

// do up-stream transformation, this integrates the results
// back into the original attribute value, if appropriate
traits::post_transform(attr_param, attr_);

非常感谢您的快速回答!“make
else\u语句
相同长度”是否表示与语句相同的元素数(2)?或者它们也必须是相同的类型吗?我认为这只是长度,但“错误的启发式”只有在单元素(子)序列变平时才会发生。在大多数情况下,这会产生最佳的自动属性兼容性效果。可悲的是,所有足够复杂的“魔法”都会导致像这样的边缘问题
Parsed: IF_STATEMENT:expression; STATEMENT:A;  STATEMENT:B
else_statement = lit("else") > statement > attr(42); // this is wrong
// do up-stream transformation, this integrates the results
// back into the original attribute value, if appropriate
traits::post_transform(attr_param, attr_);