2017-07-09 89 views
1

我想解析一個文件,並將數據複製到一個類對象內的向量。我採取了員工示例,並將其修改爲我正在嘗試執行的操作。正在解析的文件看起來像這樣(但多行)...精神x3如何添加一個向量的AST

1 0.2 0.3 0.4 

我添加了一個向量爲結構的員工和我在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 
} 
+0

「使用」'運營商<<'確實什麼也沒有。爲什麼在地球上將文件映射覆制到字符串流?爲什麼你的代碼示例被破壞而不是自包含? – sehe

回答

1

根據文檔,double_ >> double_ >> double_來合成融合的序列雙,雙,雙(所以fusion::tuple<double, double, double>fusion::list<double, double, double>等)。

你想要一個載體,所以你需要一個重複的解析器(運營商)

  • 重複指令將做repeat(3) [double_]
  • Kleene星號(operator *)或加號(operator +)很有趣(但無界)
  • 列表運算符(operator %)也無界但接受分隔符(例如double_ % ','

在這種情況下,我會走另一條路:用適當的AST的語法:

Live On Coliru

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; 

完整的示例:

Live On Coliru

#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"; 
} 
+0

需要什麼來分析多行數據?我添加了另一行2 2.2 3.3 4.4來解決問題,它仍然只解析一行。 – Ender

+0

您是否閱讀過文檔?我的答案完全針對所需的東西。請參閱https://stackoverflow.com/questions/17072987/boost-spirit-skipper-issues/17073965#17073965瞭解有關與新行相關的船長的一般信息。一定要解析成另一種類型,因爲'employee' _ [sic] _顯然只能存儲1行 – sehe

+0

好的,那麼。謝謝您的幫助。我會繼續嘗試。 – Ender