C++ mit Boost.Spirit einfaches format



  • Hi,

    ich habe folgendes dateiformat:

    module s27 ( clock, reset, G0, G1, G2, G3, G17, test_mode, test_si, test_so, test_se);
    

    Und dazu folgenden Parser mit Boost spirit gebaut:

    void print(const std::string &s)
    {
    	std::cout << s << " ";
    }
    
    template <typename Iterator, typename Skipper>
    struct data : qi::grammar<Iterator, Skipper>
    {
    	data(): data::base_type(object)
    	{
    		module_name %= +(ascii::char_-'(');
    		input_names %=  (+ascii::char_) % ','; 
    
    		object = "module" >> module_name[print] >> '(' >> input_names[print] >> ')';
    
    	}
    	qi::rule<Iterator, Skipper> object, member, str;
    	qi::rule<Iterator, std::string(), Skipper> module_name, input_names;
    };
    
    int main(int argc, char* argv[])  
    {  
    	std::ifstream input_file("s27_scan_simple.txt");
    	std::string str((std::istreambuf_iterator<char>(input_file)), std::istreambuf_iterator<char>());
    	std::cout << str << std::endl;
    	data<std::string::iterator, ascii::space_type>v;
    	qi::phrase_parse(str.begin(),str.end(),v,ascii::space);
    	std::cin.get();
        return 0;
    }
    

    Den modulname bekomme ich richtig geparst aber die Liste der Namen innerhalb der Klammern werden nur als in ganzer String ausgegebn. Ich moechte aber die Namen einzeln haben und sie spaeter in einem vector speichern. Was ist falsch an diesem parser? Hat jemand einen Tip?

    Besten Dank! 🙂



  • Statt

    input_names %=  (+ascii::char_) % ',';
    

    versuch mal

    input_names %=  (+ascii::char_ -  ',') % ',';
    

    Außerdem ist

    qi::rule<Iterator, std::string(), Skipper>
    

    nicht der richtige Regeltyp für eine Regel, die einen std::vectorstd::string zurückgeben soll. Möglich wäre

    qi::rule<Iterator, std::vector<std::string>(), Skipper> input_names;
    

    Allerdings würde ich an deiner Stelle etwas engere Beschränkungen für Identifier vergeben. So, wie du es im Moment vorhast, ist

    module s27,),,) (clo ck((), re(set), G0, G1, G2, G3), G17, test_mode, test_si, test_so, test_se))()());
    

    gültig. Ich kann mir nicht vorstellen, dass das gewollt ist. Denkbar etwa eine Regel

    identifier = qi::lexeme[ ascii::alpha >> *(ascii::alnum | '_') ];
    


  • Danke fuer die Hiweise! Jetzt klappt es fast, jetzt werden aber die Unterstriche herausgeschnitten, die Ausgabe ist:

    s27 clock reset G0 G1 G2 G3 G17 test mode test si test so test se
    

    Aber richtig ist:

    s27 clock reset G0 G1 G2 G3 G17 test_mode test_si test_so test_se
    

    Die Regel:

    identifier = qi::lexeme[ ascii::alpha >> *(ascii::alnum | '_') ];
    

    besagt doch, alphabetische Zeichen gefolgt von einer beliebigen Anzahl alphanumerischwer Werte ODER dem Unterstriche. Warum werden sie dann geloescht?



  • Habe den Fehler bis jetzt noch nicht gefunden. hat jemand eine Idee?



  • Ich weiß waran es liegt, kenne aber nur einen schlechten woraround. vielleicht weiß jemand, wie es besser geht.

    Das problem ist, dass spirit bei regeln wie >> ',' oder in deinem Fall >> '' glaubt, dass das '' nicht zur Ausgabe gehört (vergleiche deine Liste von Kommata die du auch nicht haben wolltest). Ich löse das immer mit dem attr-parser der einfach nix liest und das übergebene attribut zurück gibt.

    identifier = qi::lexeme[ ascii::alpha >> *(ascii::alnum | ('_' >> attr('_'))) ];
    


  • Danke fuer den Hinweis! Es klappt jetzt! Aber troztdem komisch das Spirit denkt das "_" gehoert nicht zur Ausgabe.



  • Warum? in diesem Fall wars doch genau das, was du wolltest:

    input_names %=  (+ascii::char_ -  ',') % ','; //das ',' hier ist nicht in der Ausgabe
    

    //edit ich habs nochmal nachgeschlagen:

    'x' steht für lit('x') welches kein attribut erzeugt
    char_('x')is ein parser für 'x' und erzeugt auch die Ausgabe 'x', also macht folgendes das was du willst:

    identifier = qi::lexeme[ ascii::alpha >> *(ascii::alnum | char_('_')) ];
    

    //edit rechtschreibsler



  • Danke fuer die Information! Der Unterscheid zwischen char_('') und nur '' is mir nun klar!


Anmelden zum Antworten