erreur de génération avec la grammaire de l'esprit d'amplification (boost 1,43 g ++ 4.4.1) partie II

StackOverflow https://stackoverflow.com/questions/3042587

  •  27-09-2019
  •  | 
  •  

Question

Je vais avoir des problèmes obtenir un petit esprit / qi grammaire pour compiler. J'utilise boost 1,43 g ++ 4.4.1.

l'en-tête de la grammaire d'entrée: l'erreur de construction semble pointer à la définition de la règle « instruction », peut-être est le « [sp :: _ val = sp :: _ 1] » qui Brokes en quelque sorte, mais ce qui est plus ou moins basé sur ce que la documentation de l'esprit tutoriels sont en train de faire avec l'analyseur de nœud xml

inputGrammar.h

#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.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/fusion/include/adapt_struct.hpp>
#include <boost/variant/recursive_variant.hpp>
#include <boost/foreach.hpp>

#include <iostream>
#include <fstream>
#include <string>
#include <vector>

namespace sp = boost::spirit;
namespace qi = boost::spirit::qi;
using namespace boost::spirit::ascii;
//using namespace boost::spirit::arg_names;

namespace fusion = boost::fusion;
namespace phoenix = boost::phoenix;

using phoenix::at_c;
using phoenix::push_back;


template< typename Iterator , typename ExpressionAST >
struct InputGrammar : qi::grammar<Iterator, ExpressionAST(), space_type> {

    InputGrammar() : InputGrammar::base_type( block ) {
        tag = sp::lexeme[+(alpha)        [sp::_val += sp::_1]];//[+(char_ - '<')        [_val += _1]];

        block = sp::lit("block") [ at_c<0>(sp::_val) = sp::_1]
                >> "(" >> *instruction[ push_back( at_c<1>(sp::_val) , sp::_1 ) ]
                >> ")";

        command = tag   [ at_c<0>(sp::_val) = sp::_1]
                                >> "(" >> *instruction [ push_back( at_c<1>(sp::_val) , sp::_1 )]
                                >> ")";

        instruction = ( command | tag ) [sp::_val = sp::_1]; //build error seems to be happening here
    }
    qi::rule< Iterator , std::string() , space_type > tag;
    qi::rule< Iterator , ExpressionAST() , space_type > block;
    qi::rule< Iterator , ExpressionAST() , space_type > function_def;
    qi::rule< Iterator , ExpressionAST() , space_type > command;
    qi::rule< Iterator , ExpressionAST() , space_type > instruction;
};

le programme de construction de test:

#include <iostream>
#include <string>
#include <vector>
using namespace std;

//my grammar
#include <InputGrammar.h>

struct MockExpressionNode {
    std::string name;
    std::vector< MockExpressionNode > operands;

    typedef std::vector< MockExpressionNode >::iterator iterator;
    typedef std::vector< MockExpressionNode >::const_iterator const_iterator;

    iterator begin() { return operands.begin(); }
    const_iterator begin() const { return operands.begin(); }
    iterator end() { return operands.end(); }
    const_iterator end() const { return operands.end(); }

    bool is_leaf() const {
        return ( operands.begin() == operands.end() );
    }
};


BOOST_FUSION_ADAPT_STRUCT(
    MockExpressionNode,
    (std::string, name)
    (std::vector<MockExpressionNode>, operands)
)

int const tabsize = 4;

void tab(int indent)
{
    for (int i = 0; i < indent; ++i)
        std::cout << ' ';
}

template< typename ExpressionNode >
struct ExpressionNodePrinter
{
    ExpressionNodePrinter(int indent = 0)
      : indent(indent)
    {
    }

    void operator()(ExpressionNode const& node) const {
        cout << " tag: " << node.name << endl;
        for (int i=0 ; i < node.operands.size() ; i++ ) {
            tab( indent ); cout << " arg "<<i<<": "; ExpressionNodePrinter(indent + 2)( node.operands[i]); cout << endl;
        }
    }

    int indent;
};

int test() {
 MockExpressionNode root;
    InputGrammar< string::const_iterator , MockExpressionNode > g;
    std::string litA = "litA";
    std::string litB = "litB";
    std::string litC = "litC";
    std::string litD = "litD";
    std::string litE = "litE";
    std::string litF = "litF";
    std::string source = litA+"( "+litB+" ,"+litC+" , "+ litD+" ( "+litE+", "+litF+" ) "+ " )";
    string::const_iterator iter = source.begin();
    string::const_iterator end = source.end();
    bool r = qi::phrase_parse( iter , end , g , space , root );
    ExpressionNodePrinter< MockExpressionNode > np;
    np( root );
};

int main() {
   test();
}

enfin, l'erreur de construction est le suivant:

(la trace complète d'erreur est 20 fois plus grande que la taille maximale autorisée pour une question stackoverflow, donc je posté la version complète de celui-ci à

Était-ce utile?

La solution

vous indique que vous souhaitez attribuer une variant<MockExpressionNode, basic_string> à un MockExpressionNode

Les lignes correspondantes sont de 33 et 34;

[...] error: no match for ‘operator=’ [...] boost::variant<MockExpressionNode, std::basic_string [...]
[...] candidates are: MockExpressionNode& MockExpressionNode::operator=(const MockExpressionNode&) [...]

Pour comprendre pourquoi cela se produit, nous devons examiner les définitions. De la définition d'un Qi règle , la signature de la valeur de retour est défini par un paramètre de modèle. Par conséquent

qi::rule< Iterator , ExpressionAST() , space_type > command;

signifie que le type de retour d'un command sera un ExpressionAST (à savoir un MockExpressionNode dans votre cas). De même

qi::rule< Iterator , std::string() , space_type > tag;

signifie que tag seront de type string. En combinant ceci avec des moyens de instruction = (command | tag) qu'un instruction est soit un string ou un MockExpressionNode. Ceci est enregistré en interne comme variant<MockExpressionNode, string>. Enfin,

qi::rule< Iterator , ExpressionAST() , space_type > instruction;

indique que le type de retour de instruction est à nouveau un ExpressionAST (à savoir un MockExpressionNode). Cela nécessite l'affectation à défaut de la tenue variant interne à un MockExpressionNode.

Pour résumer, vous devez fournir les types dans vos qi::rules que peu « correspondent à » les types implicites par votre grammaire dans le sens où la cession est possible. Malgré toute la magie de Boost.Spirit, C ++ est encore un langage typé statiquement après tout. Pour la question à, vous avez soit à fournir un operator= de montage, ou vous devez affecter les résultats des différentes règles à différents types qui prennent en charge la conversion implicite. BTW, vous avez des problèmes de type similaire pour block et command au moment. Jetez un oeil attentif à la mini_xml exemple dans la documentation: comment définir les types de structure récursive et comment les règles différent assigner à différents types en fonction de la grammaire définie (en particulier les règles xml et node)

.
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top