erreur de génération avec la grammaire de l'esprit d'amplification (boost 1,43 g ++ 4.4.1) partie II
-
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 à
La solution vous indique que vous souhaitez attribuer une Les lignes correspondantes sont de 33 et 34; 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 signifie que le type de retour d'un signifie que indique que le type de retour de Pour résumer, vous devez fournir les types dans vos variant<MockExpressionNode, basic_string>
à un MockExpressionNode
[...] error: no match for ‘operator=’ [...] boost::variant<MockExpressionNode, std::basic_string [...]
[...] candidates are: MockExpressionNode& MockExpressionNode::operator=(const MockExpressionNode&) [...]
qi::rule< Iterator , ExpressionAST() , space_type > command;
command
sera un ExpressionAST
(à savoir un MockExpressionNode
dans votre cas). De même qi::rule< Iterator , std::string() , space_type > tag;
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;
instruction
est à nouveau un ExpressionAST
(à savoir un MockExpressionNode
). Cela nécessite l'affectation à défaut de la tenue variant
interne à un MockExpressionNode
. qi::rule
s 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
)