使用 Boost Spirit 解析带有数组的结构
Parsing struct with arrays with Boost Spirit
在我开始之前,是的,我知道有很多 post 与这个主题相关,我花了一天多的时间阅读,但我对 Boost::spirit 的了解有限,所以我可以弄清楚如何解决我的问题。
我拿Boost Employee的例子修改,给大家看
#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/phoenix_object.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/fusion/include/io.hpp>
#include <iostream>
#include <string>
#include <complex>
namespace client
{
namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;
///////////////////////////////////////////////////////////////////////////
// Our employee struct
///////////////////////////////////////////////////////////////////////////
//[tutorial_employee_struct
struct employee
{
char user[31];
char pass[34];
uint16_t page; // Pagina de usuarios
uint16_t port; // Puerto por donde es realiza la comunicación
uint8_t ip[4]; // Direccion del socket de juego
uint16_t amount;
uint16_t cents;
char nick[9];
uint8_t already_logged;
uint8_t version;
uint8_t extension;
};
}
// We need to tell fusion about our employee struct
// to make it a first-class fusion citizen. This has to
// be in global scope.
//[tutorial_employee_adapt_struct
BOOST_FUSION_ADAPT_STRUCT(
client::employee,
(char, user[31])
(char, pass[34])
(uint16_t, page)
(uint16_t, port)
(uint8_t, ip[4])
(uint16_t, amount)
(uint16_t, cents)
(char, nick[9])
(uint8_t, already_logged)
(uint8_t, version)
(uint8_t, extension)
)
//]
namespace client
{
///////////////////////////////////////////////////////////////////////////////
// Our employee parser
///////////////////////////////////////////////////////////////////////////////
//[tutorial_employee_parser
template <typename Iterator>
struct employee_parser : qi::grammar<Iterator, employee(), ascii::space_type>
{
employee_parser() : employee_parser::base_type(start)
{
using boost::spirit::qi::ushort_;
using ascii::char_;
start %=
char_ >> ','
>> char_ >> ','
>> ushort_ >> ','
;
}
qi::rule<Iterator, employee(), ascii::space_type> start;
};
//]
}
////////////////////////////////////////////////////////////////////////////
// Main program
////////////////////////////////////////////////////////////////////////////
int
main()
{
std::cout << "/////////////////////////////////////////////////////////\n\n";
std::cout << "\t\tAn employee parser for Spirit...\n\n";
std::cout << "/////////////////////////////////////////////////////////\n\n";
std::cout
<< "Give me an employee of the form :"
<< "employee{age, \"surname\", \"forename\", salary } \n";
std::cout << "Type [q or Q] to quit\n\n";
using boost::spirit::ascii::space;
typedef std::string::const_iterator iterator_type;
typedef client::employee_parser<iterator_type> employee_parser;
employee_parser g; // Our grammar
std::string str;
while (getline(std::cin, str))
{
if (str.empty() || str[0] == 'q' || str[0] == 'Q')
break;
client::employee emp;
std::string::const_iterator iter = str.begin();
std::string::const_iterator end = str.end();
bool r = phrase_parse(iter, end, g, space, emp);
if (r && iter == end)
{
std::cout << boost::fusion::tuple_open('[');
std::cout << boost::fusion::tuple_close(']');
std::cout << boost::fusion::tuple_delimiter(", ");
std::cout << "-------------------------\n";
std::cout << "Parsing succeeded\n";
std::cout << "got: " << boost::fusion::as_vector(emp) << std::endl;
std::cout << "\n-------------------------\n";
}
else
{
std::cout << "-------------------------\n";
std::cout << "Parsing failed\n";
std::cout << "-------------------------\n";
}
}
std::cout << "Bye... :-) \n\n";
return 0;
}
但是我遇到了这个编译错误,我不知道如何解决它或如何编写解析器
In file included from /usr/include/boost/fusion/include/as_vector.hpp:11:0,
from /usr/include/boost/spirit/home/support/attributes.hpp:24,
from /usr/include/boost/spirit/home/qi/detail/attributes.hpp:12,
from /usr/include/boost/spirit/home/qi/action/action.hpp:16,
from /usr/include/boost/spirit/home/qi/action.hpp:14,
from /usr/include/boost/spirit/home/qi.hpp:14,
from /usr/include/boost/spirit/include/qi.hpp:16,
from user.cpp:17:
/usr/include/boost/fusion/container/vector/convert.hpp: In instantiation of ‘struct boost::fusion::result_of::as_vector<const client::employee>’:
/usr/include/boost/fusion/container/vector/convert.hpp:43:5: required by substitution of ‘template<class Sequence> typename boost::fusion::result_of::as_vector<const Sequence>::type boost::fusion::as_vector(const Sequence&) [with Sequence = client::employee]’
user.cpp:140:65: required from here
/usr/include/boost/fusion/container/vector/convert.hpp:27:13: error: invalid use of incomplete type ‘struct boost::fusion::detail::as_vector<11>’
type;
^
In file included from /usr/include/boost/fusion/container/vector/convert.hpp:11:0,
from /usr/include/boost/fusion/include/as_vector.hpp:11,
from /usr/include/boost/spirit/home/support/attributes.hpp:24,
from /usr/include/boost/spirit/home/qi/detail/attributes.hpp:12,
from /usr/include/boost/spirit/home/qi/action/action.hpp:16,
from /usr/include/boost/spirit/home/qi/action.hpp:14,
from /usr/include/boost/spirit/home/qi.hpp:14,
from /usr/include/boost/spirit/include/qi.hpp:16,
from user.cpp:17:
/usr/include/boost/fusion/container/vector/detail/as_vector.hpp:26:12: error: declaration of ‘struct boost::fusion::detail::as_vector<11>’
struct as_vector;
^
In file included from /usr/include/boost/fusion/include/as_vector.hpp:11:0,
from /usr/include/boost/spirit/home/support/attributes.hpp:24,
from /usr/include/boost/spirit/home/qi/detail/attributes.hpp:12,
from /usr/include/boost/spirit/home/qi/action/action.hpp:16,
from /usr/include/boost/spirit/home/qi/action.hpp:14,
from /usr/include/boost/spirit/home/qi.hpp:14,
from /usr/include/boost/spirit/include/qi.hpp:16,
from user.cpp:17:
/usr/include/boost/fusion/container/vector/convert.hpp: In instantiation of ‘struct boost::fusion::result_of::as_vector<client::employee>’:
/usr/include/boost/fusion/container/vector/convert.hpp:34:5: required by substitution of ‘template<class Sequence> typename boost::fusion::result_of::as_vector<Sequence>::type boost::fusion::as_vector(Sequence&) [with Sequence = client::employee]’
user.cpp:140:65: required from here
/usr/include/boost/fusion/container/vector/convert.hpp:27:13: error: invalid use of incomplete type ‘struct boost::fusion::detail::as_vector<11>’
type;
^
In file included from /usr/include/boost/fusion/container/vector/convert.hpp:11:0,
from /usr/include/boost/fusion/include/as_vector.hpp:11,
from /usr/include/boost/spirit/home/support/attributes.hpp:24,
from /usr/include/boost/spirit/home/qi/detail/attributes.hpp:12,
from /usr/include/boost/spirit/home/qi/action/action.hpp:16,
from /usr/include/boost/spirit/home/qi/action.hpp:14,
from /usr/include/boost/spirit/home/qi.hpp:14,
from /usr/include/boost/spirit/include/qi.hpp:16,
from user.cpp:17:
/usr/include/boost/fusion/container/vector/detail/as_vector.hpp:26:12: error: declaration of ‘struct boost::fusion::detail::as_vector<11>’
struct as_vector;
^
user.cpp: In function ‘int main()’:
user.cpp:140:65: error: no matching function for call to ‘as_vector(client::employee&)’
std::cout << "got: " << boost::fusion::as_vector(emp) << std::endl;
^
user.cpp:140:65: note: candidates are:
In file included from /usr/include/boost/fusion/include/as_vector.hpp:11:0,
from /usr/include/boost/spirit/home/support/attributes.hpp:24,
from /usr/include/boost/spirit/home/qi/detail/attributes.hpp:12,
from /usr/include/boost/spirit/home/qi/action/action.hpp:16,
from /usr/include/boost/spirit/home/qi/action.hpp:14,
from /usr/include/boost/spirit/home/qi.hpp:14,
from /usr/include/boost/spirit/include/qi.hpp:16,
from user.cpp:17:
/usr/include/boost/fusion/container/vector/convert.hpp:34:5: note: template<class Sequence> typename boost::fusion::result_of::as_vector<Sequence>::type boost::fusion::as_vector(Sequence&)
as_vector(Sequence& seq)
^
/usr/include/boost/fusion/container/vector/convert.hpp:34:5: note: substitution of deduced template arguments resulted in errors seen above
/usr/include/boost/fusion/container/vector/convert.hpp:43:5: note: template<class Sequence> typename boost::fusion::result_of::as_vector<const Sequence>::type boost::fusion::as_vector(const Sequence&)
as_vector(Sequence const& seq)
^
/usr/include/boost/fusion/container/vector/convert.hpp:43:5: note: substitution of deduced template arguments resulted in errors seen above
我只需要有一个固定大小的结构,这就是使用 char XXX[31] 的原因,但我可以为任何具有固定大小的声明更改它。
提前致谢
您有超过 10 个字段。您需要提高 fusion/container/vector/limits.hpp
.
中的默认序列大小限制
在包含任何 boost fusion header(或任何 boost header 因为许多库可能隐式包含它)之前包含它:
#define FUSION_MAX_VECTOR_SIZE 15
在我开始之前,是的,我知道有很多 post 与这个主题相关,我花了一天多的时间阅读,但我对 Boost::spirit 的了解有限,所以我可以弄清楚如何解决我的问题。
我拿Boost Employee的例子修改,给大家看
#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/phoenix_object.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/fusion/include/io.hpp>
#include <iostream>
#include <string>
#include <complex>
namespace client
{
namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;
///////////////////////////////////////////////////////////////////////////
// Our employee struct
///////////////////////////////////////////////////////////////////////////
//[tutorial_employee_struct
struct employee
{
char user[31];
char pass[34];
uint16_t page; // Pagina de usuarios
uint16_t port; // Puerto por donde es realiza la comunicación
uint8_t ip[4]; // Direccion del socket de juego
uint16_t amount;
uint16_t cents;
char nick[9];
uint8_t already_logged;
uint8_t version;
uint8_t extension;
};
}
// We need to tell fusion about our employee struct
// to make it a first-class fusion citizen. This has to
// be in global scope.
//[tutorial_employee_adapt_struct
BOOST_FUSION_ADAPT_STRUCT(
client::employee,
(char, user[31])
(char, pass[34])
(uint16_t, page)
(uint16_t, port)
(uint8_t, ip[4])
(uint16_t, amount)
(uint16_t, cents)
(char, nick[9])
(uint8_t, already_logged)
(uint8_t, version)
(uint8_t, extension)
)
//]
namespace client
{
///////////////////////////////////////////////////////////////////////////////
// Our employee parser
///////////////////////////////////////////////////////////////////////////////
//[tutorial_employee_parser
template <typename Iterator>
struct employee_parser : qi::grammar<Iterator, employee(), ascii::space_type>
{
employee_parser() : employee_parser::base_type(start)
{
using boost::spirit::qi::ushort_;
using ascii::char_;
start %=
char_ >> ','
>> char_ >> ','
>> ushort_ >> ','
;
}
qi::rule<Iterator, employee(), ascii::space_type> start;
};
//]
}
////////////////////////////////////////////////////////////////////////////
// Main program
////////////////////////////////////////////////////////////////////////////
int
main()
{
std::cout << "/////////////////////////////////////////////////////////\n\n";
std::cout << "\t\tAn employee parser for Spirit...\n\n";
std::cout << "/////////////////////////////////////////////////////////\n\n";
std::cout
<< "Give me an employee of the form :"
<< "employee{age, \"surname\", \"forename\", salary } \n";
std::cout << "Type [q or Q] to quit\n\n";
using boost::spirit::ascii::space;
typedef std::string::const_iterator iterator_type;
typedef client::employee_parser<iterator_type> employee_parser;
employee_parser g; // Our grammar
std::string str;
while (getline(std::cin, str))
{
if (str.empty() || str[0] == 'q' || str[0] == 'Q')
break;
client::employee emp;
std::string::const_iterator iter = str.begin();
std::string::const_iterator end = str.end();
bool r = phrase_parse(iter, end, g, space, emp);
if (r && iter == end)
{
std::cout << boost::fusion::tuple_open('[');
std::cout << boost::fusion::tuple_close(']');
std::cout << boost::fusion::tuple_delimiter(", ");
std::cout << "-------------------------\n";
std::cout << "Parsing succeeded\n";
std::cout << "got: " << boost::fusion::as_vector(emp) << std::endl;
std::cout << "\n-------------------------\n";
}
else
{
std::cout << "-------------------------\n";
std::cout << "Parsing failed\n";
std::cout << "-------------------------\n";
}
}
std::cout << "Bye... :-) \n\n";
return 0;
}
但是我遇到了这个编译错误,我不知道如何解决它或如何编写解析器
In file included from /usr/include/boost/fusion/include/as_vector.hpp:11:0,
from /usr/include/boost/spirit/home/support/attributes.hpp:24,
from /usr/include/boost/spirit/home/qi/detail/attributes.hpp:12,
from /usr/include/boost/spirit/home/qi/action/action.hpp:16,
from /usr/include/boost/spirit/home/qi/action.hpp:14,
from /usr/include/boost/spirit/home/qi.hpp:14,
from /usr/include/boost/spirit/include/qi.hpp:16,
from user.cpp:17:
/usr/include/boost/fusion/container/vector/convert.hpp: In instantiation of ‘struct boost::fusion::result_of::as_vector<const client::employee>’:
/usr/include/boost/fusion/container/vector/convert.hpp:43:5: required by substitution of ‘template<class Sequence> typename boost::fusion::result_of::as_vector<const Sequence>::type boost::fusion::as_vector(const Sequence&) [with Sequence = client::employee]’
user.cpp:140:65: required from here
/usr/include/boost/fusion/container/vector/convert.hpp:27:13: error: invalid use of incomplete type ‘struct boost::fusion::detail::as_vector<11>’
type;
^
In file included from /usr/include/boost/fusion/container/vector/convert.hpp:11:0,
from /usr/include/boost/fusion/include/as_vector.hpp:11,
from /usr/include/boost/spirit/home/support/attributes.hpp:24,
from /usr/include/boost/spirit/home/qi/detail/attributes.hpp:12,
from /usr/include/boost/spirit/home/qi/action/action.hpp:16,
from /usr/include/boost/spirit/home/qi/action.hpp:14,
from /usr/include/boost/spirit/home/qi.hpp:14,
from /usr/include/boost/spirit/include/qi.hpp:16,
from user.cpp:17:
/usr/include/boost/fusion/container/vector/detail/as_vector.hpp:26:12: error: declaration of ‘struct boost::fusion::detail::as_vector<11>’
struct as_vector;
^
In file included from /usr/include/boost/fusion/include/as_vector.hpp:11:0,
from /usr/include/boost/spirit/home/support/attributes.hpp:24,
from /usr/include/boost/spirit/home/qi/detail/attributes.hpp:12,
from /usr/include/boost/spirit/home/qi/action/action.hpp:16,
from /usr/include/boost/spirit/home/qi/action.hpp:14,
from /usr/include/boost/spirit/home/qi.hpp:14,
from /usr/include/boost/spirit/include/qi.hpp:16,
from user.cpp:17:
/usr/include/boost/fusion/container/vector/convert.hpp: In instantiation of ‘struct boost::fusion::result_of::as_vector<client::employee>’:
/usr/include/boost/fusion/container/vector/convert.hpp:34:5: required by substitution of ‘template<class Sequence> typename boost::fusion::result_of::as_vector<Sequence>::type boost::fusion::as_vector(Sequence&) [with Sequence = client::employee]’
user.cpp:140:65: required from here
/usr/include/boost/fusion/container/vector/convert.hpp:27:13: error: invalid use of incomplete type ‘struct boost::fusion::detail::as_vector<11>’
type;
^
In file included from /usr/include/boost/fusion/container/vector/convert.hpp:11:0,
from /usr/include/boost/fusion/include/as_vector.hpp:11,
from /usr/include/boost/spirit/home/support/attributes.hpp:24,
from /usr/include/boost/spirit/home/qi/detail/attributes.hpp:12,
from /usr/include/boost/spirit/home/qi/action/action.hpp:16,
from /usr/include/boost/spirit/home/qi/action.hpp:14,
from /usr/include/boost/spirit/home/qi.hpp:14,
from /usr/include/boost/spirit/include/qi.hpp:16,
from user.cpp:17:
/usr/include/boost/fusion/container/vector/detail/as_vector.hpp:26:12: error: declaration of ‘struct boost::fusion::detail::as_vector<11>’
struct as_vector;
^
user.cpp: In function ‘int main()’:
user.cpp:140:65: error: no matching function for call to ‘as_vector(client::employee&)’
std::cout << "got: " << boost::fusion::as_vector(emp) << std::endl;
^
user.cpp:140:65: note: candidates are:
In file included from /usr/include/boost/fusion/include/as_vector.hpp:11:0,
from /usr/include/boost/spirit/home/support/attributes.hpp:24,
from /usr/include/boost/spirit/home/qi/detail/attributes.hpp:12,
from /usr/include/boost/spirit/home/qi/action/action.hpp:16,
from /usr/include/boost/spirit/home/qi/action.hpp:14,
from /usr/include/boost/spirit/home/qi.hpp:14,
from /usr/include/boost/spirit/include/qi.hpp:16,
from user.cpp:17:
/usr/include/boost/fusion/container/vector/convert.hpp:34:5: note: template<class Sequence> typename boost::fusion::result_of::as_vector<Sequence>::type boost::fusion::as_vector(Sequence&)
as_vector(Sequence& seq)
^
/usr/include/boost/fusion/container/vector/convert.hpp:34:5: note: substitution of deduced template arguments resulted in errors seen above
/usr/include/boost/fusion/container/vector/convert.hpp:43:5: note: template<class Sequence> typename boost::fusion::result_of::as_vector<const Sequence>::type boost::fusion::as_vector(const Sequence&)
as_vector(Sequence const& seq)
^
/usr/include/boost/fusion/container/vector/convert.hpp:43:5: note: substitution of deduced template arguments resulted in errors seen above
我只需要有一个固定大小的结构,这就是使用 char XXX[31] 的原因,但我可以为任何具有固定大小的声明更改它。
提前致谢
您有超过 10 个字段。您需要提高 fusion/container/vector/limits.hpp
.
在包含任何 boost fusion header(或任何 boost header 因为许多库可能隐式包含它)之前包含它:
#define FUSION_MAX_VECTOR_SIZE 15