2016-07-05 20 views
8

Ten kod nie kompiluje (gcc 5.3.1 + zwiększyć 1.60):Spirit X3, semantyczny działanie sprawia kompilacja nie powiedzie się z: Atrybut nie ma oczekiwanej wielkości

#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()); 
} 

To nie ze statycznym twierdzenie:

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

Dzięki wandboxowi próbowałem również zwiększyć 1.61 i klang, oba dają takie same wyniki.

Po usunięciu akcji semantycznej dołączonej do portal kompiluje się dobrze; to samo dzieje się w przypadku zmiany dest do:

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

Każda pomoc będzie mile widziane. TIA.

+1

Ten reproduktor jest doskonały. Uwielbiam, gdy ludzie zawężają problem do istoty. +10 jeśli mógłbym – sehe

Odpowiedz

4

To jest dla mnie zaskakujące, zgłosiłbym to na liście mailingowej (lub w narzędziu do śledzenia błędów) jako potencjalny błąd.

Tymczasem można "naprawić" go poprzez dostarczanie typ atrybutu dla 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()); 
} 

Wydruki:

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

UWAGA Zmieniłem char_('P') w tylko lit('P'), ponieważ nie chciałem komplikować próbki zajmującej się postacią w atrybucie. Być może i tak nie chciałeś mieć go w widocznym atrybucie.

+0

Dziękuję za obejście problemu! – dvd

+0

Czy jest jakiś narzut na konieczność ustawiania zmiennych gramatycznych (takich jak 'tiles') za każdym razem, gdy wywoływany jest' parse() '? Czy byłoby lepiej mieć "analizę klasy" z (być może "statycznymi") członkami, które mogą zostać zinicjalizowane raz, a następnie ponownie użyte na wielu połączeniach? Ułatwiłoby to również udostępnienie własnych analizatorów w kodzie nagłówkowym. – TemplateRex

+0

Nie sądzę, że w większości kodu ma to znaczenie, ponieważ wszystko można wstawić. 'tiles' prawdopodobnie nigdy nie będzie istnieć. Jeśli chcesz użyć parserów dostarczonych przez klienta, to z definicji - wymazanie typu pożądania. To jest terytorium 'x3 :: any_parser' IYAM. Jeśli chcesz logicznie grupować reguły (ukrywając wszystko poza punktem początkowym), to po prostu zwrócę je z funkcji. X3 nie ma z tym problemu, w przeciwieństwie do Qi – sehe