[Turn on line numbering]arg s, who; 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 ", " !"); s = strsub(s, " xor ", " ^^"); 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, default to object type 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; } } switch (lock) { case "any", "true", "anybody", "yes": lock = $true_lock_frob.new(); case "none", "false", "nobody", "no": lock = $false_lock_frob.new(); default: if ((obj = (| type.parse_value(lock, who) |))) lock = type.new_lock(obj); else 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."); } }
// Created 27-Mar-1995 as a part of ColdCore, see: @help Credit