new object $lock_parser: $misc;
var $lock_parser lock_types = [["inside", $inside_lock_frob], ["indirect", $indirect_lock_frob], ["owner", $owner_lock_frob], ["carry", $carry_lock_frob], ["parent", $parent_lock_frob]];
var $root created_on = 796268969;
var $root flags = ['methods, 'code, 'core, 'variables];
var $root inited = 1;
var $root managed = [$lock_parser];
var $root manager = $lock_parser;
public method .parse() {
arg s, env;
var stack, lock, n, m, obj, type, i;
stack = [];
s = " " + s;
s = strsed(s, "&([^&])", "&&%1", "g");
s = strsed(s, "\|([^\|])", "||%1", "g");
s = strsub(s, " or ", " || ");
s = strsub(s, " and ", " && ");
s = strsub(s, " not ", " !");
while (1) {
// Look for valid prefixes.
while (1) {
(s = s.trim()) || throw(~parse, "String ends unexpectedly.");
if ((s[1]) == "(") {
stack = ['open, @stack];
s = s.subrange(2);
} else if ((s[1]) == "!") {
if (stack && ((stack[1]) == 'not))
stack = stack.subrange(2);
else
stack = ['not, @stack];
s = s.subrange(2);
} else {
break;
}
}
// Look for an object name or tag
m = regexp(s, "^([^)&|]+)(.*)");
if (!m)
throw(~parse, "Null object obj_name.");
s = m[2];
lock = (m[1]).trim();
if (!lock)
throw(~parse, "Null object obj_name.");
// try and match it
type = $object_lock_frob;
for i in (lock_types) {
if (lock.match_begin((i[1]) + ":")) {
type = i[2];
lock = lock.subrange(((i[1]).length()) + 2);
break;
}
}
if ((obj = (| env.match_environment(lock) |))) {
lock = type.new_lock(obj);
} else {
switch (lock) {
case "any", "true", "anybody", "yes":
lock = $true_lock_frob.new();
case "none", "false", "nobody", "no":
lock = $false_lock_frob.new();
default:
throw(~parse, ("Invalid lock tag \"" + lock) + "\"");
}
}
stack = [lock, @stack];
// Loop until no more reduction to be done.
while (1) {
// Process negations, ands, ors.
while (1) {
if ((stack.length()) < 2)
break;
if ((stack[2]) == 'not)
stack = [$not_lock_frob.new_lock(stack[1]), @stack.subrange(3)];
else if ((stack[2]) == 'and)
stack = [$and_lock_frob.new_lock(stack[1], stack[3]), @stack.subrange(4)];
else if ((stack[2]) == 'or)
stack = [$or_lock_frob.new_lock(stack[1], stack[3]), @stack.subrange(4)];
else
break;
}
// Close parens, if necessary; otherwise stop.
if ((!s) || ((s[1]) != ")"))
break;
while (s && ((s[1]) == ")")) {
if (((stack.length()) < 2) || ((stack[2]) != 'open))
throw(~parse, "Misplaced right parenthesis.");
stack = [stack[1], @stack.subrange(3)];
s = (s.subrange(2)).trim();
}
}
// Are we done?
if (!s) {
if ((stack.length()) > 1)
throw(~parse, "Unmatched left parentheses.");
return stack[1];
}
// No, we're at a conjunction.
if ((s[1]) == "&") {
stack = ['and, @stack];
s = s.subrange(3);
} else if ((s[1]) == "|") {
stack = ['or, @stack];
s = s.subrange(3);
} else {
throw(~parse, "Illegal character following right parenthesis.");
}
}
};