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."); } } };