Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/143.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
在'之前应为不合格id;名称空间';使用“精神之气”时出错 我写了一个C++应用程序,有几个复杂的结构和_C++_Boost Spirit Qi - Fatal编程技术网

在'之前应为不合格id;名称空间';使用“精神之气”时出错 我写了一个C++应用程序,有几个复杂的结构和

在'之前应为不合格id;名称空间';使用“精神之气”时出错 我写了一个C++应用程序,有几个复杂的结构和,c++,boost-spirit-qi,C++,Boost Spirit Qi,我想读取一个字符串并用文本中提供的数据填充这些结构 但为了便于理解和调试,我编写了带有相同问题的easy程序 这是我的代码: #include <string> #include <iostream> #define FUSION_MAX_VECTOR_SIZE 30 #define BOOST_PHOENIX_USE_V2_OVER_V3 #include <boost/spirit/home/phoenix/bind/bind_function.hpp&g

我想读取一个字符串并用文本中提供的数据填充这些结构

但为了便于理解和调试,我编写了带有相同问题的easy程序

这是我的代码:

#include <string>
#include <iostream>

#define FUSION_MAX_VECTOR_SIZE  30
#define BOOST_PHOENIX_USE_V2_OVER_V3

#include <boost/spirit/home/phoenix/bind/bind_function.hpp>
#include <boost/phoenix/bind.hpp>
#include <boost/fusion/adapted.hpp>
#include <boost/spirit/include/qi.hpp>


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

using qi::double_;
using qi::char_;
using qi::lexeme;
using qi::int_;
using qi::lit;
using qi::_1;
using ascii::space;
using phoenix::ref;
using qi::parser;


class Test 
{
    // Class fields
    std::string test_str;
    public:

        Test(std::string& sample_str)
        {
            test_str = sample_str;
        }

        struct fruit
        {
            std::string name;
            std::string color;
        };
        BOOST_FUSION_ADAPT_STRUCT
            (
             fruit,
             (std::string, name)
             (std::string, color)
            );      
        struct person
        {
            std::string name;
            int age;
        };

        BOOST_FUSION_ADAPT_STRUCT
            (
             person,
             (std::string, name)
             (int, age)
            );

        void received_person(person& p)
        {
            std::cout << p.name << " with age"<< p.age<< " has been seen!"<<std::endl;
        }
        void received_fruit(fruit& f)
        {
            std::cout << f.name<<" is "<<f.color<<std::endl;
        }

        template <typename Iterator>
            struct MyGrammar : boost::spirit::qi::grammar<Iterator, void()>
        {
            MyGrammar() : MyGrammar::base_type(my_item)
            {
                my_item = *(fruit[ boost::phoenix::bind(&received_fruit, boost::spirit::_1 )]
                        |
                        _person[ boost::phoenix::bind(&received_person, boost::spirit::_1 )]
                        );

                 _person = qi::lit('(') >> *(qi::char_ - ',') >> ',' >> qi::int_ >> ')';
                _fruit = qi::lit('[') >> *(qi::char_ - ',') >> ',' >> *(qi::char_) >> ']';


            }
            qi::rule<Iterator, void()> my_item;
            qi::rule<Iterator, person()> _person;
            qi::rule<Iterator, fruit()> _fruit;
        };

        void run()
        {
            typedef std::string::const_iterator iterator;
            MyGrammar <std::string::const_iterator> my_grammar;
            std::string::const_iterator begin = test_str.begin();
            std::string::const_iterator end = test_str.end();
            bool result_ = qi::parse(begin, end, my_grammar) && begin == end;
        }
};


int main()
{
    std::string input("(jane, 23000)(david, 19)(mary, 30)[yello,100][green, 60.6][red, 30.5]");

    Test test(input);
    test.run();

    return 0;
}
我知道这段代码可以不用类来编写,但我想在主项目中使用类。 非常感谢

