2017-08-23 4 views
1

J'essaye d'analyser des listes de nombres imbriquées avec Boost.Spirit. Voilà ce que j'ai jusqu'à présent:Analyse de listes imbriquées avec Boost.Spirit

//define a test string 
std::string string = "[[\t1 , 2 ], [3, 4, 65.4]]"; 
auto it = string.begin(); 

//parse the string 
std::vector<std::vector<double>> vector; 
auto listRule = "[" >> (qi::double_ % ",") >> "]"; 
auto list2Rule = "[" >> (listRule % ",") >> "]"; 
bool match = qi::phrase_parse(it, string.end(), list2Rule, ascii::space, vector); 

//check if we have a match 
std::cout << "matched: " << std::boolalpha << match << '\n'; 
if (it != string.end()) 
    std::cout << "unmatched part: " << std::string{it, string.end()} << '\n'; 

//print the result 
std::cout << "result\n"; 
for (const auto& v : vector) { 
    std::cout << "["; 
    for (double i : v) 
     std::cout << i << ","; 
    std::cout << "]\n"; 
} 

Les travaux ci-dessus à merveille et impressions:

matched: true 
result 
[1,2,] 
[3,4,65.4,] 

Le problème que je suis confronté est qu'il n'accepte pas vides listes. Par exemple, en changeant la chaîne comme ceci:

std::string string = "[[\t1 , 2 ], [3, 4, 65.4], []]"; 

alors je n'ai pas de match (c'est match == false et it == string.begin()). Le vecteur est toujours peuplé, apparemment, mais la dernière liste vide est manquante. Quelqu'un peut-il expliquer pourquoi c'est le cas et comment y remédier?

+1

L'analyseur '% de' est définie comme: « Liste. Parse un b délimité une ou plusieurs fois. »IIRC, vous pouvez simplement marquer la liste comme optionnelle, et il fera ce que vous voulez:' "[" >> - (listRule% ",") >> "]"; ' – Frank

+0

Uhmm .. non, ne semble pas fonctionner.Dans ce cas (et avec toutes les combinaisons à la fois' listRule' et 'list2Rule' j'obtiens une liste de vecteurs, chacun avec une seule valeur ... – matpen

Répondre

1

Vous utilisez auto pour les modèles proto d'expression dans le domaine Qi - c'est un comportement non défini 99,9% du temps:

Maintenant, pendant que vous résoudre ce problème, assurez-vous aussi corps de liste optionnelle:

Live On Coliru

#include <boost/spirit/include/qi.hpp> 
namespace qi = boost::spirit::qi; 

int main() { 
    using It  = std::string::const_iterator; 
    using Skipper = qi::space_type; 

    for(std::string const input : { "[[\t1 , 2 ], [3, 4, 65.4]]", "[[\t1 , 2 ], [3, 4, 65.4], []]", "[]" }) 
    { 
     std::cout << " ---- '" << input << "' ----\n"; 
     auto it = input.begin(); 

     //parse the string 
     using doubles = std::vector<double>; 
     using vectors = std::vector<doubles>; 

     qi::rule<It, doubles(), Skipper> doubles_ = "[" >> -(qi::double_ % ",") >> "]"; 
     qi::rule<It, vectors(), Skipper> vectors_ = "[" >> -(doubles_ % ",") >> "]"; 

     vectors data; 
     bool match = qi::phrase_parse(it, input.end(), vectors_, qi::space, data); 

     //check if we have a match 
     std::cout << "matched: " << std::boolalpha << match << '\n'; 
     if (it != input.end()) 
      std::cout << "unmatched part: " << std::string{it, input.end()} << '\n'; 

     //print the result 
     std::cout << "result\n"; 
     for (const auto& v : data) { 
      std::cout << "["; 
      for (double i : v) 
       std::cout << i << ","; 
      std::cout << "]\n"; 
     } 
    } 
} 

Prints

---- '[[ 1 , 2 ], [3, 4, 65.4]]' ---- 
matched: true 
result 
[1,2,] 
[3,4,65.4,] 
---- '[[ 1 , 2 ], [3, 4, 65.4], []]' ---- 
matched: true 
result 
[1,2,] 
[3,4,65.4,] 
[] 
---- '[]' ---- 
matched: true 
result 
+0

Merci pour votre réponse: Cependant, ce n'est pas la sortie que je m'attendais ... voir ma question modifiée – matpen

+0

Merde Je devrais accorder plus d'attention à la sortie la prochaine fois.Evidemment, ce n'est pas juste :) – sehe

+0

Correction.Le problème est trop attribut de la magie de compatibilité pour ce cas :) – sehe