2 votes

Boost::Spirit::Qi Auto-règles et actions conditionnelles

C'est probablement une question d'une facilité déconcertante, d'autant plus que j'utilise QI avec succès pour analyser des structures simples depuis un certain temps déjà, et que je devrais probablement déjà connaître la réponse, mais elle m'échappe malgré tout...

Disons que nous avons un conteneur comme :

struct GenderTally
{
 std::vector<std::string> males;
 std::vector<std::string> females;
};

et un fichier d'entrée comme

m:Steve;
f:Dora;
f:Martha;
m:Joe;
...

Les objets d'une catégorie spécifique peuvent apparaître dans n'importe quel ordre et tous les objets peuvent ne pas apparaître.

Je vais passer l'adaptation de Fusion ici, mais il s'agirait de deux vecteurs de chaînes de caractères.

Mon problème est de construire une grammaire qui remplisse un conteneur conditionnel comme celui-ci. Jusqu'à présent, j'ai contourné ce problème en analysant l'entrée plusieurs fois, chaque fois avec une grammaire spécialisée. Dans cet exemple, il s'agirait d'une grammaire masculine et féminine.

Dans le tutoriel mini-XML de QI, j'ai eu l'impression que les règles automatiques suppriment les actions sémantiques, mais il faut bien admettre que je suis un débutant et que je suis encore intimidé par les API magiques (template) hardcore comme celles utilisées par QI. Donc, même si je sais que c'est très, très mal vu... je serais très reconnaissant d'avoir un exemple concret ici, car je suis en train de faire face à un blocage majeur de la part d'un cerf dans la lumière. modifier : Il n'est pas nécessaire que ce soit exactement pour cette structure, juste... un exemple pratique d'une grammaire qui utilise des règles automatiques, et met les choses dans les catégories appropriées.

5voto

hkaiser Points 8097

Ce que je ferais dans votre cas est le suivant :

BOOST_FUSION_ADAPT_STRUCT(
    GenderTally,
    (std::vector<std::string>, males)
    (std::vector<std::string>, females)
);

rule<Iterator, std::string()> r = +alnum;
rule<Iterator, GenderTally()> g = 
    *(   ("f:" >> r)[phx::push_back(at_c<0>(_val), _1)] 
     |   ("m:" >> r)[phx::push_back(at_c<1>(_val), _1)]
     );

Ce n'est pas bien, mais c'est la meilleure façon de faire avec ce que vous avez.

Si vous aviez une structure de données différente, comme

struct Gender {
    char gender;
    std::string name;
};

typedef std::vector<Gender> GenderTally;

BOOST_FUSION_ADAPT_STRUCT(
    Gender,
    (char, gender)
    (std::string, name)
);

vous pourriez l'écrire différemment :

rule<Iterator, std::string()> r = +alnum;
rule<Iterator, GenderTally()> g = *(char_('f') >> ':' >> r | char_('m') >> ':' >> r);

Mais ce code pourrait ne fonctionner qu'avec le tronc SVN, car nous avons apporté récemment de nombreuses corrections à la gestion des attributs.

L'inconvénient est que vous avez besoin d'une étape de post-traitement distincte pour trier les mâles et les femelles.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X