parent $libraries
object $parse
var $root child_index 0
var $root owners [$parse]
var $root fertile 0
var $root inited 1
var $root owned [$parse]
var $parse boolean_strs [["yes", "true", "1", "on"], ["no", "false", "0", "off"]]
var $root manager $parse
var $root writable [$parse]
var $root readable ['parameters, 'methods, 'code]
var $root dbref 'parse
method reference
arg string, [sep];
var middle, ref;
// receives: "<object><seperator><method/param>"
// returns ["<object>", "<method/param>"]
// seperator defaults to a period.
sep = [@sep, "."][1];
middle = sep in string;
if (!middle)
ref = [string, ""];
else if (middle == 1)
ref = [sender().namef(['dbref]), substr(string, 2)];
else
ref = [substr(string, 1, middle - 1), substr(string, middle + 1)];
// assumes "()" will appear at the end of the reference if at all,
// and strips it off if present
if ("()" in (ref[2]))
ref = [ref[1], substr(ref[2], 1, ("()" in (ref[2])) - 1)];
return ref;
.
method object_match
arg name, [who];
var msg;
// .object_match("name"[, who])
// -> 0 name was the empty string
// -> ~objnf nothing matched name
// -> ~ambig more than one object matched name
// Attempt to match an object name with who.match_environment(). If one is found, return it. Else, print a message and return one of the above false values.
// 'who' defaults to sender().
who = who ? who[1] | sender();
if (!name) {
(| who.tell("You must give the name of something.") |);
return 0;
}
catch ~objnf, ~ambig {
return who.match_environment(name);
} with handler {
switch (error()) {
case ~objnf:
msg = ("I don't see any \"" + name) + "\" here.";
case ~ambig:
msg = ("I don't know which \"" + name) + "\" you mean.";
}
(| who.tell(msg) |);
return error();
}
.
method tell_error
arg problem, [args];
var who, syntax, line, sprefix, prefix;
// arg 1 == error
// arg 2 (opt) == syntax
// arg 3 (opt) == who
// arg 4 (opt) == subbing object (in place of 'Object') -- string.
syntax = [@args, 0][1];
who = [@args, sender(), sender()][2];
sprefix = (| sender().setting("error-syntax-prefix") |) || "=> ";
prefix = (| sender().setting("error-prefix") |) || "! ";
if (syntax)
who.tell(((sprefix + "Syntax: `") + syntax) + "`");
if (problem) {
if (type(problem) == 'string) {
problem = $string.wrap_line(problem, (| who.linelen() |) || 79, prefix, 1);
} else {
for line in [1 .. listlen(problem)]
problem = replace(problem, line, prefix + (problem[line]));
}
who.tell(problem);
}
throw(~stop, "", 'no_traceback);
.
method usage
arg method, [dbref];
var code, extracted;
// .usage(method[, dbref])
// Extract initial comments from the given method, returning them as a list of strings.
// Throw ~methodnf if dbref does not define method.
// dbref defaults to sender.
dbref = dbref ? dbref[1] | sender();
dbref = dbref.find_method(method);
code = dbref.list_method(method);
extracted = [];
if ((code[1]) == "disallow_overrides;")
code = delete(code, 1);
if (("arg " in (code[1])) == 1)
code = delete(code, 1);
if (("var " in (code[1])) == 1)
code = delete(code, 1);
while (!(code[1]))
code = delete(code, 1);
while (("//" in (code[1])) == 1) {
extracted = [@extracted, strsub(code[1], "//", "")];
code = delete(code, 1);
}
return extracted;
.
method match
arg string;
var loc, obj;
// called by $user.match_* methods, simply parses up the basic me/here/$*
if (string == "me")
return sender();
if (string == "here")
return sender().location();
if (string && ((string[1]) == "$")) {
obj = toobj(substr(string, 2));
if (!valid(obj))
throw(~objnf, "No such object " + string);
return obj;
} else {
return 0;
}
.
method boolean
arg str;
if (str in (boolean_strs[1]))
return 1;
else if (str in (boolean_strs[2]))
return 0;
else
throw(~unknown, "Boolean flag not recognized.");
.
method full_reference
arg str, [args];
var sep, defobj, middle, ref, type, match;
defobj = [@args, sender()][1];
match = [@args, [$object, 'to_dbref], [$object, 'to_dbref]][2];
if ("()" in str)
str = substr(str, 1, ("()" in str) - 1);
if ("." in str) {
type = 'method;
sep = ".";
} else if ("," in str) {
type = 'parameter;
sep = ",";
} else {
type = 'unknown;
sep = ".";
}
middle = sep in str;
if (!middle)
ref = [(> (match[1]).(match[2])(str) <), ""];
else if (middle == 1)
ref = [defobj, substr(str, 2)];
else
ref = [(> (match[1]).(match[2])(substr(str, 1, middle - 1)) <), substr(str, middle + 1)];
return [type, ref[1], (ref[2]) ? tosym(ref[2]) | 0];
.
method traceback
arg traceback, [args];
var line, out, pre, lines, cur, x, error;
// $parse.traceback(traceback(), lines, pre);
// -1 lines represents the full error
// pre is set to "! " unless otherwise specified.
lines = [@args, -1][1];
pre = [@args, "! ", "! "][2];
error = [@args, 0, 0, 0][3];
//
out = [(pre + "=> ") + ((traceback[1])[2])];
pre = pre + " ";
//
if (error == 0)
out = [@out, (pre + "Thrown by ") + (._traceback(@sublist(traceback[2], 2)))];
else
out = [@out, (((pre + "Error ") + toliteral(error)) + " thrown by ") + (._traceback(@sublist(traceback[2], 2)))];
//
for x in [1 .. listlen(traceback) - 2] {
if ((x <= lines) || (lines == (-1))) {
line = ($data.unparse((traceback[x + 2])[1])) + ": ";
line = line + (._traceback(@sublist(traceback[x + 2], 2)));
out = [@out, pre + line];
}
}
return out;
.
method _traceback
arg what, [more];
var line;
if (more)
return (((((($data.unparse(more[1])) + ".") + tostr(what)) + "() (") + ($data.unparse(more[2]))) + ") line ") + tostr(more[3]);
else
return tostr(what);
.
method options
arg line, [defaults];
var loc, opt, x, out, defs;
// this will not pay attention to groupings with quotes, should add
// the functionality in later.
// templates: #[["opt", [0/1, 0/1]]]; / #[['opt, [bool, value]]];
defaults = [@defaults, #[]][1];
if (!(("-" in line) || ("+" in line)))
return [explode(line), defaults];
line = explode(line);
out = line;
for x in [1 .. listlen(line)] {
if (((line[x])[1]) in ["-", "+"]) {
out = setremove(out, line[x]);
opt = substr(line[x], 2);
defs = (| defaults[opt] |) || [0, ""];
defs = [((line[x])[1]) in ["+"], defs[2]];
if (defs[2]) {
if (listlen(line) >= (x + 1)) {
defs = [defs[1], line[x + 1]];
out = setremove(out, line[x + 1]);
}
}
defaults = dict_add(defaults, opt, defs);
}
}
return [out, defaults];
.
method my_options
arg line, options;
var args, word, c, pos, key, p, p2;
word = "";
args = "";
while (line) {
c = line[1];
switch (c) {
case "+":
pos = " " in line;
if (!pos) {
key = substr(line, 2);
line = "";
} else {
key = substr(line, 2, pos);
line = substr(line, pos);
}
key = tosym(key);
catch ~keynf {
if (((options[key])[1]) == 'bool)
options = dict_add(options, key, ['bool, 1]);
else
throw(~opttype, ("Option " + tostr(key)) + " is not boolean.");
} with handler {
throw(~badopt, ("Option " + tostr(key)) + " is not a valid option.");
}
case "-":
pos = " " in line;
if (!pos) {
key = substr(line, 2);
line = "";
} else {
key = substr(line, 2, pos);
line = substr(line, pos);
}
key = tosym(key);
catch ~keynf {
if (((options[key])[1]) == 'bool)
options = dict_add(options, key, ['bool, 0]);
else
throw(~opttype, ("Option " + tostr(key)) + " is not boolean.");
} with handler {
throw(~badopt, ("Option " + tostr(key)) + " is not a valid option.");
}
case "=":
key = word;
word = "";
pos = " " in line;
if (!pos)
pos = strlen(line);
key = tosym(key);
catch ~keynf {
if (((options[key])[1]) == 'value)
options = dict_add(options, key, ['value, substr(line, 2, pos - 1)]);
else
throw(~opttype, ("Option " + tostr(key)) + " is not a value.");
} with handler {
throw(~badopt, ("Option " + tostr(key)) + " is not a valid option.");
}
line = substr(line, pos + 1);
case " ":
args = args + word;
word = "";
line = substr(line, 2);
default:
pos = " " in line;
if (!pos)
pos = strlen(line);
p = "=" in line;
if ((p > 0) && (p < pos)) {
word = word + substr(line, 1, p - 1);
line = substr(line, p);
} else {
p = "-" in line;
p2 = "+" in line;
if (p2 < p)
p = p2;
if ((p > 0) && (p < pos)) {
args = args + substr(line, 1, p - 1);
line = substr(line, p);
} else {
args = args + substr(line, 1, pos);
line = substr(line, pos + 1);
}
}
}
}
args = args + word;
for key in (dict_keys(options)) {
word = (options[key])[2];
if (type(word) == 'string)
word = $string.trim(word);
options = dict_add(options, key, word);
}
return [args, options];
.
method xreference
arg str, [args];
var out, p, tmp, defobj, match;
defobj = [@args, sender()][1];
match = [@args, [$object, 'to_dbref], [$object, 'to_dbref]][2];
p = "<" in str;
if (p) {
out = [substr(str, 1, p - 1)];
tmp = substr(str, p + 1);
p = ">" in tmp;
if (!p)
throw(~parse, ("Unable to parse reference \"" + str) + "\".");
out = [out[1], substr(tmp, 1, p - 1)];
tmp = (> .split_reference(substr(tmp, p + 1)) <);
out = [tmp[1], @out, tmp[3]];
} else {
out = (> .split_reference(str) <);
out = [out[1], out[2], out[2], out[3]];
}
if (!(out[2]))
out = replace(out, 2, defobj);
else
out = replace(out, 2, (> (match[1]).(match[2])(out[2]) <));
if (!(out[3]))
out = replace(out, 3, defobj);
else
out = replace(out, 3, (> (match[1]).(match[2])(out[3]) <));
return out;
.
method split_reference
arg str;
var sep, type, mid;
if ("." in str) {
type = 'method;
sep = ".";
} else if (":" in str) {
type = 'variable;
sep = ":";
} else if (";" in str) {
type = 'anc_variable;
sep = ";";
} else {
throw(~parse, ("Invalid reference \"" + str) + "\"");
}
if (type == 'method) {
if ("()" in str)
str = substr(str, 1, ("()" in str) - 1);
}
mid = sep in str;
if (!mid)
return [type, str, 0];
else if (mid == 1)
return [type, "", tosym(substr(str, 2))];
else
return [type, substr(str, 1, mid - 1), tosym(substr(str, mid + 1))];
.
method range
arg str;
var out;
out = str.explode("-");
if (listlen(out) == 1) {
out = [(> ._range(str) <), 'single];
} else if (listlen(out) == 2) {
out = out.replace(1, (> ._range(out[1]) <));
out = out.replace(2, (> ._range(out[2]) <));
} else {
throw(~range, "Invalid range reference.");
}
return out;
.
method _range
arg str;
if (str.is_numeric()) {
return toint(str);
} else {
switch (str[1]) {
case "$":
return 'end;
case ".":
return 'current;
case "^":
return 'start;
default:
throw(~range, "Invalid range reference.");
}
}
.