Wie boost::regex befragen: Welches Zeichen ist für neg. Test verantwortlich? Jetzt auch boost::spirit



  • N'Abend allerseits!

    Hat boost::regex die Möglichkeit mir zu sagen an welcher Stelle im String es den ersten Verstoß findet?

    Kleines Bsp.:

    Regex: "^abcd$"
    String: "abed"
    Ergebnis: An der dritten Pos. ist die erste Regelverletzung.

    Danke und Gruß,
    Goran



  • Da es bei einem nicht übereinstimmen eines RegExp sich nicht um einen "Regelverstoß" handelt sondern schlicht dass das Muster nicht auf den string passt wirst Du es IMHO mit der boost::regex nicht herausfinden können. Vielleicht wirst Du aber mit boost::spirit fündiger. Der parser gibt nach dem parsen eine parse_info struktur zurück die enthält infos ob es fehl geschlagen ist und an welcher Stelle er aufgehört hat mit parsen.

    Gut Schuß
    VuuRWerK 😉



  • Danke VuuRWerK.

    Ich habe mich an boost::spirit gemacht. Doch ohne Erfolg 😞

    Hier ein kurzer Versuch der leider nicht das erwünschte Ergebnis bringt:

    #include <boost/spirit.hpp>
    #include <string>
    #include <iostream>
    
    int main()
    {
            using namespace std;
            using namespace boost::spirit;
    
            // config
            string conf = "Somevar=1234";
    
            // variable
            rule<> someVar = strlit<>("SomeVar");
            // value
            rule<> someVal = int_p >> 
                             int_p >> 
                             int_p >>
                             int_p;
            // declaration
            rule<> confDec = someVar >>
                             strlit<>("=") >>
                             someVal;
    
            // parsing
            parse_info<> pI = parse(conf.c_str(),confDec);
            if(pI.full)
                    cout << "OK.\n";
    
            return 0;
    }
    

    Hat jemand Verbesserungsvorschläge?

    Gruß, Goran



  • Da möchte ich Dir mal folgendes Tutorial ans herz legen: Klick Da wird Spirit sehr gut anhand eines INI-File Parsers erklärt, denke das geht in die Richtung was Du machen möchtest.

    Gut Schuß
    VuuRWerK 😉



  • int_p ist bereits für mehrstellige Zahlen gedacht.



  • Danke für eure Hilfe. Ich hatte im obigen Bsp. in Zeile 11 einen Schreibfehler innerhalb des Strings. 😞 Jetzt geht das Bsp.

    Das von VuuRWerK verlinkte Tutorial habe ich mir heute morgen reingezogen. Doch stellt sich mir eine Frage:

    Wie kann ich Variablen überprüfen (Variablen aufgebaut wie in meinem Bsp.) wenn ich deren Reihenfolge nicht kenne? Ich möchte dem User nicht vorschreiben in welcher Reihenfolge er die Variablen angibt. Aber er soll sie nur einmal angeben können.

    Gruß, Goran



  • du kannst den einzelnen parsern semantic actions mitgeben, z.B. eine action die den gerade geparsten Variablennamen in einer Symboltabelle nachschlägt und bei einer wiederholten Deklaration Alarm schlägt.



  • Hallo, ich habe mich heute wieder an boost::spirit gemacht.

    Folgender Code funktioniert:

    #include <iostream>
    #include <iostream>
    #include <fstream>
    #include <string>
    #include <boost/spirit.hpp>
    
    using namespace std;
    using namespace boost::spirit;
    
    int main()
    {
        // rules
        rule<> comment = chlit<>('#') >> *(anychar_p - eol_p) >> eol_p;
        rule<> space = *(space_p | comment);
        rule<> hostName = repeat_p(4)[range<>('a','d')];
        rule<> hostIp   = repeat_p(4)[range<>('1','4')];
        rule<> converter = strlit<>("converter") >> space >> strlit<>("=")
            >> space >> strlit<>("\"") >> hostName >> strlit<>("\"")
            >> space;
        rule<> analyser = strlit<>("analyser") >> space >> strlit<>("=")
            >> space >> strlit<>("\"") >> hostIp >> strlit<>("\"")
            >> space;
        rule<> conf = space >> repeat_p(2)[converter | analyser] >> space;
    
        // open file
        ifstream f("test.conf");
        if(!f)
        {
            cerr << "Can't open config file!\n";
            exit(1);
        }
    
        // read file
        string s;
        while(f.good())
            getline(f,s,'~');
    
        // parse
        parse_info<> pi = parse(s.c_str(),conf);
        if(pi.full)
            cout << "File is OK:\n";
        else
            cout << "Can't understand \"Test.conf\" at position "
                << pi.length << ". Stopped at:\n" << pi.stop;
    
        return 0;
    }
    

    Bei folgender test.conf ist alles OK:

    converter ="abcd"
    
    	# bla	
    
    analyser="1234"
    # foo
    

    Sobald die Datei die def. Regeln verletzt (z.B. indem man aus "1234" "123" macht) beendet sich das Prog. mit einer Statusmeldung. Aber ich bekomme hier folgende Ausgabe:

    Can't understand "test.conf" at position 4294967295. Stopped here:
    "
    # foo

    Nun ist 4294967295 = 2^32-1. Was bedeutet das? Läuft hier was über? Damit kann ich dem Nutzer nicht sagen wo seine Datei fehlerhaft ist.

    Wisst ihr Rat?

    Gruß, Goran



  • Hab' jetzt eine Lösung:

    #include <iostream>
    #include <fstream>
    #include <string>
    #include <boost/spirit.hpp>
    
    using namespace std;
    using namespace boost::spirit;
    
    int main()
    {
        // rules
        rule<> comment = chlit<>('#') >> *(anychar_p - eol_p) >> eol_p;
        rule<> space = *(space_p | comment);
        rule<> hostName = repeat_p(4)[range<>('a','d')];
        rule<> hostIp   = repeat_p(4)[range<>('1','4')];
        rule<> converter = strlit<>("converter") >> space >> strlit<>("=")
    		>> space >> strlit<>("\"") >> hostName >> strlit<>("\"")
    		>> space;
        rule<> analyser = strlit<>("analyser") >> space >> strlit<>("=")
    		>> space >> strlit<>("\"") >> hostIp >> strlit<>("\"")
    		>> space;
        rule<> conf = space >> repeat_p(2)[converter | analyser] >> space;
    
        // open file
        ifstream f("test.conf");
        if(!f)
        {
            cerr << "Can't open config file!\n";
            exit(1);
        }
    
        // read file
        string s;
        while(f.good())
            getline(f,s,'~');
        const char * c = s.c_str();
    
        // parse
        parse_info<> p = parse(c,conf);
        if(p.full)
            cout << "File is OK:\n";
        else
            cout << "Can't understand \"Test.conf\" at position "
                << p.stop-s.c_str() << ".\n";
    
        return 0;
    }
    

Anmelden zum Antworten