解决这些问题,首先:
  • BOOST\u FUSION\u ADAPT\u结构需要位于全局命名空间

    宏应该在全局范围内使用,struct_name应该是要调整的结构的完全命名空间限定名。[]

  • 您需要一个skipper来允许在示例输入中使用空格

    • 这也意味着您需要
      qi::phrase\u parse
      来提供一个跳过程序
    • 这也意味着
      begin==end
      是冗余的(因为
      qi::parse
      总是在AFAIR成功时消耗整个输入)
    • 这还意味着您需要
      qi::lexeme
      来控制何时将空白作为解析内容的一部分
  • 您需要回调是
    静态的

  • 您需要修改
    \u fruit
    规则以读取,直到关闭
    ]
  • 有了这些,您的代码就可以工作了:请参见

    奖金材料 以防万一你不知道,如果你不想,你不必跳过所有这些融合/凤凰圈。通常先解析数据结构,然后在那里进行处理

    请参见演示的

    例如,数据结构:

    namespace ast {
        struct fruit {
            std::string name;
            std::string color;
        };
        struct person {
            std::string name;
            int age;
        };
    
        typedef boost::variant<fruit, person> record;
        typedef std::vector<record> records;
    
        // for our demo output:
        static std::ostream& operator<<(std::ostream& os, fruit const& f);
        static std::ostream& operator<<(std::ostream& os, person const& p);
    }
    
    以下是

    #include <string>
    #include <iostream>
    #include <boost/fusion/adapted/struct.hpp>
    #include <boost/spirit/include/qi.hpp>
    
    namespace qi = boost::spirit::qi;
    
    namespace ast {
        struct fruit {
            std::string name;
            std::string color;
    
            friend std::ostream& operator<<(std::ostream& os, fruit const& f) { return os << f.name << " is " << f.color; }
        };
        struct person {
            std::string name;
            int age;
    
            friend std::ostream& operator<<(std::ostream& os, person const& p) { return os << p.name << " with age" << p.age << " has been seen!"; }
        };
    
        typedef boost::variant<fruit, person> record;
        typedef std::vector<record> records;
    }
    
    BOOST_FUSION_ADAPT_STRUCT(ast::fruit,
        (std::string, name)
        (std::string, color))
    
    BOOST_FUSION_ADAPT_STRUCT(ast::person,
        (std::string, name)
        (int, age))
    
    template <typename Iterator, typename Skipper = qi::space_type>
        struct MyGrammar : qi::grammar<Iterator, ast::records(), Skipper>
    {
        MyGrammar() : MyGrammar::base_type(_start)
        {
            _text   = qi::lexeme [ *~qi::char_(",)]") ];
            _person = qi::lit('(') >> _text >> ',' >> qi::int_ >> ')';
            _fruit  = qi::lit('[') >> _text >> ',' >> _text >> ']';
    
            _start  = *(_fruit | _person);
        }
    
        qi::rule<Iterator, ast::records(), Skipper> _start;
        qi::rule<Iterator, ast::person(),  Skipper> _person;
        qi::rule<Iterator, ast::fruit(),   Skipper> _fruit;
        qi::rule<Iterator, std::string()>           _text;
    };
    
    int main()
    {
        typedef std::string::const_iterator It;
        std::string const input("(jane, 23000)(david, 19)(mary, 30)[yello,100][green, 60.6][red, 30.5]");
    
        MyGrammar <It> my_grammar;
    
        It begin(input.begin()), end(input.end());
    
        ast::records data;
        if (qi::phrase_parse(begin, end, my_grammar, qi::space, data))
        {
            std::cout << "Parse success\n";
            for (auto& r : data)
                std::cout << r << "\n";
        }
        else
            std::cout << "Parse failed\n";
    
        if (begin != end)
            std::cout << "Remaining unparsed: '" << std::string(begin, end) << "'\n";
    }
    
    #包括
    #包括
    #包括
    #包括
    名称空间qi=boost::spirit::qi;
    名称空间ast{
    结构果{
    std::字符串名;
    字符串颜色;
    friend std::ostream&operator>','>>_text>>'];
    _开始=*(|水果|人);
    }
    qi::规则_开始;
    齐:规则,人;
    齐:规则,水果;
    qi::规则_文本;
    };
    int main()
    {
    typedef std::string::const_迭代器It;
    std::字符串常量输入(“(简,23000)(大卫,19)(玛丽,30)[yello,100][green,60.6][red,30.5]”);
    我的语法我的语法;
    它开始(input.begin()),结束(input.end());
    ast::记录数据;
    if(qi::短语解析(开始、结束、我的语法、qi::空格、数据))
    {
    
    std::cout哪一行有错误?第44行生成此错误!在BOOST\u FUSION\u ADAPT\u结构之前,上面没有行号。在为fruit结构定义BOOST\u FUSION\u ADAPT\u结构的行中,我猜BOOST\u FUSION\u ADAPT\u结构宏正在做一些不允许它作为类的子级的事情。我建议研究这正是BOOST_FUSION_ADAPT_STRUCT所做的。此外,您可以尝试将声明移到类之外,看看这是否有帮助(这可能不符合您的预期设计,但可能有助于诊断)。啊。我刚刚添加了一个没有phoenix的版本。请注意,我的版本重72行代码(少40行),而它可以说做的更多。PS(为什么要使用Phoenix V2而不是V3?我不推荐这样做,因为缺乏支持/bug)。请看,我使用Phoenix V2而不是V3来使用Phoenix bind。V3也有bind,它有更多的功能和更少的bug
    int main()
    {
        typedef std::string::const_iterator It;
        std::string const input("(jane, 23000)(david, 19)(mary, 30)[yello,100][green, 60.6][red, 30.5]");
    
        MyGrammar <It> my_grammar;
    
        It begin(input.begin()), end(input.end());
    
        ast::records data;
        if (qi::phrase_parse(begin, end, my_grammar, qi::space, data))
        {
            std::cout << "Parse success\n";
            for (auto const& record : data)
                std::cout << record << "\n";
        }
        else
            std::cout << "Parse failed\n";
    
        if (begin != end)
            std::cout << "Remaining unparsed: '" << std::string(begin, end) << "'\n";
    }
    
        _text   = qi::lexeme [ *~qi::char_(",)]") ];
        _person = qi::lit('(') >> _text >> ',' >> qi::int_ >> ')';
        _fruit  = qi::lit('[') >> _text >> ',' >> _text >> ']';
    
        _start  = *(_fruit | _person);
    
    #include <string>
    #include <iostream>
    #include <boost/fusion/adapted/struct.hpp>
    #include <boost/spirit/include/qi.hpp>
    
    namespace qi = boost::spirit::qi;
    
    namespace ast {
        struct fruit {
            std::string name;
            std::string color;
    
            friend std::ostream& operator<<(std::ostream& os, fruit const& f) { return os << f.name << " is " << f.color; }
        };
        struct person {
            std::string name;
            int age;
    
            friend std::ostream& operator<<(std::ostream& os, person const& p) { return os << p.name << " with age" << p.age << " has been seen!"; }
        };
    
        typedef boost::variant<fruit, person> record;
        typedef std::vector<record> records;
    }
    
    BOOST_FUSION_ADAPT_STRUCT(ast::fruit,
        (std::string, name)
        (std::string, color))
    
    BOOST_FUSION_ADAPT_STRUCT(ast::person,
        (std::string, name)
        (int, age))
    
    template <typename Iterator, typename Skipper = qi::space_type>
        struct MyGrammar : qi::grammar<Iterator, ast::records(), Skipper>
    {
        MyGrammar() : MyGrammar::base_type(_start)
        {
            _text   = qi::lexeme [ *~qi::char_(",)]") ];
            _person = qi::lit('(') >> _text >> ',' >> qi::int_ >> ')';
            _fruit  = qi::lit('[') >> _text >> ',' >> _text >> ']';
    
            _start  = *(_fruit | _person);
        }
    
        qi::rule<Iterator, ast::records(), Skipper> _start;
        qi::rule<Iterator, ast::person(),  Skipper> _person;
        qi::rule<Iterator, ast::fruit(),   Skipper> _fruit;
        qi::rule<Iterator, std::string()>           _text;
    };
    
    int main()
    {
        typedef std::string::const_iterator It;
        std::string const input("(jane, 23000)(david, 19)(mary, 30)[yello,100][green, 60.6][red, 30.5]");
    
        MyGrammar <It> my_grammar;
    
        It begin(input.begin()), end(input.end());
    
        ast::records data;
        if (qi::phrase_parse(begin, end, my_grammar, qi::space, data))
        {
            std::cout << "Parse success\n";
            for (auto& r : data)
                std::cout << r << "\n";
        }
        else
            std::cout << "Parse failed\n";
    
        if (begin != end)
            std::cout << "Remaining unparsed: '" << std::string(begin, end) << "'\n";
    }