new object $command_parser: $user_parsers;
var $root created_on = 796680318;
var $root flags = ['methods, 'code, 'core, 'variables];
var $root inited = 1;
var $root managed = [$command_parser];
var $root manager = $command_parser;
public method ._local() {
arg user, nmatch, match, template, method, info;
var x, cmd;
cmd = match[2];
catch any {
for x in [1 .. nmatch] {
if (dict_contains(info, x))
match = match.replace(x + 2, (> .convert_arg(cmd, (info[x])[1], match[x + 2], user, (info[x])[2], user) <));
}
} with {
if (error() == ~syntax)
return ['error, (((traceback()[1])[2]) + template) + "\""];
return ['error, (traceback()[1])[2]];
}
return ['command, user, method, @match];
};
public method ._remote() {
arg user, nmatch, definer, match, template, method, info;
var x, value, that, cmd;
cmd = match[2];
catch any {
for x in [1 .. nmatch] {
if (dict_contains(info, x)) {
if (((info[x])[1]) == 'this) {
that = (> user.match_environment(match[x + 2]) <);
if (!(that.is(definer)))
return ['error, ((("You cannot " + (match[2])) + " ") + (that.name())) + "."];
} else {
value = (> .convert_arg(cmd, (info[x])[1], match[x + 2], user, ((info[x])[2]) || [definer], user) <);
}
match = match.replace(x + 2, value);
}
}
} with {
if (error() == ~syntax)
return ['error, (((traceback()[1])[2]) + template) + "\""];
return ['error, (traceback()[1])[2]];
}
if (!that)
return ['error, "An error was encountered: no target object found."];
return ['command, that, method, @match];
};
public method .complete() {
arg cmd, user, obj, match, info;
var x, method, parsed;
method = info[2];
info = info[4];
parsed = info.keys();
for x in [1 .. match.length()] {
if (x in parsed)
match = match.replace(x, (> $command_lib.convert_arg((info[x])[1], match[x], user, ((info[x])[2]) ? ((info[x])[2]) : user, user) <));
}
return [user, method, (cmd.explode())[1], @match];
};
public method .convert_arg() {
arg cmd, type, str, me, argargs, target;
var obj, args, anc, out, x, y, list;
switch (type) {
case 'list:
out = [];
if (!str)
return [(> .convert_arg(cmd, argargs[1], "", me, argargs[2], target) <)];
// or do the whole list
if ("," in str)
list = str.explode_english_list(",");
else
list = explode(str);
for x in (list) {
catch ~ambig {
out = out.setadd(.convert_arg(cmd, argargs[1], x, me, argargs[2], target));
} with {
if ((| (traceback()[1])[3] |) && (!((argargs[1]) in ['user, 'user_opt]))) {
for y in ((traceback()[1])[3])
out = out.setadd((> .convert_arg(cmd, argargs[1], tostr(y), me, argargs[2], target) <));
} else {
rethrow(error());
}
}
}
return out;
case 'any:
return str;
case 'any_opt:
args = $parse_lib.opt(str, @argargs);
return args;
case 'object:
return (> me.match_environment(str) <);
case 'object_opt:
args = $parse_lib.opt(str, @argargs);
if (!(args[1]))
throw(~syntax, "No reference specified for command \"");
obj = (> me.match_environment((args[1])[1]) <);
return [obj, delete(args[1], 1), args[2]];
case 'objref:
return (> $parse_lib.ref(str, me) <);
case 'objref_opt:
args = $parse_lib.opt(str, @argargs);
if (!(args[1]))
throw(~syntax, "No reference specified for command \"");
obj = (> $parse_lib.ref((args[1])[1], me) <);
return [obj, delete(args[1], 1), args[2]];
case 'user:
if (!str)
throw(~match, "No user specified.");
if (str == "me")
return me;
return (| $user_db.search(str) |) || throw(~match, ("Unable to find user " + str) + ".");
case 'user_opt:
args = $parse_lib.opt(str, @argargs);
if (!(args[1]))
throw(~syntax, "Nobody specified for command \"");
if (str == "me")
return me;
return [(> $user_db.search((args[1])[1]) <), args[2]];
case 'number:
return (> str.to_number() <);
case 'number_opt:
args = $parse_lib.opt(str, @argargs);
if (!(args[1]))
throw(~syntax, "No number specified for command \"");
return [(> str.to_number() <), args[2]];
case 'descendant:
obj = (> me.match_environment(str) <);
anc = argargs ? (argargs[1]) : user;
if (!(obj.has_ancestor(anc)))
throw(~parse, strfmt("You cannot %s %s because it is not %s!", cmd, obj.name(), anc.name()));
return obj;
case 'descendant_opt:
args = $parse_lib.opt(str, @argargs);
if (!(args[1]))
throw(~syntax, "No descendant specified for command \"");
obj = (> me.match_environment((args[1])[1]) <);
anc = argargs ? (argargs[1]) : user;
if (!(obj.has_ancestor(anc)))
throw(~parse, strfmt("You cannot %s %s because it is not %s!", cmd, obj.name(), anc.name()));
return [obj, args[2]];
default:
throw(~ack, ("Support for the type '" + type) + " is incomplete!");
}
};
public method .grasp_for_remote_command() {
arg str, cmd, args;
var reg, obj, cdef, match, matched, info;
reg = args.match_regexp("[$#][a-z_0-9][a-z_0-9]*");
if (!reg)
return 0;
obj = (| $object_lib.to_dbref(args.subrange(@reg[1])) |);
if (!obj)
return 0;
info = (| obj.get_command_info('remote, cmd) |);
if (!info)
return 0;
matched = [];
for cdef in (info) {
match = args.match_template(cdef[2]);
if (match != 0)
matched += [[match.length(), obj, [str, cmd, @match], @cdef.subrange(3)]];
}
if (matched) {
matched = matched.sort(matched.slice(1));
return ['remote, matched];
}
return ['partial, [[str, cmd], info.slice(3)]];
};
public method .handle_error() {
arg traceback;
return (traceback[1])[2];
};
public method .local() {
arg user, @matches;
var parsed, match;
parsed = [];
for match in (matches) {
match = ._local(user, @match);
if ((match[1]) == 'command)
return match;
parsed = [match[2]] + parsed;
}
return ['error, parsed.compress()];
};
public method .parse() {
arg u, str, next_parser, @other_parsers;
var l, cmd, c, p, obj, exits;
cmd = str.explode();
if (cmd) {
cmd = [str, cmd[1], ((cmd.subrange(2)).join()) || ""];
p = [];
if ((c = (| u.match_in_shortcut_cache(@cmd) |))) {
if ((c[1]) == 'shortcut)
return .shortcut(u, @c[2]);
p = c[2];
}
if ((c = (| u.match_in_local_cache(@cmd) |))) {
if ((c[1]) == 'local)
return .local(u, @c[2]);
p += c[2];
}
if ((c = (| u.match_in_remote_cache(@cmd) |))) {
if ((c[1]) == 'remote)
return .remote(u, @c[2]);
p += c[2];
}
l = u.location();
if ((c = (| l.match_in_local_cache(@cmd) |))) {
if ((c[1]) == 'local)
return .local(l, @c[2]);
p += c[2];
}
if ((c = (| l.match_in_remote_cache(@cmd) |))) {
if ((c[1]) == 'remote)
return .remote(u, @c[2]);
p += c[2];
}
if ((c = (| .grasp_for_remote_command(@cmd) |))) {
if ((c[1]) == 'remote)
return .remote(u, @c[2]);
p += c[2];
}
if ((exits = (| (u.location()).exits() |) || [])) {
catch any {
obj = exits.match_object(str);
return ['command, obj, 'invoke];
} with {
if (error() == ~ambig) {
exits = (traceback()[1])[3];
return ['error, ((("\"" + str) + "\" can match ") + ((exits.mmap('namef, 'ref)).to_english("", " or "))) + "."];
}
}
}
if (p)
return .partial(u, cmd, p);
}
return next_parser.parse(u, str, @other_parsers);
};
public method .partial() {
arg user, args, templates;
var part, line;
for part in (templates)
templates = templates.replace(part in templates, toliteral(part));
if ((templates.length()) == 1)
line = toliteral(args[2]) + " could match ";
else if ((templates.length()) == 2)
line = toliteral(args[2]) + " could match either ";
else
line = toliteral(args[2]) + " could match any of ";
return ['error, (line + (templates.to_english("", " or "))) + "."];
};
public method .remote() {
arg user, @matches;
var parsed, match;
parsed = [];
for match in (matches) {
match = ._remote(user, @match);
if ((match[1]) == 'command)
return match;
parsed = [match[2]] + parsed;
}
return ['error, parsed.compress()];
};
public method .shortcut() {
arg user, method, parsed;
return ['command, user, method, @parsed];
};