2016-07-05 14 views
8

Questo codice non compilazione (gcc 5.3.1 + amplificare 1,60):Spirito X3, azione semantica rende la compilazione non riesce con: attributo non ha la dimensione prevista

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

Non riesce con un'affermazione statica:

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

Grazie a wandbox ho anche provato ad aumentare 1.61 e clang, entrambi producono gli stessi risultati.

Se rimuovo l'azione semantica allegata a portal, compila bene; lo stesso accade se cambio dest a:

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

Qualsiasi aiuto sarebbe apprezzato. TIA.

+1

Questo riproduttore è eccellente. Amo quando le persone restringono il problema all'essenza. +10 se potessi – sehe

risposta

4

Questo è sorprendente anche per me, lo segnalerei alla mailing list (o al bug tracker) come un potenziale bug.

Nel frattempo, è possibile "fissare" esso fornendo un tipo di attributo per 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()); 
} 

Stampe:

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

NOTA Ho modificato char_('P') in solo lit('P') perché non volevo complicare l'esempio relativo al carattere nell'attributo. Forse non intendevi comunque averlo nell'attributo esposto.

+0

Grazie per la soluzione! – dvd

+0

C'è un sovraccarico di dover impostare le variabili grammaticali (come 'tiles') ogni volta che viene chiamato' parse() '? Sarebbe meglio avere un 'analisi di classe con membri (forse' statici') che possono essere initalizzati una volta e poi riutilizzarli su più chiamate? Sarebbe anche più semplice fornire i propri parser nel codice di sola intestazione. – TemplateRex

+0

Non penso nella maggior parte del codice che conta, perché tutto può essere sottolineato. 'tiles' probabilmente non esisterà mai. Se si desidera utilizzare i parser forniti dal client, si - per definizione - si desidera cancellare il tipo. Questo è il territorio di 'x3 :: any_parser' IYAM. Se si desidera semplicemente raggruppare le regole in modo logico (nascondendo tutto tranne il punto di partenza), restituirei semplicemente da una funzione. X3 non ha problemi con questo, al contrario di Qi – sehe

Problemi correlati