mirror of
https://github.com/amyinspace/MagicSetEditor2.git
synced 2026-06-10 04:57:00 -04:00
Added some more classes for ScriptErrors;
Added split_text function, which is the 'opposite' of break_text; Script code "f\n(stuff)" now parses as "f;stuff" instead of a function call, "f(stuff)"; Fixed bug in cursor movement, which caused the closing > of a tag at end of input to be overwritten. git-svn-id: svn://svn.code.sf.net/p/magicseteditor/code/trunk@1175 0fc631ac-6414-0410-93d0-97cfa31319b6
This commit is contained in:
@@ -74,7 +74,7 @@ ScriptValueP Context::eval(const Script& script, bool useScope) {
|
||||
// Get a variable
|
||||
case I_GET_VAR: {
|
||||
ScriptValueP value = variables[i.data].value;
|
||||
if (!value) throw ScriptError(_("Variable not set: ") + variable_to_string((Variable)i.data));
|
||||
if (!value) throw ScriptErrorNoVariable(variable_to_string((Variable)i.data));
|
||||
stack.push_back(value);
|
||||
break;
|
||||
}
|
||||
@@ -124,7 +124,7 @@ ScriptValueP Context::eval(const Script& script, bool useScope) {
|
||||
// Function call
|
||||
case I_CALL: {
|
||||
// new scope
|
||||
size_t scope = openScope();
|
||||
LocalScope local_scope(*this);
|
||||
// prepare arguments
|
||||
for (unsigned int j = 0 ; j < i.data ; ++j) {
|
||||
setVariable((Variable)instr[i.data - j - 1].data, stack.back());
|
||||
@@ -135,7 +135,6 @@ ScriptValueP Context::eval(const Script& script, bool useScope) {
|
||||
// get function and call
|
||||
stack.back() = stack.back()->eval(*this);
|
||||
} catch (const Error& e) {
|
||||
closeScope(scope);
|
||||
// try to determine what named function was called
|
||||
// the instructions for this look like:
|
||||
// I_GET_VAR name of function
|
||||
@@ -152,8 +151,6 @@ ScriptValueP Context::eval(const Script& script, bool useScope) {
|
||||
throw e; // rethrow
|
||||
}
|
||||
}
|
||||
// restore scope
|
||||
closeScope(scope);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -241,7 +238,7 @@ void Context::setVariable(Variable name, const ScriptValueP& value) {
|
||||
|
||||
ScriptValueP Context::getVariable(const String& name) {
|
||||
ScriptValueP value = variables[string_to_variable(name)].value;
|
||||
if (!value) throw ScriptError(_("Variable not set: ") + name);
|
||||
if (!value) throw ScriptErrorNoVariable(name);
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -250,7 +247,7 @@ ScriptValueP Context::getVariableOpt(const String& name) {
|
||||
}
|
||||
ScriptValueP Context::getVariable(Variable var) {
|
||||
if (variables[var].value) return variables[var].value;
|
||||
throw ScriptError(_("Variable not set: ") + variable_to_string(var));
|
||||
throw ScriptErrorNoVariable(variable_to_string(var));
|
||||
}
|
||||
ScriptValueP Context::getVariableInScopeOpt(Variable var) {
|
||||
if (variables[var].level == level) return variables[var].value;
|
||||
|
||||
@@ -110,14 +110,14 @@ SCRIPT_FUNCTION(to_int) {
|
||||
} else if (str.empty()) {
|
||||
result = 0;
|
||||
} else {
|
||||
return delayError(_ERROR_3_("can't convert value", str, input->typeName(), _TYPE_("integer")));
|
||||
return delay_error(ScriptErrorConversion(str, input->typeName(), _TYPE_("integer")));
|
||||
}
|
||||
} else {
|
||||
result = (int)*input;
|
||||
}
|
||||
SCRIPT_RETURN(result);
|
||||
} catch (const ScriptError& e) {
|
||||
return new_intrusive1<ScriptDelayedError>(e);
|
||||
return delay_error(e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -136,14 +136,14 @@ SCRIPT_FUNCTION(to_real) {
|
||||
if (str.empty()) {
|
||||
result = 0.0;
|
||||
} else if (!str.ToDouble(&result)) {
|
||||
return delayError(_ERROR_3_("can't convert value", str, input->typeName(), _TYPE_("double")));
|
||||
return delay_error(ScriptErrorConversion(str, input->typeName(), _TYPE_("double")));
|
||||
}
|
||||
} else {
|
||||
result = (double)*input;
|
||||
}
|
||||
SCRIPT_RETURN(result);
|
||||
} catch (const ScriptError& e) {
|
||||
return new_intrusive1<ScriptDelayedError>(e);
|
||||
return delay_error(e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -170,11 +170,11 @@ SCRIPT_FUNCTION(to_number) {
|
||||
} else if (str.empty()) {
|
||||
SCRIPT_RETURN(0);
|
||||
} else {
|
||||
return delayError(_ERROR_3_("can't convert value", str, input->typeName(), _TYPE_("double")));
|
||||
return delay_error(ScriptErrorConversion(str, input->typeName(), _TYPE_("double")));
|
||||
}
|
||||
}
|
||||
} catch (const ScriptError& e) {
|
||||
return new_intrusive1<ScriptDelayedError>(e);
|
||||
return delay_error(e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -190,7 +190,7 @@ SCRIPT_FUNCTION(to_boolean) {
|
||||
}
|
||||
SCRIPT_RETURN(result);
|
||||
} catch (const ScriptError& e) {
|
||||
return new_intrusive1<ScriptDelayedError>(e);
|
||||
return delay_error(e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -199,7 +199,7 @@ SCRIPT_FUNCTION(to_color) {
|
||||
SCRIPT_PARAM_C(AColor, input);
|
||||
SCRIPT_RETURN(input);
|
||||
} catch (const ScriptError& e) {
|
||||
return new_intrusive1<ScriptDelayedError>(e);
|
||||
return delay_error(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -124,7 +124,7 @@ SCRIPT_FUNCTION(symbol_variation) {
|
||||
if (value) {
|
||||
filename = value->filename;
|
||||
} else if (valueO) {
|
||||
throw ScriptError(_ERROR_2_("can't convert", valueO->typeName(), _TYPE_("symbol" )));
|
||||
throw ScriptErrorConversion(valueO->typeName(), _TYPE_("symbol" ));
|
||||
} else {
|
||||
filename = from_script<String>(symbol);
|
||||
}
|
||||
|
||||
@@ -192,6 +192,38 @@ SCRIPT_FUNCTION_SIMPLIFY_CLOSURE(break_text) {
|
||||
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
|
||||
while (match->regex.Matches(input)) {
|
||||
// match, append to result
|
||||
size_t start, len;
|
||||
bool ok = match->regex.GetMatch(&start, &len, 0);
|
||||
assert(ok);
|
||||
if (include_empty || start > 0) {
|
||||
ret->value.push_back(to_script(input.substr(0,start)));
|
||||
}
|
||||
input = input.substr(start + len); // everything after the match
|
||||
}
|
||||
if (include_empty || !input.empty()) {
|
||||
ret->value.push_back(to_script(input));
|
||||
}
|
||||
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();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------- : Rules : regex match
|
||||
|
||||
SCRIPT_FUNCTION_WITH_SIMPLIFY(match) {
|
||||
@@ -214,6 +246,7 @@ 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"), new_intrusive1<ScriptRule>(script_replace));
|
||||
ctx.setVariable(_("filter rule"), new_intrusive1<ScriptRule>(script_filter_text));
|
||||
|
||||
@@ -625,7 +625,7 @@ void parseExpr(TokenIterator& input, Script& script, Precedence minPrec) {
|
||||
void parseOper(TokenIterator& input, Script& script, Precedence minPrec, InstructionType closeWith, int closeWithData) {
|
||||
size_t added = script.getInstructions().size(); // number of instructions added
|
||||
parseExpr(input, script, minPrec); // first argument
|
||||
added -= script.getInstructions().size();
|
||||
added = script.getInstructions().size() - added;
|
||||
// read any operators after an expression
|
||||
// EBNF: expr = expr | expr oper expr
|
||||
// without left recursion: expr = expr (oper expr)*
|
||||
@@ -649,7 +649,7 @@ void parseOper(TokenIterator& input, Script& script, Precedence minPrec, Instruc
|
||||
// We made a mistake, the part before the := should be a variable name,
|
||||
// not an expression. Remove that instruction.
|
||||
Instruction& instr = script.getInstructions().back();
|
||||
if (added == 1 && instr.instr != I_GET_VAR) {
|
||||
if (added != 1 || instr.instr != I_GET_VAR) {
|
||||
input.add_error(_("Can only assign to variables"));
|
||||
}
|
||||
script.getInstructions().pop_back();
|
||||
@@ -695,9 +695,9 @@ void parseOper(TokenIterator& input, Script& script, Precedence minPrec, Instruc
|
||||
} else {
|
||||
input.expected(_("name"));
|
||||
}
|
||||
} else if (minPrec <= PREC_FUN && token==_("[")) { // get member by expr
|
||||
} else if (minPrec <= PREC_FUN && token==_("[") && !token.newline) { // get member by expr
|
||||
size_t before = script.getInstructions().size();
|
||||
parseOper(input, script, PREC_ALL);
|
||||
parseOper(input, script, PREC_SET);
|
||||
if (script.getInstructions().size() == before + 1 && script.getInstructions().back().instr == I_PUSH_CONST) {
|
||||
// optimize:
|
||||
// PUSH_CONST x
|
||||
@@ -709,7 +709,7 @@ void parseOper(TokenIterator& input, Script& script, Precedence minPrec, Instruc
|
||||
script.addInstruction(I_BINARY, I_MEMBER);
|
||||
}
|
||||
expectToken(input, _("]"), &token);
|
||||
} else if (minPrec <= PREC_FUN && token==_("(")) {
|
||||
} else if (minPrec <= PREC_FUN && token==_("(") && !token.newline) {
|
||||
// function call, read arguments
|
||||
vector<Variable> arguments;
|
||||
parseCallArguments(input, script, arguments);
|
||||
|
||||
@@ -79,9 +79,12 @@ class ScriptDelayedError : public ScriptValue {
|
||||
ScriptError error; // the error message
|
||||
};
|
||||
|
||||
inline ScriptValueP delayError(const String& m) {
|
||||
inline ScriptValueP delay_error(const String& m) {
|
||||
return new_intrusive1<ScriptDelayedError>(ScriptError(m));
|
||||
}
|
||||
inline ScriptValueP delay_error(const ScriptError& error) {
|
||||
return new_intrusive1<ScriptDelayedError>(error);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------- : Iterators
|
||||
|
||||
@@ -93,6 +96,7 @@ struct ScriptIterator : public ScriptValue {
|
||||
|
||||
/// Return the next item for this iterator, or ScriptValueP() if there is no such item
|
||||
virtual ScriptValueP next(ScriptValueP* key_out = nullptr) = 0;
|
||||
virtual ScriptValueP makeIterator(const ScriptValueP& thisP) const;
|
||||
};
|
||||
|
||||
// make an iterator over a range
|
||||
@@ -161,7 +165,7 @@ ScriptValueP get_member(const map<String,V>& m, const String& name) {
|
||||
if (it != m.end()) {
|
||||
return to_script(it->second);
|
||||
} else {
|
||||
return delayError(_ERROR_2_("has no member", _TYPE_("collection"), name));
|
||||
return delay_error(ScriptErrorNoMember(_TYPE_("collection"), name));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -171,7 +175,7 @@ ScriptValueP get_member(const IndexMap<K,V>& m, const String& name) {
|
||||
if (it != m.end()) {
|
||||
return to_script(*it);
|
||||
} else {
|
||||
return delayError(_ERROR_2_("has no member", _TYPE_("collection"), name));
|
||||
return delay_error(ScriptErrorNoMember(_TYPE_("collection"), name));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -389,7 +393,7 @@ inline ScriptValueP to_script(const Defaultable<T>& v) { return to_script(v());
|
||||
template <typename T> inline T from_script (const ScriptValueP& value) {
|
||||
ScriptObject<T>* o = dynamic_cast<ScriptObject<T>*>(value.get());
|
||||
if (!o) {
|
||||
throw ScriptError(_ERROR_2_("can't convert", value->typeName(), _TYPE_("object" )));
|
||||
throw ScriptErrorConversion(value->typeName(), _TYPE_("object" ));
|
||||
}
|
||||
return o->getValue();
|
||||
}
|
||||
|
||||
+17
-16
@@ -19,16 +19,16 @@ DECLARE_TYPEOF_COLLECTION(pair<Variable COMMA ScriptValueP>);
|
||||
// ----------------------------------------------------------------------------- : ScriptValue
|
||||
// Base cases
|
||||
|
||||
ScriptValue::operator String() const { throw ScriptError(_ERROR_2_("can't convert", typeName(), _TYPE_("string" ))); }
|
||||
ScriptValue::operator int() const { throw ScriptError(_ERROR_2_("can't convert", typeName(), _TYPE_("integer" ))); }
|
||||
ScriptValue::operator bool() const { throw ScriptError(_ERROR_2_("can't convert", typeName(), _TYPE_("boolean" ))); }
|
||||
ScriptValue::operator double() const { throw ScriptError(_ERROR_2_("can't convert", typeName(), _TYPE_("double" ))); }
|
||||
ScriptValue::operator AColor() const { throw ScriptError(_ERROR_2_("can't convert", typeName(), _TYPE_("color" ))); }
|
||||
ScriptValueP ScriptValue::eval(Context&) const { return delayError(_ERROR_2_("can't convert", typeName(), _TYPE_("function"))); }
|
||||
ScriptValue::operator String() const { throw ScriptErrorConversion(typeName(), _TYPE_("string" )); }
|
||||
ScriptValue::operator int() const { throw ScriptErrorConversion(typeName(), _TYPE_("integer" )); }
|
||||
ScriptValue::operator bool() const { throw ScriptErrorConversion(typeName(), _TYPE_("boolean" )); }
|
||||
ScriptValue::operator double() const { throw ScriptErrorConversion(typeName(), _TYPE_("double" )); }
|
||||
ScriptValue::operator AColor() const { throw ScriptErrorConversion(typeName(), _TYPE_("color" )); }
|
||||
ScriptValueP ScriptValue::eval(Context&) const { return delay_error(ScriptErrorConversion(typeName(), _TYPE_("function"))); }
|
||||
ScriptValueP ScriptValue::next(ScriptValueP* key_out) { throw InternalError(_("Can't convert from ")+typeName()+_(" to iterator")); }
|
||||
ScriptValueP ScriptValue::makeIterator(const ScriptValueP&) const { return delayError(_ERROR_2_("can't convert", typeName(), _TYPE_("collection"))); }
|
||||
int ScriptValue::itemCount() const { throw ScriptError(_ERROR_2_("can't convert", typeName(), _TYPE_("collection"))); }
|
||||
GeneratedImageP ScriptValue::toImage(const ScriptValueP&) const { throw ScriptError(_ERROR_2_("can't convert", typeName(), _TYPE_("image" ))); }
|
||||
ScriptValueP ScriptValue::makeIterator(const ScriptValueP&) const { return delay_error(ScriptErrorConversion(typeName(), _TYPE_("collection"))); }
|
||||
int ScriptValue::itemCount() const { throw ScriptErrorConversion(typeName(), _TYPE_("collection")); }
|
||||
GeneratedImageP ScriptValue::toImage(const ScriptValueP&) const { throw ScriptErrorConversion(typeName(), _TYPE_("image" )); }
|
||||
String ScriptValue::toCode() const { return *this; }
|
||||
CompareWhat ScriptValue::compareAs(String& compare_str, void const*& compare_ptr) const {
|
||||
compare_str = toCode();
|
||||
@@ -39,11 +39,11 @@ ScriptValueP ScriptValue::getMember(const String& name) const {
|
||||
if (name.ToLong(&index)) {
|
||||
return getIndex(index);
|
||||
} else {
|
||||
return delayError(_ERROR_2_("has no member", typeName(), name));
|
||||
return delay_error(ScriptErrorNoMember(typeName(), name));
|
||||
}
|
||||
}
|
||||
ScriptValueP ScriptValue::getIndex(int index) const {
|
||||
return delayError(_ERROR_2_("has no member", typeName(), String()<<index));
|
||||
return delay_error(ScriptErrorNoMember(typeName(), String()<<index));
|
||||
}
|
||||
|
||||
|
||||
@@ -122,6 +122,7 @@ ScriptValueP ScriptDelayedError::makeIterator(const ScriptValueP& thisP) const
|
||||
ScriptType ScriptIterator::type() const { return SCRIPT_ITERATOR; }
|
||||
String ScriptIterator::typeName() const { return _("iterator"); }
|
||||
CompareWhat ScriptIterator::compareAs(String&, void const*&) const { return COMPARE_NO; }
|
||||
ScriptValueP ScriptIterator::makeIterator(const ScriptValueP& thisP) const { return thisP; }
|
||||
|
||||
// Iterator over a range of integers
|
||||
class ScriptRangeIterator : public ScriptIterator {
|
||||
@@ -248,7 +249,7 @@ class ScriptString : public ScriptValue {
|
||||
if (value.ToDouble(&d)) {
|
||||
return d;
|
||||
} else {
|
||||
throw ScriptError(_ERROR_3_("can't convert value", value, typeName(), _TYPE_("double")));
|
||||
throw ScriptErrorConversion(value, typeName(), _TYPE_("double"));
|
||||
}
|
||||
}
|
||||
virtual operator int() const {
|
||||
@@ -256,7 +257,7 @@ class ScriptString : public ScriptValue {
|
||||
if (value.ToLong(&l)) {
|
||||
return l;
|
||||
} else {
|
||||
throw ScriptError(_ERROR_3_("can't convert value", value, typeName(), _TYPE_("integer")));
|
||||
throw ScriptErrorConversion(value, typeName(), _TYPE_("integer"));
|
||||
}
|
||||
}
|
||||
virtual operator bool() const {
|
||||
@@ -265,13 +266,13 @@ class ScriptString : public ScriptValue {
|
||||
} else if (value == _("no") || value == _("false") || value.empty()) {
|
||||
return false;
|
||||
} else {
|
||||
throw ScriptError(_ERROR_3_("can't convert value", value, typeName(), _TYPE_("boolean")));
|
||||
throw ScriptErrorConversion(value, typeName(), _TYPE_("boolean"));
|
||||
}
|
||||
}
|
||||
virtual operator AColor() const {
|
||||
AColor c = parse_acolor(value);
|
||||
if (!c.Ok()) {
|
||||
throw ScriptError(_ERROR_3_("can't convert value", value, typeName(), _TYPE_("color")));
|
||||
throw ScriptErrorConversion(value, typeName(), _TYPE_("color"));
|
||||
}
|
||||
return c;
|
||||
}
|
||||
@@ -285,7 +286,7 @@ class ScriptString : public ScriptValue {
|
||||
if (name.ToLong(&index) && index >= 0 && (size_t)index < value.size()) {
|
||||
return to_script(String(1,value[index]));
|
||||
} else {
|
||||
return delayError(_ERROR_2_("has no member value", value, name));
|
||||
return delay_error(_ERROR_2_("has no member value", value, name));
|
||||
}
|
||||
}
|
||||
private:
|
||||
|
||||
Reference in New Issue
Block a user