2010-08-05 8 views
1

J'ai essayé différentes approches pour corriger ce problème avec des cartes et des moulages, en divisant l'analyse en sous-parties différentes, en utilisant std :: vecteur directement et en essayant _r1 etc. mais je semble avoir manqué de saisir quelque chose de fondamental sur l'utilisation des attributs.boost esprit v2 erreur de compilation - essayant d'utiliser des symboles pour quelque chose de légèrement plus difficile et manquant un point important quelque part

Je veux analyser une ligne telle que:

DEFMACRO macroname param1 param2 param3 ... paramN 

et ajouter nommacro dans un analyseur qi :: symboles ainsi que la liste des params.

correspondant sur

lit("DEFMACRO") >> (+char_) >> predicate_ 

et la mise en un élément struct defmacro fonctionne très bien, mais quand je tente d'utiliser le résultat ou le stocker tout comme les données d'un analyseur de symboles que je reçois des erreurs de la forme

ne peut pas convertir 'boost const :: acteur :: Phoenix' à 'client const :: defmacro'

  • mais tout ce que j'essaie toujours je ne « convertir" acteur const boost :: phénix à "quelles que soient les données type que j'essaie d'utiliser (par exemple, directement à std :: vector ou à d'autres variations dans les structures. Également essayé des variations sur la syntaxe mais jusqu'ici dessiné un vide.

Le fragment de code est ci-dessous, suivi par la sortie du compilateur pour cette variation sur mon problème.

Toute explication de mon incapacité à saisir un concept important est la bienvenue. Utiliser VC++ 2008 avec Spirit 1.42.

Merci Rick

#include <boost/spirit/include/qi.hpp> 
#include <boost/spirit/include/qi_int.hpp> 
#include <boost/spirit/include/phoenix_core.hpp> 
#include <boost/spirit/include/phoenix_operator.hpp> 
#include <boost/spirit/include/phoenix_fusion.hpp> 
#include <boost/spirit/include/phoenix_stl.hpp> 
#include <boost/spirit/include/phoenix_object.hpp> 
#include <boost/fusion/include/adapt_struct.hpp> 

#include <string> 
#include <vector> 

namespace client 
{ 
    namespace fusion = boost::fusion; 
    namespace phoenix = boost::phoenix; 
    namespace qi = boost::spirit::qi; 
    namespace ascii = boost::spirit::ascii; 

typedef std::vector<std::string> predicate; 

struct defmacro 
    { 
    std::string name; // identifier for macro 
    predicate params; // parameters for macro 
    }; 

} 

BOOST_FUSION_ADAPT_STRUCT(
    client::defmacro, 
    (std::string, name) 
(client::predicate, params) 
) 

namespace client 
{ 
    template <typename Iterator> 
    struct awe_grammar 
     : qi::grammar<Iterator, awe(), qi::locals<std::string>, ascii::space_type> 
    { 
     awe_grammar() 
      : awe_grammar::base_type(x, "x") 
     { 
      using qi::lit; 
      using qi::eol; 
      using qi::int_; 
      using ascii::char_; 
      using namespace qi::labels; 

      using phoenix::at_c; 

    long line_no=1; 
    qi::symbols<std::string, defmacro> macros; 

    eol_ = eol[ref(line_no)++]; 

    predicate_ %= *(+char_); 

    defmacro_line_ %= (lit("DEFMACRO") >> (+char_) >> predicate_ >> eol_); 

    // ******** This line will not compile ************************* 
    defmacro_ = defmacro_line_[macros.add(at_c<0>(_1),_1)]; 
    // ************************************************************* 
     } 

    qi::rule<Iterator, defmacro(), ascii::space_type> defmacro_line_; 
    qi::rule<Iterator, void(), ascii::space_type> defmacro_; 
     qi::rule<Iterator, predicate(), ascii::space_type> predicate_; 

}; 
} 

2>v:\awe\parser\parser\spirit\spirit_eg.cpp(XXX) : error C2664: 'const boost::spirit::qi::symbols<Char,T>::adder &boost::spirit::qi::symbols<Char,T>::adder::operator()<boost::phoenix::actor<Eval>>(const Str &,const T &) const' : cannot convert parameter 2 from 'const boost::phoenix::actor<Eval>' to 'const client::defmacro &' 
2>  with 
2>  [ 
2>   Char=std::string, 
2>   T=client::defmacro, 
2>   Eval=boost::phoenix::composite<boost::phoenix::at_eval<0>,boost::fusion::vector<boost::spirit::argument<0>,boost::fusion::void_,boost::fusion::void_,boost::fusion::void_,boost::fusion::void_,boost::fusion::void_,boost::fusion::void_,boost::fusion::void_,boost::fusion::void_,boost::fusion::void_>>, 
2>   Str=boost::phoenix::actor<boost::phoenix::composite<boost::phoenix::at_eval<0>,boost::fusion::vector<boost::spirit::argument<0>,boost::fusion::void_,boost::fusion::void_,boost::fusion::void_,boost::fusion::void_,boost::fusion::void_,boost::fusion::void_,boost::fusion::void_,boost::fusion::void_,boost::fusion::void_>>> 
2>  ] 
2>  and 
2>  [ 
2>   Eval=boost::spirit::argument<0> 
2>  ] 
2>  Reason: cannot convert from 'const boost::phoenix::actor<Eval>' to 'const client::defmacro' 
2>  with 
2>  [ 
2>   Eval=boost::spirit::argument<0> 
2>  ] 
2>  No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called 
2>  v:\awe\parser\parser\spirit\spirit_eg.cpp(351) : while compiling class template member function 'client::awe_grammar<Iterator>::awe_grammar(void)' 
2>  with 
2>  [ 
2>   Iterator=std::_String_const_iterator<char,std::char_traits<char>,std::allocator<char>> 
2>  ] 
2>  v:\awe\parser\parser\spirit\spirit_eg.cpp(622) : see reference to class template instantiation 'client::awe_grammar<Iterator>' being compiled 
2>  with 
2>  [ 
2>   Iterator=std::_String_const_iterator<char,std::char_traits<char>,std::allocator<char>> 
2>  ] 
+0

