mirror of
https://github.com/amyinspace/MagicSetEditor2.git
synced 2026-06-10 21:06:59 -04:00
Change tabs to two spaces.
This commit is contained in:
+185
-185
@@ -20,238 +20,238 @@ DECLARE_TYPEOF_COLLECTION(pair<Variable COMMA ScriptValueP>);
|
||||
/// A regular expression for use in a script
|
||||
class ScriptRegex : public ScriptValue, public Regex {
|
||||
public:
|
||||
virtual ScriptType type() const { return SCRIPT_REGEX; }
|
||||
virtual String typeName() const { return _("regex"); }
|
||||
|
||||
ScriptRegex(const String& code) {
|
||||
assign(code);
|
||||
}
|
||||
|
||||
/// Match only if in_context also matches
|
||||
bool matches(Results& results, const String& str, String::const_iterator begin, const ScriptRegexP& in_context) {
|
||||
if (!in_context) {
|
||||
return matches(results, begin, str.end());
|
||||
} else {
|
||||
while (matches(results, begin, str.end())) {
|
||||
Results::const_reference match = results[0];
|
||||
String context_str(str.begin(), match.first); // before
|
||||
context_str += _("<match>");
|
||||
context_str.append(match.second, str.end()); // after
|
||||
if (in_context->matches(context_str)) {
|
||||
return true; // the context matches, done
|
||||
}
|
||||
begin = match.second; // skip
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
using Regex::matches;
|
||||
virtual ScriptType type() const { return SCRIPT_REGEX; }
|
||||
virtual String typeName() const { return _("regex"); }
|
||||
|
||||
ScriptRegex(const String& code) {
|
||||
assign(code);
|
||||
}
|
||||
|
||||
/// Match only if in_context also matches
|
||||
bool matches(Results& results, const String& str, String::const_iterator begin, const ScriptRegexP& in_context) {
|
||||
if (!in_context) {
|
||||
return matches(results, begin, str.end());
|
||||
} else {
|
||||
while (matches(results, begin, str.end())) {
|
||||
Results::const_reference match = results[0];
|
||||
String context_str(str.begin(), match.first); // before
|
||||
context_str += _("<match>");
|
||||
context_str.append(match.second, str.end()); // after
|
||||
if (in_context->matches(context_str)) {
|
||||
return true; // the context matches, done
|
||||
}
|
||||
begin = match.second; // skip
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
using Regex::matches;
|
||||
};
|
||||
|
||||
ScriptRegexP regex_from_script(const ScriptValueP& value) {
|
||||
// is it a regex already?
|
||||
ScriptRegexP regex = dynamic_pointer_cast<ScriptRegex>(value);
|
||||
if (!regex) {
|
||||
// TODO: introduce some kind of caching?
|
||||
regex = intrusive(new ScriptRegex(*value));
|
||||
}
|
||||
return regex;
|
||||
// is it a regex already?
|
||||
ScriptRegexP regex = dynamic_pointer_cast<ScriptRegex>(value);
|
||||
if (!regex) {
|
||||
// TODO: introduce some kind of caching?
|
||||
regex = intrusive(new ScriptRegex(*value));
|
||||
}
|
||||
return regex;
|
||||
}
|
||||
|
||||
template <> inline ScriptRegexP from_script<ScriptRegexP>(const ScriptValueP& value) {
|
||||
return regex_from_script(value);
|
||||
return regex_from_script(value);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------- : Rules : regex replace
|
||||
|
||||
struct RegexReplacer {
|
||||
ScriptRegexP match; ///< Regex to match
|
||||
ScriptRegexP context; ///< Match only in a given context, optional
|
||||
String replacement_string; ///< Replacement
|
||||
ScriptValueP replacement_function; ///< Replacement function instead of a simple string, optional
|
||||
bool recursive; ///< Recurse into the replacement
|
||||
|
||||
String apply(Context& ctx, const String& input, int level = 0) const {
|
||||
String ret;
|
||||
String::const_iterator start = input.begin();
|
||||
ScriptRegex::Results results;
|
||||
while (match->matches(results, input, start, context)) {
|
||||
// for each match ...
|
||||
ScriptRegex::Results::const_reference pos = results[0];
|
||||
ret.append(start, pos.first); // everything before the match position stays
|
||||
// determine replacement
|
||||
String inside;
|
||||
if (replacement_function) {
|
||||
// set match results in context
|
||||
for (UInt sub = 0 ; sub < results.size() ; ++sub) {
|
||||
String name = sub == 0 ? _("input") : String(_("_")) << sub;
|
||||
ctx.setVariable(name, to_script(results.str(sub)));
|
||||
}
|
||||
// call
|
||||
inside = replacement_function->eval(ctx)->toString();
|
||||
} else {
|
||||
inside = results.format(replacement_string);
|
||||
}
|
||||
// append replaced inside
|
||||
if (recursive && level < 20) {
|
||||
ret += apply(ctx, inside, level + 1);
|
||||
} else {
|
||||
ret += inside;
|
||||
}
|
||||
start = pos.second;
|
||||
}
|
||||
ret.append(start, input.end());
|
||||
return ret;
|
||||
}
|
||||
ScriptRegexP match; ///< Regex to match
|
||||
ScriptRegexP context; ///< Match only in a given context, optional
|
||||
String replacement_string; ///< Replacement
|
||||
ScriptValueP replacement_function; ///< Replacement function instead of a simple string, optional
|
||||
bool recursive; ///< Recurse into the replacement
|
||||
|
||||
String apply(Context& ctx, const String& input, int level = 0) const {
|
||||
String ret;
|
||||
String::const_iterator start = input.begin();
|
||||
ScriptRegex::Results results;
|
||||
while (match->matches(results, input, start, context)) {
|
||||
// for each match ...
|
||||
ScriptRegex::Results::const_reference pos = results[0];
|
||||
ret.append(start, pos.first); // everything before the match position stays
|
||||
// determine replacement
|
||||
String inside;
|
||||
if (replacement_function) {
|
||||
// set match results in context
|
||||
for (UInt sub = 0 ; sub < results.size() ; ++sub) {
|
||||
String name = sub == 0 ? _("input") : String(_("_")) << sub;
|
||||
ctx.setVariable(name, to_script(results.str(sub)));
|
||||
}
|
||||
// call
|
||||
inside = replacement_function->eval(ctx)->toString();
|
||||
} else {
|
||||
inside = results.format(replacement_string);
|
||||
}
|
||||
// append replaced inside
|
||||
if (recursive && level < 20) {
|
||||
ret += apply(ctx, inside, level + 1);
|
||||
} else {
|
||||
ret += inside;
|
||||
}
|
||||
start = pos.second;
|
||||
}
|
||||
ret.append(start, input.end());
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
SCRIPT_FUNCTION_WITH_SIMPLIFY(replace) {
|
||||
// construct replacer
|
||||
RegexReplacer replacer;
|
||||
replacer.match = from_script<ScriptRegexP>(ctx.getVariable(SCRIPT_VAR_match), SCRIPT_VAR_match);
|
||||
if (ctx.getVariableOpt(SCRIPT_VAR_in_context)) {
|
||||
replacer.context = from_script<ScriptRegexP>(ctx.getVariableOpt(SCRIPT_VAR_in_context), SCRIPT_VAR_in_context);
|
||||
}
|
||||
if (ctx.getVariableOpt(SCRIPT_VAR_recursive)) {
|
||||
replacer.recursive = from_script<bool>(ctx.getVariableOpt(SCRIPT_VAR_recursive), SCRIPT_VAR_recursive);
|
||||
} else {
|
||||
replacer.recursive = false;
|
||||
}
|
||||
replacer.replacement_function = ctx.getVariable(SCRIPT_VAR_replace);
|
||||
if (replacer.replacement_function->type() != SCRIPT_FUNCTION) {
|
||||
replacer.replacement_string = replacer.replacement_function->toString();
|
||||
replacer.replacement_function = ScriptValueP();
|
||||
}
|
||||
// run
|
||||
SCRIPT_PARAM_C(String, input);
|
||||
if (replacer.context || replacer.replacement_function || replacer.recursive) {
|
||||
SCRIPT_RETURN(replacer.apply(ctx, input));
|
||||
} else {
|
||||
// simple replacing
|
||||
replacer.match->replace_all(&input, replacer.replacement_string);
|
||||
SCRIPT_RETURN(input);
|
||||
}
|
||||
// construct replacer
|
||||
RegexReplacer replacer;
|
||||
replacer.match = from_script<ScriptRegexP>(ctx.getVariable(SCRIPT_VAR_match), SCRIPT_VAR_match);
|
||||
if (ctx.getVariableOpt(SCRIPT_VAR_in_context)) {
|
||||
replacer.context = from_script<ScriptRegexP>(ctx.getVariableOpt(SCRIPT_VAR_in_context), SCRIPT_VAR_in_context);
|
||||
}
|
||||
if (ctx.getVariableOpt(SCRIPT_VAR_recursive)) {
|
||||
replacer.recursive = from_script<bool>(ctx.getVariableOpt(SCRIPT_VAR_recursive), SCRIPT_VAR_recursive);
|
||||
} else {
|
||||
replacer.recursive = false;
|
||||
}
|
||||
replacer.replacement_function = ctx.getVariable(SCRIPT_VAR_replace);
|
||||
if (replacer.replacement_function->type() != SCRIPT_FUNCTION) {
|
||||
replacer.replacement_string = replacer.replacement_function->toString();
|
||||
replacer.replacement_function = ScriptValueP();
|
||||
}
|
||||
// run
|
||||
SCRIPT_PARAM_C(String, input);
|
||||
if (replacer.context || replacer.replacement_function || replacer.recursive) {
|
||||
SCRIPT_RETURN(replacer.apply(ctx, input));
|
||||
} else {
|
||||
// simple replacing
|
||||
replacer.match->replace_all(&input, replacer.replacement_string);
|
||||
SCRIPT_RETURN(input);
|
||||
}
|
||||
}
|
||||
SCRIPT_FUNCTION_SIMPLIFY_CLOSURE(replace) {
|
||||
FOR_EACH(b, closure.bindings) {
|
||||
if (b.first == SCRIPT_VAR_match || b.first == SCRIPT_VAR_in_context) {
|
||||
b.second = regex_from_script(b.second); // pre-compile
|
||||
}
|
||||
}
|
||||
return ScriptValueP();
|
||||
FOR_EACH(b, closure.bindings) {
|
||||
if (b.first == SCRIPT_VAR_match || b.first == SCRIPT_VAR_in_context) {
|
||||
b.second = regex_from_script(b.second); // pre-compile
|
||||
}
|
||||
}
|
||||
return ScriptValueP();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------- : Rules : regex filter
|
||||
|
||||
SCRIPT_FUNCTION_WITH_SIMPLIFY(filter_text) {
|
||||
SCRIPT_PARAM_C(String, input);
|
||||
SCRIPT_PARAM_C(ScriptRegexP, match);
|
||||
SCRIPT_OPTIONAL_PARAM_C_(ScriptRegexP, in_context);
|
||||
String ret;
|
||||
// find all matches
|
||||
String::const_iterator start = input.begin();
|
||||
ScriptRegex::Results results;
|
||||
while (match->matches(results, input, start, in_context)) {
|
||||
// match, append to result
|
||||
ScriptRegex::Results::const_reference pos = results[0];
|
||||
ret.append(pos.first, pos.second); // the match
|
||||
start = pos.second;
|
||||
}
|
||||
SCRIPT_RETURN(ret);
|
||||
SCRIPT_PARAM_C(String, input);
|
||||
SCRIPT_PARAM_C(ScriptRegexP, match);
|
||||
SCRIPT_OPTIONAL_PARAM_C_(ScriptRegexP, in_context);
|
||||
String ret;
|
||||
// find all matches
|
||||
String::const_iterator start = input.begin();
|
||||
ScriptRegex::Results results;
|
||||
while (match->matches(results, input, start, in_context)) {
|
||||
// match, append to result
|
||||
ScriptRegex::Results::const_reference pos = results[0];
|
||||
ret.append(pos.first, pos.second); // the match
|
||||
start = pos.second;
|
||||
}
|
||||
SCRIPT_RETURN(ret);
|
||||
}
|
||||
SCRIPT_FUNCTION_SIMPLIFY_CLOSURE(filter_text) {
|
||||
FOR_EACH(b, closure.bindings) {
|
||||
if (b.first == SCRIPT_VAR_match || b.first == SCRIPT_VAR_in_context) {
|
||||
b.second = regex_from_script(b.second); // pre-compile
|
||||
}
|
||||
}
|
||||
return ScriptValueP();
|
||||
FOR_EACH(b, closure.bindings) {
|
||||
if (b.first == SCRIPT_VAR_match || b.first == SCRIPT_VAR_in_context) {
|
||||
b.second = regex_from_script(b.second); // pre-compile
|
||||
}
|
||||
}
|
||||
return ScriptValueP();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------- : Rules : regex break
|
||||
|
||||
SCRIPT_FUNCTION_WITH_SIMPLIFY(break_text) {
|
||||
SCRIPT_PARAM_C(String, input);
|
||||
SCRIPT_PARAM_C(ScriptRegexP, match);
|
||||
SCRIPT_OPTIONAL_PARAM_C_(ScriptRegexP, in_context);
|
||||
ScriptCustomCollectionP ret(new ScriptCustomCollection);
|
||||
// find all matches
|
||||
String::const_iterator start = input.begin();
|
||||
ScriptRegex::Results results;
|
||||
while (match->matches(results, input, start, in_context)) {
|
||||
// match, append to result
|
||||
ret->value.push_back(to_script(results.str()));
|
||||
start = results[0].second;
|
||||
}
|
||||
return ret;
|
||||
SCRIPT_PARAM_C(String, input);
|
||||
SCRIPT_PARAM_C(ScriptRegexP, match);
|
||||
SCRIPT_OPTIONAL_PARAM_C_(ScriptRegexP, in_context);
|
||||
ScriptCustomCollectionP ret(new ScriptCustomCollection);
|
||||
// find all matches
|
||||
String::const_iterator start = input.begin();
|
||||
ScriptRegex::Results results;
|
||||
while (match->matches(results, input, start, in_context)) {
|
||||
// match, append to result
|
||||
ret->value.push_back(to_script(results.str()));
|
||||
start = results[0].second;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
SCRIPT_FUNCTION_SIMPLIFY_CLOSURE(break_text) {
|
||||
FOR_EACH(b, closure.bindings) {
|
||||
if (b.first == SCRIPT_VAR_match || b.first == SCRIPT_VAR_in_context) {
|
||||
b.second = regex_from_script(b.second); // pre-compile
|
||||
}
|
||||
}
|
||||
return ScriptValueP();
|
||||
FOR_EACH(b, closure.bindings) {
|
||||
if (b.first == SCRIPT_VAR_match || b.first == SCRIPT_VAR_in_context) {
|
||||
b.second = regex_from_script(b.second); // pre-compile
|
||||
}
|
||||
}
|
||||
return ScriptValueP();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------- : Rules : regex split
|
||||
|
||||
SCRIPT_FUNCTION_WITH_SIMPLIFY(split_text) {
|
||||
SCRIPT_PARAM_C(String, input);
|
||||
SCRIPT_PARAM_C(ScriptRegexP, match);
|
||||
SCRIPT_PARAM_DEFAULT_N(bool, _("include empty"), include_empty, true);
|
||||
ScriptCustomCollectionP ret(new ScriptCustomCollection);
|
||||
// find all matches
|
||||
String::const_iterator start = input.begin();
|
||||
ScriptRegex::Results results;
|
||||
while (match->matches(results, start, input.end())) {
|
||||
// match, append the part before it to the result
|
||||
ScriptRegex::Results::const_reference pos = results[0];
|
||||
if (include_empty || pos.first != start) {
|
||||
ret->value.push_back(to_script( String(start,pos.first) ));
|
||||
}
|
||||
start = pos.second;
|
||||
}
|
||||
if (include_empty || start != input.end()) {
|
||||
ret->value.push_back(to_script( String(start,input.end()) ));
|
||||
}
|
||||
return ret;
|
||||
SCRIPT_PARAM_C(String, input);
|
||||
SCRIPT_PARAM_C(ScriptRegexP, match);
|
||||
SCRIPT_PARAM_DEFAULT_N(bool, _("include empty"), include_empty, true);
|
||||
ScriptCustomCollectionP ret(new ScriptCustomCollection);
|
||||
// find all matches
|
||||
String::const_iterator start = input.begin();
|
||||
ScriptRegex::Results results;
|
||||
while (match->matches(results, start, input.end())) {
|
||||
// match, append the part before it to the result
|
||||
ScriptRegex::Results::const_reference pos = results[0];
|
||||
if (include_empty || pos.first != start) {
|
||||
ret->value.push_back(to_script( String(start,pos.first) ));
|
||||
}
|
||||
start = pos.second;
|
||||
}
|
||||
if (include_empty || start != input.end()) {
|
||||
ret->value.push_back(to_script( String(start,input.end()) ));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
SCRIPT_FUNCTION_SIMPLIFY_CLOSURE(split_text) {
|
||||
FOR_EACH(b, closure.bindings) {
|
||||
if (b.first == SCRIPT_VAR_match) {
|
||||
b.second = regex_from_script(b.second); // pre-compile
|
||||
}
|
||||
}
|
||||
return ScriptValueP();
|
||||
FOR_EACH(b, closure.bindings) {
|
||||
if (b.first == SCRIPT_VAR_match) {
|
||||
b.second = regex_from_script(b.second); // pre-compile
|
||||
}
|
||||
}
|
||||
return ScriptValueP();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------- : Rules : regex match
|
||||
|
||||
SCRIPT_FUNCTION_WITH_SIMPLIFY(match) {
|
||||
SCRIPT_PARAM_C(String, input);
|
||||
SCRIPT_PARAM_C(ScriptRegexP, match);
|
||||
SCRIPT_RETURN(match->matches(input));
|
||||
SCRIPT_PARAM_C(String, input);
|
||||
SCRIPT_PARAM_C(ScriptRegexP, match);
|
||||
SCRIPT_RETURN(match->matches(input));
|
||||
}
|
||||
SCRIPT_FUNCTION_SIMPLIFY_CLOSURE(match) {
|
||||
FOR_EACH(b, closure.bindings) {
|
||||
if (b.first == SCRIPT_VAR_match) {
|
||||
b.second = regex_from_script(b.second); // pre-compile
|
||||
}
|
||||
}
|
||||
return ScriptValueP();
|
||||
FOR_EACH(b, closure.bindings) {
|
||||
if (b.first == SCRIPT_VAR_match) {
|
||||
b.second = regex_from_script(b.second); // pre-compile
|
||||
}
|
||||
}
|
||||
return ScriptValueP();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------- : Init
|
||||
|
||||
void init_script_regex_functions(Context& ctx) {
|
||||
ctx.setVariable(_("replace"), script_replace);
|
||||
ctx.setVariable(_("filter text"), script_filter_text);
|
||||
ctx.setVariable(_("break text"), script_break_text);
|
||||
ctx.setVariable(_("split text"), script_split_text);
|
||||
ctx.setVariable(_("match"), script_match);
|
||||
ctx.setVariable(_("replace rule"), intrusive(new ScriptRule(script_replace)));
|
||||
ctx.setVariable(_("filter rule"), intrusive(new ScriptRule(script_filter_text)));
|
||||
ctx.setVariable(_("break rule"), intrusive(new ScriptRule(script_break_text)));
|
||||
ctx.setVariable(_("match rule"), intrusive(new ScriptRule(script_match)));
|
||||
ctx.setVariable(_("replace"), script_replace);
|
||||
ctx.setVariable(_("filter text"), script_filter_text);
|
||||
ctx.setVariable(_("break text"), script_break_text);
|
||||
ctx.setVariable(_("split text"), script_split_text);
|
||||
ctx.setVariable(_("match"), script_match);
|
||||
ctx.setVariable(_("replace rule"), intrusive(new ScriptRule(script_replace)));
|
||||
ctx.setVariable(_("filter rule"), intrusive(new ScriptRule(script_filter_text)));
|
||||
ctx.setVariable(_("break rule"), intrusive(new ScriptRule(script_break_text)));
|
||||
ctx.setVariable(_("match rule"), intrusive(new ScriptRule(script_match)));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user