3

Je vous écris une grammaire de Spirit Boost pour analyser le texte dans un vecteur de ces struct:Boost règle de l'Esprit avec l'analyse syntaxique attribut personnalisé

struct Pair 
{ 
    double a; 
    double b; 
}; 

BOOST_FUSION_ADAPT_STRUCT(
    Pair, 
    (double, a) 
    (double, a) 
) 

Cette grammaire a une règle comme ceci:

qi::rule<Iterator, Pair()> pairSequence; 

Cependant , la grammaire réelle de pairSequence est la suivante:

double_ % separator 

Je veux que cette grammaire pour produire un Pair avec a égal au double et b égal à une certaine constante. Je veux faire quelque chose comme ceci:

pairSequence = double_[_val = Pair(_1, DEFAULT_B)] % separator; 

Ce qui précède ne compile pas, bien sûr. J'ai essayé d'ajouter un constructeur à Pair, mais je reçois toujours des erreurs de compilation (aucune fonction correspondant à l'appel de 'Pair :: Pair (const boost :: phoenix :: actor> &, double)').

Répondre

6

Tout d'abord, la signature de pairSequence doit être:

qi::rule<Iterator, std::vector<Pair>()> pairSequence; 

que l'opérateur de la liste expose une std::vector<Pair> comme son attribut.

Toutes les fonctions appelées dans une action sémantique doivent être « paresseux », vous devez donc utiliser Phoenix:

namespace phx = boost::phoenix; 

pairSequence = 
    double_[ 
     phx::push_back(_val, 
      phx::construct<Pair>(_1, phx::val(DEFAULT_B)) 
     ) 
    ] % separator 
; 

Une autre possibilité serait d'ajouter un constructeur (non explicite) à Pair:

struct Pair   
{   
    Pair(double a) : a(a), b(DEFAULT_B) {} 

    double a;   
    double b;   
};   

qui permet de simplifier la grammaire:

pairSequence = double_ % separator; 

et repose entièrement sur les règles de propagation d'attributs intégrées de Spirit. Par ailleurs, pour que cela fonctionne, vous n'avez pas besoin d'adapter Pair en tant que séquence Fusion.

+0

Ah oui, j'ai manqué le vecteur construire. – AJM