Fix C++11 std::regex incompatibility

boost::regex supports escape sequences starting with a backslash in format
strings of regex_replace, but std::regex does not. Therefore format strings
involving literal backslashes have to be written differently for both flavours.

The special MSVC handling in regex.h is removed, since it is not needed
anymore, and using grep syntax would definitely be wrong.
This commit is contained in:
Georg Baum 2015-11-24 20:31:14 +01:00
parent 12faf2b161
commit e8211fb931
3 changed files with 23 additions and 62 deletions

View File

@ -670,11 +670,19 @@ static docstring escape_special_chars(docstring const & expr)
// $& is an ECMAScript format expression that expands to all
// of the current match
// The '$' must be prefixed with the escape character '\' for
// boost to treat it as a literal.
// Thus, to prefix a matched expression with '\', we use:
#if defined(LYX_USE_CXX11) && defined(LYX_USE_STD_REGEX)
// To prefix a matched expression with a single literal backslash, we
// need to escape it for the C++ compiler and use:
// FIXME: UNICODE
return from_utf8(lyx::regex_replace(to_utf8(expr), reg, string("\\$&")));
#else
// A backslash in the format string starts an escape sequence in boost.
// Thus, to prefix a matched expression with a single literal backslash,
// we need to give two backslashes to the regex engine, and escape both
// for the C++ compiler and use:
// FIXME: UNICODE
return from_utf8(lyx::regex_replace(to_utf8(expr), reg, string("\\\\$&")));
#endif
}

View File

@ -20,10 +20,17 @@ string const escape_special_chars(string const & expr)
// $& is a ECMAScript format expression that expands to all
// of the current match
// The '$' must be prefixed with the escape character '\' for
// boost to treat it as a literal.
// Thus, to prefix a matched expression with '\', we use:
#if defined(LYX_USE_CXX11) && defined(LYX_USE_STD_REGEX)
// To prefix a matched expression with a single literal backslash, we
// need to escape it for the C++ compiler and use:
return lyx::regex_replace(expr, reg, "\\$&");
#else
// A backslash in the format string starts an escape sequence in boost.
// Thus, to prefix a matched expression with a single literal backslash,
// we need to give two backslashes to the regex engine, and escape both
// for the C++ compiler and use:
return lyx::regex_replace(expr, reg, "\\\\$&");
#endif
}

View File

@ -14,74 +14,20 @@
#if defined(LYX_USE_CXX11) && defined(LYX_USE_STD_REGEX)
# include <regex>
# ifdef _MSC_VER
namespace lyx {
// inheriting 'private' to see which functions are used and if there are
// other ECMAScript defaults
// FIXME: Is this really needed?
// If yes, then the MSVC regex implementation is not standard-conforming.
class regex : private std::regex
{
public:
regex() {}
regex(const regex& rhs) : std::regex(rhs) {}
template<class T>
regex(T t) : std::regex(t, std::regex_constants::grep) {}
template<class T>
void assign(T t) { std::regex::assign(t, std::regex_constants::grep); }
template<class T, class V>
void assign(T t, V v) { std::regex::assign(t, v); }
const std::regex& toStd() const { return *this; }
};
template<class T>
bool regex_match(T t, const regex& r) { return std::regex_match(t, r.toStd()); }
template<class T>
bool regex_match(T t, std::smatch& m, const regex& r) { return std::regex_match(t, m, r.toStd()); }
template<class T, class V>
bool regex_match(T t, V v, std::smatch& m, const regex& r) { return std::regex_match(t, v, m, r.toStd()); }
template<class T, class V>
std::string regex_replace(T t, const regex& r, V v) { return std::regex_replace(t, r.toStd(), v); }
template<class T, class V, class U, class H>
T regex_replace(T t, V v, U u, const regex& r, H h) { return std::regex_replace(t, v, u, r.toStd(), h); }
template<class T>
bool regex_search(T t, const regex& r) { return std::regex_search(t, r.toStd()); }
template<class T>
bool regex_search(T t, std::smatch& m, const regex& r) { return std::regex_search(t, m, r.toStd()); }
template<class T, class V>
bool regex_search(T t, V v, std::smatch& m, const regex& r) { return std::regex_search(t, v, m, r.toStd()); }
struct sregex_iterator : std::sregex_iterator
{
sregex_iterator() {}
template<class T, class V>
sregex_iterator(T t, V v, const regex& r) : std::sregex_iterator(t, v, r.toStd()) {}
};
}
# else
// <regex> in gcc is unusable in versions less than 4.9.0
// see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53631
# define LR_NS std
namespace lyx {
using LR_NS::regex;
using LR_NS::regex_match;
using LR_NS::regex_replace;
using LR_NS::regex_search;
using LR_NS::sregex_iterator;
}
# endif
#else
# include <boost/regex.hpp>
# define LR_NS boost
#endif
namespace lyx {
using LR_NS::regex;
using LR_NS::regex_match;
using LR_NS::regex_replace;
using LR_NS::regex_search;
using LR_NS::sregex_iterator;
}
#endif
namespace lyx {
using LR_NS::smatch;
using LR_NS::basic_regex;
using LR_NS::regex_error;