2009-01-21 4 views
3

Ma situation: Je suis novice en Esprit, je dois utiliser VC6 et j'utilise donc Spirit 1.6.4.Comment est-ce que j'analyse correctement ceci avec l'esprit?

J'ai une ligne qui ressemble à ceci:

//The Description;DESCRIPTION;; 

Je veux mettre le texte DESCRIPTION dans une chaîne si la ligne commence par //The Description;.

J'ai quelque chose qui fonctionne, mais me semble pas élégante:

vector<char> vDescription; // std::string doesn't work due to missing ::clear() in VC6's STL implementation 
if(parse(chars, 
    // Begin grammar 
    (
     as_lower_d["//the description;"] 
    >> (+~ch_p(';'))[assign(vDescription)] 
    ), 
    // End grammar 
    space_p).hit) 
{ 
    const string desc(vDescription.begin(), vDescription.end()); 
} 

Je beaucoup plus que d'attribuer tous les caractères imprimables jusqu'à la prochaine ';' mais ce qui suit ne marchera pas parce que parse(...).hit == false

parse(chars, 
     // Begin grammar 
     (
      as_lower_d["//the description;"] 
     >> (+print_p)[assign(vDescription)] 
     >> ';' 
     ), 
     // End grammar 
     space_p).hit) 

Comment le faire frapper?

Répondre

3

Vous pouvez essayer d'utiliser confix_p:

confix_p(as_lower_d["//the description;"], 
     (+print_p)[assign(vDescription)], 
     ch_p(';') 
     ) 

Il devrait être équivalent à Fred's response.

La raison de l'échec de votre code est que print_p est greedy. L'analyseur +print_p utilisera des caractères jusqu'à ce qu'il rencontre la fin de l'entrée ou un caractère non imprimable. Le point-virgule est imprimable, donc print_p le réclame. Votre entrée est épuisée, la variable est assignée et la correspondance échoue - il n'y a plus rien pour le dernier point-virgule de votre analyseur.

La réponse de Fred construit un nouvel analyseur, (print_p - ';'), qui correspond à tout print_p, à l'exception des points-virgules. "Correspond à tout sauf X, puis correspondre X" est un modèle commun, alors confix_p est fourni en tant que raccourci pour la construction de ce type d'analyseur. La documentation suggère de l'utiliser pour analyser des commentaires de style C ou Pascal, mais ce n'est pas obligatoire. Pour que votre code fonctionne, Spirit doit reconnaître que le print_p gourmand correspond trop et faire marche arrière pour permettre moins de correspondance. Mais bien que l'Esprit revienne en arrière, il ne reviendra pas au «milieu» de ce qu'un sous-analyseur pourrait faire avec avidité. Il reviendra au prochain "point de choix", mais votre grammaire n'en a pas. Voir Exhaustive backtracking and greedy RD dans la documentation de Spirit.

+0

Merci, cela fonctionne aussi et semble encore mieux. J'ai cependant une petite correction: Pour obtenir uniquement l'ouverture et la fermeture du texte _in_between_ confix_p, l'action [assign()] doit être placée derrière print_p et non derrière confix_p(). – foraidt

+0

Ah, vous avez raison.J'ai parcouru la documentation trop vite. Il semble mal au début, mais l'analyseur le corrige pour faire la bonne chose. –

3

Vous ne recevez pas de succès parce que ';' est apparié par print_p. Essayez ceci:

parse(chars, 
    // Begin grammar 
    (
     as_lower_d["//the description;"] 
    >> (+(print_p-';'))[assign(vDescription)] 
    >> ';' 
    ), 
    // End grammar 
    space_p).hit) 
+0

Merci, je vais essayer ça demain. On dirait qu'il y a un malentendu fondamental de mon côté alors. J'ai supposé que l'analyseur essaierait de faire correspondre les choses si possible et ne pas être si paresseux ... Savez-vous quel est le problème de ce comportement? – foraidt

+0

Je pense que le terme est "gourmand". Voir http://www.boost.org/doc/libs/1_35_0/libs/spirit/doc/faq.html#greedy_rd –

Questions connexes