[Turn off line numbering]1: arg s, who; 2: var stack, lock, n, m, obj, type, i; 3: 4: stack = []; 5: s = " " + s; 6: s = strsed(s, "&([^&])", "&&%1", "g"); 7: s = strsed(s, "\|([^\|])", "||%1", "g"); 8: s = strsub(s, " or ", " || "); 9: s = strsub(s, " and ", " && "); 10: s = strsub(s, " not ", " !"); 11: s = strsub(s, " xor ", " ^^"); 12: while (1) { 13: // Look for valid prefixes. 14: while (1) { 15: (s = s.trim()) || throw(~parse, "String ends unexpectedly."); 16: if (s[1] == "(") { 17: stack = ['open, @stack]; 18: s = s.subrange(2); 19: } else if (s[1] == "!") { 20: if (stack && stack[1] == 'not) 21: stack = stack.subrange(2); 22: else 23: stack = ['not, @stack]; 24: s = s.subrange(2); 25: } else { 26: break; 27: } 28: } 29: 30: // Look for an object name or tag 31: m = regexp(s, "^([^)&|]+)(.*)"); 32: if (!m) 33: throw(~parse, "Null object obj_name."); 34: s = m[2]; 35: lock = m[1].trim(); 36: if (!lock) 37: throw(~parse, "Null object obj_name."); 38: 39: // try and match it, default to object type 40: type = $object_lock_frob; 41: for i in (lock_types) { 42: if (lock.match_begin(i[1] + ":")) { 43: type = i[2]; 44: lock = lock.subrange(i[1].length() + 2); 45: break; 46: } 47: } 48: switch (lock) { 49: case "any", "true", "anybody", "yes": 50: lock = $true_lock_frob.new(); 51: case "none", "false", "nobody", "no": 52: lock = $false_lock_frob.new(); 53: default: 54: if ((obj = (| type.parse_value(lock, who) |))) 55: lock = type.new_lock(obj); 56: else 57: throw(~parse, "Invalid lock tag \"" + lock + "\""); 58: } 59: stack = [lock, @stack]; 60: 61: // Loop until no more reduction to be done. 62: while (1) { 63: // Process negations, ands, ors. 64: while (1) { 65: if (stack.length() < 2) 66: break; 67: if (stack[2] == 'not) 68: stack = [$not_lock_frob.new_lock(stack[1]), @stack.subrange(3)]; 69: else if (stack[2] == 'and) 70: stack = [$and_lock_frob.new_lock(stack[1], stack[3]), @stack.subrange(4)]; 71: else if (stack[2] == 'or) 72: stack = [$or_lock_frob.new_lock(stack[1], stack[3]), @stack.subrange(4)]; 73: else 74: break; 75: } 76: 77: // Close parens, if necessary; otherwise stop. 78: if (!s || s[1] != ")") 79: break; 80: while (s && s[1] == ")") { 81: if (stack.length() < 2 || stack[2] != 'open) 82: throw(~parse, "Misplaced right parenthesis."); 83: stack = [stack[1], @stack.subrange(3)]; 84: s = s.subrange(2).trim(); 85: } 86: } 87: 88: // Are we done? 89: if (!s) { 90: if (stack.length() > 1) 91: throw(~parse, "Unmatched left parentheses."); 92: return stack[1]; 93: } 94: 95: // No, we're at a conjunction. 96: if (s[1] == "&") { 97: stack = ['and, @stack]; 98: s = s.subrange(3); 99: } else if (s[1] == "|") { 100: stack = ['or, @stack]; 101: s = s.subrange(3); 102: } else { 103: throw(~parse, "Illegal character following right parenthesis."); 104: } 105: }
// Created 27-Mar-1995 as a part of ColdCore, see: @help Credit