使用 boost Spirit 解析为 STL 向量
Parsing using boost Spirit into STL vector
我正在学习 Boost Spirit 2,我不明白为什么我不能将两个整数的序列解析为 int 的 STL 向量。从 >> 运算符的文档中(here) I know the attribute of the grammar int_ >> int_
should be vector<int>
. And from the attribute notation documentation 我知道 "The notation of vector<A>
stands for any STL container holding elements of type A".
然而,当我尝试向 int_ >> int_
添加一个将 std::vector
作为其属性的操作时,编译失败。
在其他错误消息中,它表示:/usr/include/boost/bind/mem_fn_template.hpp:163:7: note: no known conversion for argument 2 from ‘boost::fusion::vector<int, int>’ to ‘const std::vector<int>&’
我知道 this question ("Getting boost::spirit::qi to use stl containers"),但那里的解决方案 - 包括 std_tuple.hpp - 没有改变任何东西。
这是为什么?
#include <iostream>
#include <string>
#include <vector>
#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/bind.hpp>
namespace client
{
namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;
class ParserActions
{
public:
void printivec (std::vector<int> const& ivec)
{
std::cout << "We see " << ivec.size() << " integers" << std::endl;
}
};
template <typename Iterator>
bool parse_ivec(Iterator first, Iterator last)
{
using ascii::space;
ParserActions actionContainer;
auto two_ints = (qi::int_ >> qi::int_);
bool r = qi::parse(
first, /*< start iterator >*/
last, /*< end iterator >*/
two_ints[boost::bind(&ParserActions::printivec,&actionContainer,_1)]
);
return first == last && r;
}
}
int main()
{
std::string str = "12 13";
if (client::parse_ivec(str.begin(),str.end()))
std::cout << "Parsing succeeded\n";
else
std::cout << "Parsing failed!\n";
return 0;
}
int_ >> int_
合成一个 int 元组,int.¹
如果你想强制合成一个容器,让它repeat(2) [ int_ ]
表达出来。
Sidenote: As you'll see below, there's room for attribute compatibility even if the bound attribute is a cotainer, so you don't need to.
Sidenote: auto
with parser expressions is asking undefined behaviour: Assigning parsers to auto variables
Sidenote: your input uses space delimiter, but the parser doesn't. That will never work.
您的代码示例似乎与目标关系不大,所以这是我的小示例:
1。 vector<int>
:
#include <boost/spirit/include/qi.hpp>
using Vec = std::vector<int>;
namespace qi = boost::spirit::qi;
template <typename It> Vec parse_ivec(It first, It last) {
Vec v;
if (qi::phrase_parse(first, last, qi::int_ >> qi::int_ >> qi::eoi, qi::space, v))
return v;
throw std::runtime_error("Parse failed");
}
Vec parse_ivec(std::string const& r) { return parse_ivec(begin(r), end(r)); }
int main() {
for (int i : parse_ivec("12 13")) {
std::cout << i << "\n";
}
}
版画
12
13
2。改编结构
或者,如果你想要一个结构,而不是 std::vector<>
:
#include <boost/fusion/adapted/struct.hpp>
struct Vec { int a, b; };
BOOST_FUSION_ADAPT_STRUCT(Vec, a, b)
#include <boost/spirit/include/qi.hpp>
namespace qi = boost::spirit::qi;
template <typename It> Vec parse_ivec(It first, It last) {
Vec v;
if (qi::phrase_parse(first, last, qi::int_ >> qi::int_ >> qi::eoi, qi::space, v))
return v;
throw std::runtime_error("Parse failed");
}
Vec parse_ivec(std::string const& r) { return parse_ivec(begin(r), end(r)); }
int main() {
Vec vec = parse_ivec("12 13");
std::cout << vec.a << " " << vec.b << "\n";
}
版画
12 13
3。 std::tuple<int, int>
:
#include <boost/fusion/adapted/std_tuple.hpp>
using Vec = std::tuple<int, int>;
#include <boost/spirit/include/qi.hpp>
namespace qi = boost::spirit::qi;
template <typename It> Vec parse_ivec(It first, It last) {
Vec v;
if (qi::phrase_parse(first, last, qi::int_ >> qi::int_ >> qi::eoi, qi::space, v))
return v;
throw std::runtime_error("Parse failed");
}
Vec parse_ivec(std::string const& r) { return parse_ivec(begin(r), end(r)); }
int main() {
Vec vec = parse_ivec("12 13");
std::cout << std::get<0>(vec) << " " << std::get<1>(vec) << "\n";
}
版画
12 13
¹ 从技术上讲,Fusion 序列可以与许多类型(如 std::pair)或您自己的类型相兼容。
我正在学习 Boost Spirit 2,我不明白为什么我不能将两个整数的序列解析为 int 的 STL 向量。从 >> 运算符的文档中(here) I know the attribute of the grammar int_ >> int_
should be vector<int>
. And from the attribute notation documentation 我知道 "The notation of vector<A>
stands for any STL container holding elements of type A".
然而,当我尝试向 int_ >> int_
添加一个将 std::vector
作为其属性的操作时,编译失败。
在其他错误消息中,它表示:/usr/include/boost/bind/mem_fn_template.hpp:163:7: note: no known conversion for argument 2 from ‘boost::fusion::vector<int, int>’ to ‘const std::vector<int>&’
我知道 this question ("Getting boost::spirit::qi to use stl containers"),但那里的解决方案 - 包括 std_tuple.hpp - 没有改变任何东西。
这是为什么?
#include <iostream>
#include <string>
#include <vector>
#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/bind.hpp>
namespace client
{
namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;
class ParserActions
{
public:
void printivec (std::vector<int> const& ivec)
{
std::cout << "We see " << ivec.size() << " integers" << std::endl;
}
};
template <typename Iterator>
bool parse_ivec(Iterator first, Iterator last)
{
using ascii::space;
ParserActions actionContainer;
auto two_ints = (qi::int_ >> qi::int_);
bool r = qi::parse(
first, /*< start iterator >*/
last, /*< end iterator >*/
two_ints[boost::bind(&ParserActions::printivec,&actionContainer,_1)]
);
return first == last && r;
}
}
int main()
{
std::string str = "12 13";
if (client::parse_ivec(str.begin(),str.end()))
std::cout << "Parsing succeeded\n";
else
std::cout << "Parsing failed!\n";
return 0;
}
int_ >> int_
合成一个 int 元组,int.¹
如果你想强制合成一个容器,让它repeat(2) [ int_ ]
表达出来。
Sidenote: As you'll see below, there's room for attribute compatibility even if the bound attribute is a cotainer, so you don't need to.
Sidenote:
auto
with parser expressions is asking undefined behaviour: Assigning parsers to auto variables
Sidenote: your input uses space delimiter, but the parser doesn't. That will never work.
您的代码示例似乎与目标关系不大,所以这是我的小示例:
1。 vector<int>
:
#include <boost/spirit/include/qi.hpp>
using Vec = std::vector<int>;
namespace qi = boost::spirit::qi;
template <typename It> Vec parse_ivec(It first, It last) {
Vec v;
if (qi::phrase_parse(first, last, qi::int_ >> qi::int_ >> qi::eoi, qi::space, v))
return v;
throw std::runtime_error("Parse failed");
}
Vec parse_ivec(std::string const& r) { return parse_ivec(begin(r), end(r)); }
int main() {
for (int i : parse_ivec("12 13")) {
std::cout << i << "\n";
}
}
版画
12
13
2。改编结构
或者,如果你想要一个结构,而不是 std::vector<>
:
#include <boost/fusion/adapted/struct.hpp>
struct Vec { int a, b; };
BOOST_FUSION_ADAPT_STRUCT(Vec, a, b)
#include <boost/spirit/include/qi.hpp>
namespace qi = boost::spirit::qi;
template <typename It> Vec parse_ivec(It first, It last) {
Vec v;
if (qi::phrase_parse(first, last, qi::int_ >> qi::int_ >> qi::eoi, qi::space, v))
return v;
throw std::runtime_error("Parse failed");
}
Vec parse_ivec(std::string const& r) { return parse_ivec(begin(r), end(r)); }
int main() {
Vec vec = parse_ivec("12 13");
std::cout << vec.a << " " << vec.b << "\n";
}
版画
12 13
3。 std::tuple<int, int>
:
#include <boost/fusion/adapted/std_tuple.hpp>
using Vec = std::tuple<int, int>;
#include <boost/spirit/include/qi.hpp>
namespace qi = boost::spirit::qi;
template <typename It> Vec parse_ivec(It first, It last) {
Vec v;
if (qi::phrase_parse(first, last, qi::int_ >> qi::int_ >> qi::eoi, qi::space, v))
return v;
throw std::runtime_error("Parse failed");
}
Vec parse_ivec(std::string const& r) { return parse_ivec(begin(r), end(r)); }
int main() {
Vec vec = parse_ivec("12 13");
std::cout << std::get<0>(vec) << " " << std::get<1>(vec) << "\n";
}
版画
12 13
¹ 从技术上讲,Fusion 序列可以与许多类型(如 std::pair)或您自己的类型相兼容。