spirit x3 如何将向量添加到 AST
spirit x3 how to add a vector to an AST
我正在尝试解析文件并将数据复制到 class 对象内的向量中。我以员工为例并将其修改为我正在尝试做的事情。正在解析的文件看起来像这样(但更多行)...
1 0.2 0.3 0.4
我已经添加了一个向量来构造 employee 并且在 phrase_parse 行上遇到断言失败。
static assertion failed: Attribute does not have the expected size.
static_assert(
^
我有点认为预期大小与矢量有关。想想我哪里出错了?
namespace client {
namespace ast {
struct employee
{
int id;
std::vector<double> coords;
};
using boost::fusion::operator<<;
}}
BOOST_FUSION_ADAPT_STRUCT(
client::ast::employee,
(int, id)
(std::vector<double>, coords)
)
namespace client
{
namespace parser
{
namespace x3 = boost::spirit::x3;
namespace ascii = boost::spirit::x3::ascii;
using x3::int_;
using x3::double_;
x3::rule<class employee, ast::employee> const employee = "employee";
auto const employee_def =
int_ >> double_ >> double_ >> double_;
BOOST_SPIRIT_DEFINE(employee)
}
}
int main()
{
using boost::spirit::x3::ascii::space;
using client::parser::employee;
string fil("test-file.in");
mapped_file_source map(fil);
istringstream iss(map.data());
map.close();
client::ast::employee emp;
boost::spirit::istream_iterator iter(iss >> noskipws), eof;
phrase_parse(iter, eof, employee, space, emp);
// failure on above line
}
根据文档,double_ >> double_ >> double_
合成了双倍、双倍、双倍的融合 序列(因此 fusion::tuple<double, double, double>
或 fusion::list<double, double, double>
等) .
你想要一个向量,所以你需要一个重复解析器(运算符)
- repeat 指令将执行
repeat(3) [double_]
- Kleene star (
operator *
) 或 plus (operator +
) 很有趣(但没有限制)
- 列表运算符 (
operator %
) 也是无界的,但接受定界符(例如 double_ % ','
在这种情况下,我会采取另一种方式:对语法使用适当的 AST:
struct coord {
double x,y,z;
};
struct employee
{
int id;
coord coords;
};
调整它们比您使用的老式方法更简单:
BOOST_FUSION_ADAPT_STRUCT(client::ast::coord, x, y, z)
BOOST_FUSION_ADAPT_STRUCT(client::ast::employee, id, coords)
解析器很干净
auto const coord_def = double_ >> double_ >> double_;
auto const employee_def = int_ >> coord;
完整演示:
#include <boost/spirit/home/x3.hpp>
#include <boost/spirit/include/support_istream_iterator.hpp>
#include <boost/fusion/adapted/struct.hpp>
#include <iostream>
namespace client {
namespace ast {
struct coord {
double x,y,z;
};
struct employee
{
int id;
coord coords;
};
using boost::fusion::operator<<;
}}
BOOST_FUSION_ADAPT_STRUCT(client::ast::coord, x, y, z)
BOOST_FUSION_ADAPT_STRUCT(client::ast::employee, id, coords)
namespace client
{
namespace parser
{
namespace x3 = boost::spirit::x3;
namespace ascii = boost::spirit::x3::ascii;
using x3::int_;
using x3::double_;
x3::rule<class employee, ast::coord> const coord = "coord";
x3::rule<class employee, ast::employee> const employee = "employee";
auto const coord_def = double_ >> double_ >> double_;
auto const employee_def = int_ >> coord;
BOOST_SPIRIT_DEFINE(employee, coord);
}
}
int main()
{
using boost::spirit::x3::ascii::space;
using client::parser::employee;
std::istringstream iss("1 0.2 0.3 0.4");
client::ast::employee emp;
boost::spirit::istream_iterator iter(iss >> std::noskipws), eof;
bool ok = phrase_parse(iter, eof, employee, space, emp);
if (ok)
std::cout << "parsed: "
<< emp.id << " "
<< emp.coords.x << " "
<< emp.coords.y << " "
<< emp.coords.z << "\n";
}
我正在尝试解析文件并将数据复制到 class 对象内的向量中。我以员工为例并将其修改为我正在尝试做的事情。正在解析的文件看起来像这样(但更多行)...
1 0.2 0.3 0.4
我已经添加了一个向量来构造 employee 并且在 phrase_parse 行上遇到断言失败。
static assertion failed: Attribute does not have the expected size.
static_assert(
^
我有点认为预期大小与矢量有关。想想我哪里出错了?
namespace client {
namespace ast {
struct employee
{
int id;
std::vector<double> coords;
};
using boost::fusion::operator<<;
}}
BOOST_FUSION_ADAPT_STRUCT(
client::ast::employee,
(int, id)
(std::vector<double>, coords)
)
namespace client
{
namespace parser
{
namespace x3 = boost::spirit::x3;
namespace ascii = boost::spirit::x3::ascii;
using x3::int_;
using x3::double_;
x3::rule<class employee, ast::employee> const employee = "employee";
auto const employee_def =
int_ >> double_ >> double_ >> double_;
BOOST_SPIRIT_DEFINE(employee)
}
}
int main()
{
using boost::spirit::x3::ascii::space;
using client::parser::employee;
string fil("test-file.in");
mapped_file_source map(fil);
istringstream iss(map.data());
map.close();
client::ast::employee emp;
boost::spirit::istream_iterator iter(iss >> noskipws), eof;
phrase_parse(iter, eof, employee, space, emp);
// failure on above line
}
根据文档,double_ >> double_ >> double_
合成了双倍、双倍、双倍的融合 序列(因此 fusion::tuple<double, double, double>
或 fusion::list<double, double, double>
等) .
你想要一个向量,所以你需要一个重复解析器(运算符)
- repeat 指令将执行
repeat(3) [double_]
- Kleene star (
operator *
) 或 plus (operator +
) 很有趣(但没有限制) - 列表运算符 (
operator %
) 也是无界的,但接受定界符(例如double_ % ','
在这种情况下,我会采取另一种方式:对语法使用适当的 AST:
struct coord {
double x,y,z;
};
struct employee
{
int id;
coord coords;
};
调整它们比您使用的老式方法更简单:
BOOST_FUSION_ADAPT_STRUCT(client::ast::coord, x, y, z)
BOOST_FUSION_ADAPT_STRUCT(client::ast::employee, id, coords)
解析器很干净
auto const coord_def = double_ >> double_ >> double_;
auto const employee_def = int_ >> coord;
完整演示:
#include <boost/spirit/home/x3.hpp>
#include <boost/spirit/include/support_istream_iterator.hpp>
#include <boost/fusion/adapted/struct.hpp>
#include <iostream>
namespace client {
namespace ast {
struct coord {
double x,y,z;
};
struct employee
{
int id;
coord coords;
};
using boost::fusion::operator<<;
}}
BOOST_FUSION_ADAPT_STRUCT(client::ast::coord, x, y, z)
BOOST_FUSION_ADAPT_STRUCT(client::ast::employee, id, coords)
namespace client
{
namespace parser
{
namespace x3 = boost::spirit::x3;
namespace ascii = boost::spirit::x3::ascii;
using x3::int_;
using x3::double_;
x3::rule<class employee, ast::coord> const coord = "coord";
x3::rule<class employee, ast::employee> const employee = "employee";
auto const coord_def = double_ >> double_ >> double_;
auto const employee_def = int_ >> coord;
BOOST_SPIRIT_DEFINE(employee, coord);
}
}
int main()
{
using boost::spirit::x3::ascii::space;
using client::parser::employee;
std::istringstream iss("1 0.2 0.3 0.4");
client::ast::employee emp;
boost::spirit::istream_iterator iter(iss >> std::noskipws), eof;
bool ok = phrase_parse(iter, eof, employee, space, emp);
if (ok)
std::cout << "parsed: "
<< emp.id << " "
<< emp.coords.x << " "
<< emp.coords.y << " "
<< emp.coords.z << "\n";
}