boost::spirit - semantic action parameter type?



  • Hallo 🙂

    Ich versuche seit etlichen Stunden einen kleinen Parser mittels boost::spirit (Version 2.5.3, Visual Studio 2015) zu schreiben. Ich möchte mittels den "semantic actions" die iteratorposition extrahieren. Dazu lege ich mir einen functor welcher im ()-operator den aktuellen iterator speichern soll. Jedoch war ich nicht in der Lage den Typ der Argumente herauszufinden.

    Beispielsregel:

    struct LineCounter
    {
    	LineCounter(Assembler::iterator &ref, unsigned &num) : iter(ref), line(num)
    	{
    	}
    	void operator () (const char &val, qi::unused_type, qi::unused_type) const
    	{
    		iter = &val;
    		++line;
    	}
    	unsigned &line;
    	Assembler::iterator &iter;
    };
    
    char newline = '\n';
    rule space = (qi::space - qi::char_(newline)) | qi::char_(newline)[LineCounter(line_beginning, current_line)];
    

    Dieses Beispiel kompiliert wunderbar. Anscheinend übergibt ein qi::char_ eine referenz auf const char.

    Das selbe klappt bei komplexeren Regeln aber nicht mehr:

    struct SaveIterator
    {
    	SaveIterator(Assembler::iterator &ref) : iter(ref)
    	{
    	}
    	void operator () (const char &val, qi::unused_type, qi::unused_type) const
    	{
    	}
    	Assembler::iterator &iter;
    };
    struct AddInstruction
    {
    	AddInstruction(std::list<Instruction> &list, Assembler::iterator &ref) : instructions(list), iter(ref)
    	{
    	}
    	void operator () (const char &val, qi::unused_type, qi::unused_type) const
    	{
    	}
    	std::list<Instruction> &instructions;
    	Assembler::iterator &iter;
    };
    
    rule zero_operand_instruction = *space >> zero_operand_mnemonic[SaveIterator(saved_iterator)] >> eps[AddInstruction(instructions, saved_iterator)] >> *space;
    

    Die Compiler-Fehlermeldung ist zwar vorhanden, hilft aber nicht weiter

    1>c:\program files (x86)\boost\include\boost-1_58\boost\spirit\home\support\action_dispatch.hpp(142): error C2893: Failed to specialize function template 'action_dispatch<Subject>::fwd_storage<unknown-type,boost::spirit::traits::action_dispatch<Subject>::fwd_attrib_context_pass>::type boost::spirit::traits::action_dispatch<Subject>::do_call(F &&,boost::spirit::traits::action_dispatch<Subject>::fwd_tag<A>,boost::spirit::traits::action_dispatch<Subject>::fwd_tag<B>,boost::spirit::traits::action_dispatch<Subject>::fwd_tag<C>,...)'
    1>          with
    1>          [
    1>              Subject=boost::spirit::qi::reference<const boost::spirit::qi::rule<Assembler::iterator,boost::spirit::unused_type,boost::spirit::unused_type,boost::spirit::unused_type,boost::spirit::unused_type>>
    1>          ]
    

    Eigentlich wäre ich davon ausgegangen dass zumindest eps als typ einen const char & übergibt. Ich habe bereits allerlei typen getestet:
    const char &
    const char *
    std::string::iterator
    std::string::const_iterator
    std::string::const_iterator &

    Welche Typen bekommen die beiden functoren übergeben? Und wo finde ich eine Referenz dazu? Habe bereits mehrere Boost-beispiele durchgearbeitet, diese beschränken sich darauf einen bequemen int& von dem int_ objekt abzuholen. Auch suchen brachte mir nichts 😞

    Und:

    Kann man das ganze Konstrukt vielleicht schöner schreiben? Ich will eigentlich nur die Start und Endposition der gematchten Regel. Gibt es keine Möglichkeit den functor mit

    void operator () (const std::string::const_iterator &beg, const std::string::const_iterator &end, qi::unused_type);
    

    zu deklarieren? Dann könnte man direkt mit den Iteratoren arbeiten.

    -- MemoryPool


Anmelden zum Antworten