Method code for $lock_frob.parse()

[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

Tlon