Regex frage



  • Meine Frage: Habe ich etwas im C++-Standard nicht verstanden oder liegen Fehler der Compiler vor? Zur Erläuterung:

    Die regulären Ausdrücke sollen in C++ laut C++Standard entsprechend dem ECMA-262-Standard behandelt werden. Ich habe jedoch beobachtet, dass das möglicherweise für g++ und clang++ nicht stimmt. Das folgende Testprogramm vergleicht boost::regex mit std::regex. Dabei liefert boost::regex meiner Meinung nach in jedem Fall das richtige Ergebnis.

    #include <boost/regex.hpp>
    #include <fstream>
    #include <iostream>
    #include <regex>
    #include <string>
    
    int main(int argc, char *argv[]) {
      std::string teststring = "text\na new line";
      std::string searched_for[]{"\\n", "(\\n)", "(\\n)"};
      std::string replacement[]{"\\n\\n", "\\1\\1", "$1$1"};
      std::string headers[] = {"parsing escape", "backreference \\d:",
                               "backreference $"};
      for (unsigned int testcase = 0; testcase < 3; ++testcase) {
        boost::regex boost_searched_for(searched_for[testcase]);
        std::string boostresult = boost::regex_replace(
            teststring, boost_searched_for, replacement[testcase]);
        std::cout << '\n' << headers[testcase] 
                  << "\nboost-regex:\n" << boostresult << '\n';
        std::regex std_searched_for(searched_for[testcase]);
        std::string stdresult = std::regex_replace(
            teststring, std_searched_for, replacement[testcase]);
        std::cout << "std-regex:\n" << stdresult << '\n';
      }
    }
    

    In den ersten beiden Testfällen stimmen die Ergebnisse nicht überein. Es stellt sichheraus, dass die Implementation von std::regex bei g++ und clang++ in den ersten beiden Fällen ein anderes Ergebnis als boost::regex liefert.

    std::regex interpretiert \n als literale Zeichen \ und n. boost::regex interpretiert sie richtig, entsprechend ECMA 21.2.2.10 CharacterEscape
    (Quelle: http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf, Stand Mai 2016)

    21.2.3.1 sagt bzgl des RegExp Konstruktors:
    "If pattern is supplied using a StringLiteral, the usual escape sequence substitutions are performed before the String is processed by RegExp"

    Auch Capturing Groups und Rückreferenzen werden nur von boost::regex richtig behandelt (Testfall 2), d.h. ein LF (line feed) wird durch zwei LFs ersetzt. ECMA-262 lautet am Ende von 21.2.2.1:

    "An EscapeValue is either a character or an integer. An EscapeValue is used to denote the interpretation of a DecimalEscape escape sequence: a character ch means that the escape sequence is interpreted as the character ch, while an integer n means that the escape sequence is interpreted as a backreference to the nth set of capturing parentheses."

    Nur die nach ECMA-262 ebenfalls erlaubten Rückreferenzen mit dem $-Zeichen werden in beiden Fällen richtig behandelt (Testfall 3).

    Habe ich etwas im C++- oder ECMA_Standard nicht verstanden oder liegen fehler der Compiler vor?
    (benutzt wurde g++ 6.1 und clang++4.0 (svn) mit -std++=c++14)


Anmelden zum Antworten