Build-Fehler mit Boost-Geist-Grammatik (Boost 1,43 und g ++ 4.4.1) Teil II
-
27-09-2019 - |
Frage
Ich habe Probleme bekommen einen kleinen Geist / Qi Grammatik zu kompilieren. Ich bin mit Boost 1,43 und g ++ 4.4.1.
die Eingabegrammatik-Header: die Build-Fehler scheint sich auf die Definition der ‚Instruktion‘ -Regel zu zeigen, vielleicht ist es das ist ‚[sp :: _ val = sp :: _ 1]‘, dass brokes es irgendwie, aber das ist mehr oder weniger auf das, was der Geist Dokumentation Tutorials werden mit dem xML-Knoten-Parser tun
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;
};
Sie den Test Build Programm:
#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();
}
schließlich der Build-Fehler ist die folgende:
(die vollständige Fehlertrace ist 20-mal größer als die zulässige Größe für eine Stackoverflow Frage, so dass ich die volle Version davon im Internet abrufbar:
Lösung Fehlermeldung sagt Ihnen, dass Sie wollen assign a Die entsprechenden Linien 33 und 34; Um zu verstehen, warum dies geschieht, werden wir bei den Definitionen suchen. Aus der Definition eines Qi Regel , die Unterschrift des zurückgegebene Wert wird von einem Template-Parameter definiert. Daher bedeutet, dass der zurückgegebene Typ eines bedeutet, dass impliziert, dass die zurückgegebene Art von Um es zusammenzufassen, haben Sie Typen in Ihrem variant<MockExpressionNode, basic_string>
zu einem 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
wird eine ExpressionAST
sein (das heißt ein MockExpressionNode
in Ihrem Fall). Ähnlich qi::rule< Iterator , std::string() , space_type > tag;
tag
wird vom Typ string
sein. In Kombination mit instruction = (command | tag)
bedeutet, dass ein instruction
entweder ein string
oder ein MockExpressionNode
. Dies wird intern als variant<MockExpressionNode, string>
gespeichert. Schließlich qi::rule< Iterator , ExpressionAST() , space_type > instruction;
instruction
ist wieder ein ExpressionAST
(d.h. ein MockExpressionNode
). Dies erfordert die fehlerhafte Zuordnung der variant
intern auf einen MockExpressionNode
gehalten. qi::rule
s zu schaffen, die ein wenig die Typen implizit Grammatik in dem Sinne „entsprechen“, dass Zuordnung möglich ist. Trotz aller Boost.Spirit Magie, ist C ++ noch eine statisch typisierte Sprache, nachdem alle. Für die Frage auf der Hand, haben Sie entweder eine passende operator=
zu liefern, oder Sie müssen die Ergebnisse der verschiedenen Regeln zu verschiedenen Typen zuordnen, die implizite Konvertierung unterstützen. BTW, haben Sie ähnliche Art Ausgaben für block
und command
im Moment. Werfen Sie einen sorgfältigen Blick auf die mini_xml Beispiel in der Dokumentation: wie Typen für eine rekursive Struktur zu definieren und wie verschiedene Regeln zuweisen, um verschiedene Typen von der definierten Grammatik abhängig (insbesondere Regeln xml
und node
)