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:

War es hilfreich?

Lösung

Fehlermeldung sagt Ihnen, dass Sie wollen assign a variant<MockExpressionNode, basic_string> zu einem MockExpressionNode

Die entsprechenden Linien 33 und 34;

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

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

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

bedeutet, dass der zurückgegebene Typ eines command wird eine ExpressionAST sein (das heißt ein MockExpressionNode in Ihrem Fall). Ähnlich

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

bedeutet, dass 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;

impliziert, dass die zurückgegebene Art von instruction ist wieder ein ExpressionAST (d.h. ein MockExpressionNode). Dies erfordert die fehlerhafte Zuordnung der variant intern auf einen MockExpressionNode gehalten.

Um es zusammenzufassen, haben Sie Typen in Ihrem qi::rules 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)

.
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top