2016-07-05 17 views
8

Mã này không biên dịch (gcc 5.3.1 + tăng 1.60):Thần X3, hành động ngữ nghĩa làm cho biên soạn không thành công với: Thuộc tính không có kích thước dự kiến ​​

#include <boost/spirit/home/x3.hpp> 

namespace x3 = boost::spirit::x3; 

template <typename T> 
void parse(T begin, T end) { 
    auto dest = x3::lit('[') >> x3::int_ >> ';' >> x3::int_ >> ']'; 

    auto on_portal = [&](auto& ctx) {}; 
    auto portal = (x3::char_('P') >> -dest)[on_portal]; 

    auto tiles = +portal; 
    x3::phrase_parse(begin, end, tiles, x3::eol); 
} 

int main() { 
    std::string x; 
    parse(x.begin(), x.end()); 
} 

Nó không thành công với một sự khẳng định tĩnh:

error: static assertion failed: Attribute does not have the expected size. 

Nhờ Wandbox, tôi cũng cố gắng tăng 1,61 và kêu vang, cả hai đều cho ra kết quả tương tự.

Nếu tôi xóa hành động ngữ nghĩa được đính kèm với portal, nó sẽ biên dịch tốt; điều tương tự cũng xảy ra nếu tôi thay đổi dest thành:

auto dest = x3::lit('[') >> x3::int_ >> ']'; 

Mọi trợ giúp sẽ được đánh giá cao. TIA.

+1

Trình sao chép này rất tuyệt vời. Tôi thích khi mọi người thu hẹp vấn đề về bản chất. +10 nếu tôi có thể – sehe

Trả lời

4

Điều này cũng gây ngạc nhiên cho tôi, tôi sẽ báo cáo nó trong danh sách gửi thư (hoặc trình theo dõi lỗi) là một lỗi tiềm ẩn.

Trong khi đó, bạn có thể "sửa chữa" nó bằng cách cung cấp một loại thuộc tính cho dest:

Live On Coliru

#include <boost/fusion/adapted/std_tuple.hpp> 
#include <boost/spirit/home/x3.hpp> 
#include <iostream> 

namespace x3 = boost::spirit::x3; 

template <typename T> 
void parse(T begin, T end) { 
    auto dest = x3::rule<struct dest_type, std::tuple<int, int> > {} = '[' >> x3::int_ >> ';' >> x3::int_ >> ']'; 

    auto on_portal = [&](auto& ctx) { 
     int a, b; 
     if (auto tup = x3::_attr(ctx)) { 
      std::tie(a, b) = *tup; 
      std::cout << "Parsed [" << a << ", " << b << "]\n"; 
     } 
    }; 
    auto portal = ('P' >> -dest)[on_portal]; 

    auto tiles = +portal; 
    x3::phrase_parse(begin, end, tiles, x3::eol); 
} 

int main() { 
    std::string x = "P[1;2]P[3;4]P[5;6]"; 
    parse(x.begin(), x.end()); 
} 

Prints:

Parsed [1, 2] 
Parsed [3, 4] 
Parsed [5, 6] 

LƯU Ý Tôi đã thay đổi char_('P') thành chỉ lit('P') vì tôi không muốn làm phức tạp mẫu xử lý ký tự trong thuộc tính. Có lẽ bạn đã không có ý nghĩa để có nó trong thuộc tính tiếp xúc anyways.

+0

Cảm ơn bạn đã giải quyết sự cố! – dvd

+0

Có bất kỳ chi phí nào trong việc thiết lập các biến ngữ pháp (như 'gạch') mỗi khi' phân tích cú pháp() 'đang được gọi? Sẽ tốt hơn nếu có một lớp 'phân tích cú pháp' với các thành viên (có lẽ là' tĩnh') có thể được sinh ra một lần và sau đó sử dụng lại chúng trên nhiều cuộc gọi? Nó cũng sẽ giúp dễ dàng hơn trong việc cung cấp các trình phân tích cú pháp của riêng bạn trong mã chỉ tiêu đề. – TemplateRex

+0

Tôi không nghĩ rằng trong phần lớn mã nó quan trọng, bởi vì tất cả mọi thứ có thể được inlined. 'tiles' có thể sẽ không bao giờ tồn tại. Nếu bạn muốn sử dụng các trình phân tích cú pháp do khách hàng cung cấp, thì bạn - theo định nghĩa - xóa kiểu mong muốn. Đó là 'x3 :: lãnh thổ any_parser' IYAM. Nếu bạn chỉ muốn các quy tắc nhóm hợp lý (ẩn tất cả mọi thứ trừ điểm bắt đầu) thì tôi chỉ đơn giản trả về nó từ một hàm. X3 không có vấn đề với điều đó, trái ngược với Qi – sehe

Các vấn đề liên quan