Désolé formating échoué - pas affiché à stackoverflow avant. Rick –

+0

il y a 01 bouton pour le code de formatage – Anycorn

Répondre

1

Vous pouvez ajouter des valeurs aux symboles en dehors de votre grammaire comme ceci:

#include <boost/spirit/include/qi.hpp> 
#include <boost/spirit/include/qi_int.hpp> 
#include <boost/spirit/include/phoenix_core.hpp> 
#include <boost/spirit/include/phoenix_operator.hpp> 
#include <boost/spirit/include/phoenix_fusion.hpp> 
#include <boost/spirit/include/phoenix_stl.hpp> 
#include <boost/spirit/include/phoenix_object.hpp> 
#include <boost/fusion/include/adapt_struct.hpp> 

#include <string> 
#include <vector> 

namespace client 
{ 
    namespace fusion = boost::fusion; 
    namespace phoenix = boost::phoenix; 
    namespace qi = boost::spirit::qi; 
    namespace ascii = boost::spirit::ascii; 

    typedef std::vector<std::string> predicate; 

    struct defmacro 
    { 
     std::string name; // identifier for macro 
     predicate params; // parameters for macro 
    }; 

    typedef std::vector<defmacro> awe; 
} 

BOOST_FUSION_ADAPT_STRUCT(
    client::defmacro, 
    (std::string, name) 
    (client::predicate, params) 
) 

namespace client 
{ 
    template <typename Iterator> 
    struct awe_grammar 
     : qi::grammar<Iterator, awe()> 
    { 
     awe_grammar() 
      : awe_grammar::base_type(start_) 
     { 
      using qi::lit; 
      using qi::eol; 
      using ascii::char_; 
      using ascii::blank; 
      using ascii::space; 
      using namespace qi::labels; 
      using phoenix::ref; 
      using phoenix::at_c; 

      line_no = 0; 

      eol_ = eol[++ref(line_no)]; 

      identifier_ %= qi::lexeme[+(char_ - space)]; 

      predicate_ %= (identifier_ % blank) >> eol_; 

      defmacro_line_ %= 
        lit("DEFMACRO ") 
       >> identifier_ >> ' ' 
       >> predicate_ 
      ; 

      start_ %= +defmacro_line_; 
     } 

     long line_no; 

     qi::rule<Iterator, void()  > eol_; 
     qi::rule<Iterator, defmacro() > defmacro_line_; 
     qi::rule<Iterator, awe()  > start_; 
     qi::rule<Iterator, std::string()> identifier_; 
     qi::rule<Iterator, predicate() > predicate_; 

    }; 
} 

et

#include <cstdlib> 
#include <iostream> 
#include "awe_grammar.h" 

template <typename P, typename T> 
void test_parser_attr(
         char const* input, P const& p, T& attr, bool full_match = true) 
{ 
    using boost::spirit::qi::parse; 

    char const* f(input); 
    char const* l(f + strlen(f)); 
    if (parse(f, l, p, attr) && (!full_match || (f == l))) 
     std::cout << "ok" << std::endl; 
    else 
     std::cout << "fail" << std::endl; 
} 

int main(/*int _argc, char * _argv[]*/) 
{ 
    typedef client::awe_grammar<char const *> my_grammar; 
    my_grammar g; 
    client::awe result; 

    test_parser_attr(
     "DEFMACRO macroname param1 param2 param3\n" 
     "DEFMACRO macro2 param1 param2\n", 
     g, 
     result, 
     true 
    ); 

    //////////////////// 
    // adding 
    //////////////////// 
    boost::spirit::qi::symbols<char, client::defmacro> macros; 
    for (size_t i = 0; i < result.size(); i++) 
    { 
     macros.add(result[i].name, result[i]); 
    } 

    return EXIT_SUCCESS; 
} 

Après cela, vous pouvez faire avec votre macros ce que vous voulez (par exemple, passez le à une autre grammaire).

+0

Merci GooRoo - en un sens c'est la réponse pragmatique parfaite en ce sens que je peux juste prendre cela et l'utiliser (merci). Dans un autre sens, cependant, on ne m'a pas enseigné à pêcher parce que je ne comprends toujours pas ce que je dois faire pour que l'acteur Eval du phénix soit disponible dans le code tel qu'il est censé être - est-ce fondamentalement impossible? dans Phoenix paresseux-eval terrain ou est-il un moyen de faire reconnaître cet argument comme un objet struct/Boost que j'ai manqué. Le plus reconnaissant pour l'exemple de travail, mais encore à court de perspicacité dans ce que je fais et où je suis épais. –

+0

Je pense que l'idée que je manque est que je devrais utiliser phoenix :: construct ou similaire en quelque sorte. D'autres pensées là-bas? Merci, Rick –

+0

L'un des développeurs de boost-spirit peut vous aider peut-être: http://stackoverflow.com/users/269943/hkaiser – GooRoo

0

Essayez ceci:

// ******** This line will not compile ************************* 
using qi::_val; 
defmacro_ = defmacro_line_[macros.add(at_c<0>(_val),_1)]; 
// *************************************************************