Commit 729d30ec authored by twanvl's avatar twanvl

Made a Regex class that wraps either boost::regex or wxRegEx (split from ScriptRegex).

Use Regex for keywords.
parent 43ced447
This diff is collapsed.
......@@ -12,7 +12,7 @@
#include <util/prec.hpp>
#include <script/scriptable.hpp>
#include <util/dynamic_arg.hpp>
#include <wx/regex.h>
#include <util/regex.hpp>
DECLARE_POINTER_TYPE(KeywordParam);
DECLARE_POINTER_TYPE(KeywordMode);
......@@ -42,11 +42,11 @@ class KeywordParam : public IntrusivePtrBase<KeywordParam> {
bool optional; ///< Can this parameter be left out (a placeholder is then used)
String match; ///< Regular expression to match (including separators)
String separator_before_is; ///< Regular expression of separator before the param
wxRegEx separator_before_re; ///< Regular expression of separator before the param, compiled
wxRegEx separator_before_eat;///< Regular expression of separator before the param, if eat_separator
Regex separator_before_re; ///< Regular expression of separator before the param, compiled
Regex separator_before_eat;///< Regular expression of separator before the param, if eat_separator
String separator_after_is; ///< Regular expression of separator after the param
wxRegEx separator_after_re; ///< Regular expression of separator after the param, compiled
wxRegEx separator_after_eat; ///< Regular expression of separator after the param, if eat_separator
Regex separator_after_re; ///< Regular expression of separator after the param, compiled
Regex separator_after_eat; ///< Regular expression of separator after the param, if eat_separator
bool eat_separator; ///< Remove the separator from the match string if it also appears there (prevent duplicates)
OptionalScript script; ///< Transformation of the value for showing as the parameter
OptionalScript reminder_script; ///< Transformation of the value for showing in the reminder text
......@@ -61,6 +61,11 @@ class KeywordParam : public IntrusivePtrBase<KeywordParam> {
/// Compile regexes for separators
void compile();
/// Remove separator_before from the end of the text
void eat_separator_before(String& text);
/// Advance i past separator_before if it is at position i in the text
void eat_separator_after(const String& text, size_t& i);
DECLARE_REFLECTION();
};
......@@ -96,7 +101,7 @@ class Keyword : public IntrusivePtrVirtualBase {
* captures 1,3,... capture the plain text of the match string
* captures 2,4,... capture the separators and parameters
*/
wxRegEx match_re;
Regex match_re;
bool fixed; ///< Is this keyword uneditable? (true for game keywods, false for set keywords)
bool valid; ///< Is this keyword okay (reminder text compiles & runs; match does not match "")
......
......@@ -26,6 +26,8 @@
BasicRuntimeChecks="3"
RuntimeLibrary="5"
BufferSecurityCheck="TRUE"
TreatWChar_tAsBuiltInType="FALSE"
ForceConformanceInForLoopScope="TRUE"
RuntimeTypeInfo="TRUE"
UsePrecompiledHeader="3"
PrecompiledHeaderThrough="util/prec.hpp"
......@@ -98,6 +100,8 @@
RuntimeLibrary="4"
BufferSecurityCheck="FALSE"
EnableFunctionLevelLinking="TRUE"
TreatWChar_tAsBuiltInType="FALSE"
ForceConformanceInForLoopScope="TRUE"
RuntimeTypeInfo="TRUE"
UsePrecompiledHeader="3"
PrecompiledHeaderThrough="util/prec.hpp"
......@@ -165,6 +169,8 @@
BasicRuntimeChecks="3"
RuntimeLibrary="3"
BufferSecurityCheck="TRUE"
TreatWChar_tAsBuiltInType="FALSE"
ForceConformanceInForLoopScope="TRUE"
RuntimeTypeInfo="TRUE"
UsePrecompiledHeader="3"
PrecompiledHeaderThrough="util/prec.hpp"
......@@ -241,6 +247,8 @@
BufferSecurityCheck="FALSE"
EnableFunctionLevelLinking="TRUE"
EnableEnhancedInstructionSet="1"
TreatWChar_tAsBuiltInType="FALSE"
ForceConformanceInForLoopScope="TRUE"
RuntimeTypeInfo="TRUE"
UsePrecompiledHeader="3"
PrecompiledHeaderThrough="util/prec.hpp"
......@@ -317,6 +325,8 @@
BufferSecurityCheck="FALSE"
EnableFunctionLevelLinking="TRUE"
EnableEnhancedInstructionSet="1"
TreatWChar_tAsBuiltInType="FALSE"
ForceConformanceInForLoopScope="TRUE"
RuntimeTypeInfo="TRUE"
UsePrecompiledHeader="3"
PrecompiledHeaderThrough="util/prec.hpp"
......@@ -393,6 +403,8 @@
BufferSecurityCheck="FALSE"
EnableFunctionLevelLinking="TRUE"
EnableEnhancedInstructionSet="1"
TreatWChar_tAsBuiltInType="FALSE"
ForceConformanceInForLoopScope="TRUE"
RuntimeTypeInfo="TRUE"
UsePrecompiledHeader="3"
PrecompiledHeaderThrough="util/prec.hpp"
......@@ -462,6 +474,8 @@
BasicRuntimeChecks="0"
RuntimeLibrary="3"
BufferSecurityCheck="FALSE"
TreatWChar_tAsBuiltInType="FALSE"
ForceConformanceInForLoopScope="TRUE"
RuntimeTypeInfo="TRUE"
UsePrecompiledHeader="2"
PrecompiledHeaderThrough="util/prec.hpp"
......@@ -2242,6 +2256,54 @@
<File
RelativePath=".\util\real_point.hpp">
</File>
<File
RelativePath=".\util\regex.cpp">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCLCompilerTool"
ObjectFile="$(IntDir)/$(InputName)1.obj"/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32">
<Tool
Name="VCCLCompilerTool"
ObjectFile="$(IntDir)/$(InputName)1.obj"/>
</FileConfiguration>
<FileConfiguration
Name="Debug Unicode|Win32">
<Tool
Name="VCCLCompilerTool"
ObjectFile="$(IntDir)/$(InputName)1.obj"/>
</FileConfiguration>
<FileConfiguration
Name="Release Unicode|Win32">
<Tool
Name="VCCLCompilerTool"
ObjectFile="$(IntDir)/$(InputName)1.obj"/>
</FileConfiguration>
<FileConfiguration
Name="Release Profile Unicode|Win32">
<Tool
Name="VCCLCompilerTool"
ObjectFile="$(IntDir)/$(InputName)1.obj"/>
</FileConfiguration>
<FileConfiguration
Name="Release Unicode fast build|Win32">
<Tool
Name="VCCLCompilerTool"
ObjectFile="$(IntDir)/$(InputName)1.obj"/>
</FileConfiguration>
<FileConfiguration
Name="Debug Unicode NoInit|Win32">
<Tool
Name="VCCLCompilerTool"
ObjectFile="$(IntDir)/$(InputName)1.obj"/>
</FileConfiguration>
</File>
<File
RelativePath=".\util\regex.hpp">
</File>
<File
RelativePath=".\util\vector2d.hpp">
</File>
......
......@@ -9,144 +9,24 @@
#include <util/prec.hpp>
#include <script/functions/functions.hpp>
#include <script/functions/util.hpp>
#include <util/regex.hpp>
#include <util/error.hpp>
// Use boost::regex as opposed to wxRegex
/* 2008-09-01:
* Script profiling shows that the boost library is significantly faster:
* When loading a large magic set (which calls ScriptManager::updateAll):
* function Calls wxRegEx boost
* ------------------------------------------------------------------
* replace 3791 0.38607 0.20857
* filter_text 11 0.32251 0.02446
*
* (times are avarage over all calls, in ms)
*/
#define USE_BOOST_REGEX 1
#if USE_BOOST_REGEX
#include <boost/regex.hpp>
#include <boost/regex/pattern_except.hpp>
typedef boost::basic_regex<Char> BoostRegex;
#endif
DECLARE_POINTER_TYPE(ScriptRegex);
DECLARE_TYPEOF_COLLECTION(pair<Variable COMMA ScriptValueP>);
// ----------------------------------------------------------------------------- : Regex type
/// A regular expression for use in a script
class ScriptRegex : public ScriptValue {
class ScriptRegex : public ScriptValue, public Regex {
public:
virtual ScriptType type() const { return SCRIPT_REGEX; }
virtual String typeName() const { return _("regex"); }
#if USE_BOOST_REGEX
ScriptRegex(const String& code) {
// compile string
try {
regex.assign(code.begin(),code.end());
} catch (const boost::regex_error& e) {
/// TODO: be more precise
throw ScriptError(String::Format(_("Error while compiling regular expression: '%s'\nAt position: %d\n%s"),
code.c_str(), e.position(), String(e.what(), IF_UNICODE(wxConvUTF8,String::npos))));
}
}
struct Results : public boost::match_results<const Char*> {
/// Get a sub match
inline String str(int sub = 0) const {
const_reference v = (*this)[sub];
return String(v.first, v.second);
}
/// Format a replacement string
inline String format(const String& format) const {
std::basic_string<Char> fmt(format.begin(),format.end());
String output;
boost::match_results<const Char*>::format(
insert_iterator<String>(output, output.end()), fmt, boost::format_sed);
return output;
}
};
inline bool matches(const String& str) {
return regex_search(str.c_str(), regex);
}
inline bool matches(Results& results, const Char* begin, const Char* end) {
return regex_search(begin, end, results, regex);
}
inline void replace_all(String* input, const String& format) {
//std::basic_string<Char> fmt; format_string(format,fmt);
std::basic_string<Char> fmt(format.begin(),format.end());
String output;
regex_replace(insert_iterator<String>(output, output.end()),
input->begin(), input->end(), regex, fmt, boost::format_sed);
*input = output;
}
private:
BoostRegex regex; ///< The regular expression
#else
ScriptRegex(const String& code) {
// compile string
if (!regex.Compile(code, wxRE_ADVANCED)) {
throw ScriptError(_("Error while compiling regular expression: '") + code + _("'"));
}
assert(regex.IsValid());
}
// Interface for compatability with boost::regex
struct Results {
typedef pair<const Char*,const Char*> value_type; // (begin,end)
typedef value_type const_reference;
/// Number of submatches (+1 for the total match)
inline size_t size() const { return regex->GetMatchCount(); }
/// Get a submatch
inline value_type operator [] (int sub) const {
size_t pos, length;
bool ok = regex->GetMatch(&pos, &length, sub);
assert(ok);
return make_pair(begin + pos, begin + pos + length);
}
/// Get a sub match
inline String str(int sub = 0) const {
const_reference v = (*this)[sub];
return String(v.first, v.second);
}
/// Format a replacement string
inline String format(const String& format) const {
const_reference v = (*this)[0];
String inside(v.first, v.second);
regex->ReplaceFirst(&inside, format);
return inside;
}
private:
wxRegEx* regex;
const Char* begin;
friend class ScriptRegex;
};
inline bool matches(const String& str) {
return regex.Matches(str);
}
inline bool matches(Results& results, const Char* begin, const Char* end) {
results.regex = &regex;
results.begin = begin;
return regex.Matches(begin, 0, end - begin);
}
inline void replace_all(String* input, const String& format) {
regex.Replace(input, format);
}
private:
wxRegEx regex; ///< The regular expression
#endif
ScriptRegex(const String& code) {
assign(code);
}
public:
/// Match only if in_context also matches
bool matches(Results& results, const String& str, const Char* begin, const ScriptRegexP& in_context) {
if (!in_context) {
......@@ -156,15 +36,16 @@ class ScriptRegex : public ScriptValue {
Results::const_reference match = results[0];
String context_str(str.begin(), match.first); // before
context_str += _("<match>");
context_str.append(match.second, str.end());
context_str.append(match.second, str.end()); // after
if (in_context->matches(context_str)) {
return true;
return true; // the context matches, done
}
begin = match.second; // skip
}
return false;
}
}
using Regex::matches;
};
ScriptRegexP regex_from_script(const ScriptValueP& value) {
......
......@@ -28,7 +28,7 @@
#include <wx/wx.h>
#include <wx/image.h>
#include <wx/datetime.h>
#include <wx/regex.h>
#include <wx/regex.h> // TODO : remove, see regex.hpp
// Std headers
#include <vector>
......@@ -78,6 +78,15 @@ class FileName : public wxString {
#include "locale.hpp"
#include "error.hpp"
#include "reflect.hpp"
#include "regex.hpp"
#ifdef _MSC_VER
//# pragma conform(forScope,on) // in "for(int x=..);" x goes out of scope after the for
// somehow forScope pragma doesn't work in precompiled headers, use this hack instead:
#ifdef _DEBUG
#define for if(false);else for
#endif
#endif
// ----------------------------------------------------------------------------- : EOF
#endif
//+----------------------------------------------------------------------------+
//| Description: Magic Set Editor - Program to make Magic (tm) cards |
//| Copyright: (C) 2001 - 2008 Twan van Laarhoven and "coppro" |
//| License: GNU General Public License 2 or later (see file COPYING) |
//+----------------------------------------------------------------------------+
// ----------------------------------------------------------------------------- : Includes
#include <util/prec.hpp>
#include <util/regex.hpp>
#include <util/error.hpp>
#if USE_BOOST_REGEX
// ----------------------------------------------------------------------------- : Regex : boost
void Regex::assign(const String& code) {
// compile string
try {
regex.assign(code.begin(),code.end());
} catch (const boost::regex_error& e) {
/// TODO: be more precise
throw ScriptError(String::Format(_("Error while compiling regular expression: '%s'\nAt position: %d\n%s"),
code.c_str(), e.position(), String(e.what(), IF_UNICODE(wxConvUTF8,String::npos))));
}
}
void Regex::replace_all(String* input, const String& format) {
//std::basic_string<Char> fmt; format_string(format,fmt);
std::basic_string<Char> fmt(format.begin(),format.end());
String output;
regex_replace(insert_iterator<String>(output, output.end()),
input->begin(), input->end(), regex, fmt, boost::format_sed);
*input = output;
}
#else // USE_BOOST_REGEX
// ----------------------------------------------------------------------------- : Regex : wx
void Regex::assign(const String& code) {
// compile string
if (!regex.Compile(code, wxRE_ADVANCED)) {
throw ScriptError(_("Error while compiling regular expression: '") + code + _("'"));
}
assert(regex.IsValid());
}
#endif // USE_BOOST_REGEX
// ----------------------------------------------------------------------------- : Regex : common
//+----------------------------------------------------------------------------+
//| Description: Magic Set Editor - Program to make Magic (tm) cards |
//| Copyright: (C) 2001 - 2008 Twan van Laarhoven and "coppro" |
//| License: GNU General Public License 2 or later (see file COPYING) |
//+----------------------------------------------------------------------------+
#ifndef HEADER_UTIL_REGEX
#define HEADER_UTIL_REGEX
// ----------------------------------------------------------------------------- : Includes
#include <util/prec.hpp>
// Use boost::regex as opposed to wxRegex
/* 2008-09-01:
* Script profiling shows that the boost library is significantly faster:
* When loading a large magic set (which calls ScriptManager::updateAll):
* function Calls wxRegEx boost
* ------------------------------------------------------------------
* replace 3791 0.38607 0.20857
* filter_text 11 0.32251 0.02446
*
* (times are avarage over all calls, in ms)
*/
#define USE_BOOST_REGEX 1
#if USE_BOOST_REGEX
#include <boost/regex.hpp>
#include <boost/regex/pattern_except.hpp>
#endif
// ----------------------------------------------------------------------------- : Boost implementation
#if USE_BOOST_REGEX
/// Our own regular expression wrapper
/** Suppors both boost::regex and wxRegEx.
* Has an interface like boost::regex, but compatible with wxStrings.
*/
class Regex {
public:
struct Results : public boost::match_results<const Char*> {
/// Get a sub match
inline String str(int sub = 0) const {
const_reference v = (*this)[sub];
return String(v.first, v.second);
}
/// Format a replacement string
inline String format(const String& format) const {
std::basic_string<Char> fmt(format.begin(),format.end());
String output;
boost::match_results<const Char*>::format(
insert_iterator<String>(output, output.end()), fmt, boost::format_sed);
return output;
}
};
void assign(const String& code);
inline bool matches(const String& str) const {
return regex_search(str.begin(), str.end(), regex);
}
inline bool matches(Results& results, const String& str) const {
return regex_search(str.begin(), str.end(), results, regex);
}
inline bool matches(Results& results, const Char* begin, const Char* end) const {
return regex_search(begin, end, results, regex);
}
void replace_all(String* input, const String& format);
inline bool empty() const {
return regex.empty();
}
private:
boost::basic_regex<Char> regex; ///< The regular expression
};
// ----------------------------------------------------------------------------- : Wx implementation
#else
/// Our own regular expression wrapper
/** Suppors both boost::regex and wxRegEx.
* Has an interface like boost::regex.
*/
class Regex
public:
// Interface for compatability with boost::regex
class Results {
public:
typedef pair<const Char*,const Char*> value_type; // (begin,end)
typedef value_type const_reference;
/// Number of submatches (+1 for the total match)
inline size_t size() const { return regex->GetMatchCount(); }
/// Get a submatch
inline value_type operator [] (int sub) const {
size_t pos, length;
bool ok = regex->GetMatch(&pos, &length, sub);
assert(ok);
return make_pair(begin + pos, begin + pos + length);
}
inline size_t position(int sub = 0) const {
size_t pos, length;
bool ok = regex->GetMatch(&pos, &length, sub);
assert(ok);
return pos;
}
inline size_t length(int sub = 0) const {
size_t pos, length;
bool ok = regex->GetMatch(&pos, &length, sub);
assert(ok);
return length;
}
/// Get a sub match
inline String str(int sub = 0) const {
const_reference v = (*this)[sub];
return String(v.first, v.second);
}
/// Format a replacement string
inline String format(const String& format) const {
const_reference v = (*this)[0];
String inside(v.first, v.second);
regex->ReplaceFirst(&inside, format);
return inside;
}
private:
wxRegEx* regex;
const Char* begin;
friend class ScriptRegex;
};
void assign(const String& code);
inline bool matches(const String& str) const {
return regex.Matches(str);
}
inline bool matches(Results& results, const String& str) const {
results.regex = &regex;
results.begin = str.begin();
return regex.Matches(str);
}
inline bool matches(Results& results, const Char* begin, const Char* end) const {
results.regex = &regex;
results.begin = begin;
return regex.Matches(begin, 0, end - begin);
}
inline void replace_all(String* input, const String& format) {
regex.Replace(input, format);
}
inline bool empty() const {
return !regex.IsValid();
}
private:
wxRegEx regex; ///< The regular expression
};
#endif
// ----------------------------------------------------------------------------- : EOF
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment