2017-08-11 5 views
2

Je base mon application sur cet exemple et obtient les mêmes résultats. Pour une raison quelconque, le contenu de la chaîne d'entrée est analysé dans la structure de fusion 'comments', et rien n'est analysé dans la structure de fusion 'numbers'. Donc je ne sais pas où je vais mal ici.X3: Est-ce que cet analyseur syntaxique, * (char-eol), consomme toutes les lignes?

namespace client { 
    namespace ast { 

     struct number { 
      int num1; 
      int num2; 
     }; 

     struct comment { 
      std::string text; 
      bool dummy; 
     }; 

     struct input { 
      std::vector<comment> comments; 
      std::vector<number> numbers; 
     }; 
    } 
} 

BOOST_FUSION_ADAPT_STRUCT(client::ast::comment, text, dummy) 
BOOST_FUSION_ADAPT_STRUCT(client::ast::number, num1, num2) 
BOOST_FUSION_ADAPT_STRUCT(client::ast::input, comments, numbers) 

namespace client {  
    namespace parser { 

     namespace x3 = boost::spirit::x3; 
     using namespace x3; 

     x3::attr_gen dummy; 

     typedef std::string::const_iterator It; 

     using namespace x3; 

     auto const comment = *(char_ - eol) >> dummy(false); 
     auto const number = int_ >> int_; 

     auto lines = [](auto p) { return *(p >> eol); }; 

     auto const input = 
      lines(comment) >> 
      lines(number); 
    } 
} 

int main() 
{ 
    namespace x3 = boost::spirit::x3; 

    std::string const iss("any char string here\n1 2\n"); 

    auto iter = iss.begin(), eof = iss.end(); 

    client::ast::input types; 

    bool ok = parse(iter, eof, client::parser::input, types); 

    if (iter != eof) { 
     std::cout << "Remaining unparsed: '" << std::string(iter, eof) << "'\n"; 
    } 
    std::cout << "Parsed: " << (100.0 * std::distance(iss.begin(), iter)/iss.size()) << "%\n"; 
    std::cout << "ok = " << ok << std::endl; 

    // This range loop prints all contents if input. 
    for (auto& item : types.comments) { std::cout << "comment: " << boost::fusion::as_deque(item) << "\n"; } 

    // This loop prints nothing. 
    for (auto& item : types.numbers) { std::cout << "number: " << boost::fusion::as_deque(item) << "\n"; } 
} 

Ma plus grande application fait la même chose avec un grand fichier d'entrée et plusieurs de plus de AST, mais il semblerait tous mes exemples sont consommés par l'analyseur de commentaire.

Voici l'exemple complet de fonctionnement.

http://coliru.stacked-crooked.com/a/f983b26d673305a0

pensées?

+0

Que fait 'lines (parser)'? – llonesmiz

+0

lignes (analyseur)? lignes fait en sorte que chaque analyseur (c'est-à-dire, lignes (commentaire), lignes (nombre) est suivi par un eol – Ender

+0

Il fait plus que cela ... – llonesmiz

Répondre

1

Vous avez pris l'idée de la grammaire de ma réponse ici: X3, how to populate a more complex AST?

Là, il a travaillé parce que les formats de ligne ne sont pas ambigus. En fait, l'approche que vous avait demandé une attention particulière « variante », et je note que dans cette puce:

  • départements doivent être commandés avant que les équipes, ou vous obtenez « équipe » adaptée au lieu des départements

Le même type d'ambiguïté existe dans votre grammaire. *(char_ - eol) correspond à "1 2" très bien, donc évidemment, il est ajouté comme commentaire. Vous devrez désambiguïser la grammaire ou en quelque sorte forcer le commutateur à "analyser les lignes de numéros maintenant".

Si vous ne vous souciez absolument pas de ce qui précède les lignes numériques, utilisez x3::seek [ lines(number) ].

+0

Pouvez-vous clarifier sur la partie "forcer le commutateur à" analyser les lignes de numéros maintenant ". mode? " – Ender

+0

Désambiguïser la grammaire, par exemple [' repeat (1) [comment] '] (https://wandbox.org/permlink/yKd9mTOlBtKTVAB4). skipper ajouté en utilisant 'phrase_parse' que vous avez apparemment oublié]. Sinon, vous pouvez _assert_ it: [' lines (! number >> comment] '] (https://wandbox.org/permlink/sAlUOItRihTmnOSv), qui, comme vous peut voir, est moins efficace – sehe