new object $parse_lib: $libraries; var $parse_lib boolean_strs = [["yes", "true", "1", "on"], ["no", "false", "0", "off"]]; var $parse_lib ordinal = ["first", "second", "third", "fourth", "fifth", "sixth", "seventh", "eight", "ninth", "tenth"]; var $root created_on = 796268969; var $root flags = ['methods, 'code, 'variables, 'core]; var $root inited = 1; var $root managed = [$parse_lib]; var $root manager = $parse_lib; public method ._html_traceback() { arg type, what, @more; var line; switch (type) { case 'function: return ("function <tt>" + what) + "()</tt>"; case 'opcode: return ("operator <tt>" + what) + "</tt>"; default: line = (((((((((("method <tt><a href=\"/bin/display?target=" + (more[2])) + "\">") + (more[2])) + "</a>.<a href=\"/bin/method?target=") + (more[2])) + ".") + tostr(what)) + "&linenumbers=yes\">") + tostr(what)) + "</a>") + "()</tt>"; if ((more[1]) != (more[2])) line += (((" (<a href=\"/bin/display?target=" + (more[1])) + "\">") + (more[1])) + "</a>)"; line = (line + " line ") + (more[3]); return line; } }; public method ._range() { arg str; if (str.is_numeric()) { return toint(str); } else { switch (str[1]) { case "$": return 'end; case ".": return 'current; case "^": return 'start; default: throw(~range, "Invalid range reference."); } } }; public method ._traceback() { arg what, @more; var line; if (more) { if ((more[1]) == (more[2])) return ((((more[1]) + ".") + what) + "() line ") + (more[3]); else return ((((((more[2]) + ".") + what) + "() (") + (more[1])) + ") line ") + (more[3]); } else { return what; } }; public method .ask() { arg question, @rx; var ans, def; [(rx ?= "(yes|y)"), (def ?= "")] = rx; ans = (sender().prompt(question)).trim(); ans ?= def; if (ans == "@abort") throw(~stop, "** Aborted **"); return match_regexp(ans, rx); }; public method .buildref() { arg type, obj, def, name, @ignore; var line; line = tostr(obj); if (obj != def) line += ("<" + def) + ">"; if (type == 'object) return line; if (type == 'method) return ((line + ".") + tostr(name)) + "()"; if (type == 'variable) return (line + ",") + tostr(name); }; public method .filter_ctext() { arg what, @defaults; var dic, output, prop, eff, ctext; dic = ([@defaults, #[]][1]).union(#[['receiver, sender()], ['time, 'post], ['formatter, $plain_format]]); switch (class(what)) { case $ctext_frob: output = (what.set_vars(dic)).format(); case $message_frob: output = what.format(dic); case $filtered_frob: if ((prop = (| sender().default_propagator() |))) what = what.propagate(prop); if (!what) { output = `[]; } else { ctext = (what.message()).to_ctext(dic); for eff in (what.effects()) { if (type(eff) == 'string) ctext = ($ctext_frob.new_with([eff + " "], ctext.vars())).append(ctext); else ctext = $propagator_effects.(eff[1])(ctext, dic, eff.subrange(2)); } ctext = ctext.set_vars(what.sensory()); output = ctext.format(); } default: output = what; } return output; }; public method .getopt() { arg line, @defaults; var out, newlist, part, v, opt, t, keys, key, x; // submit: [["template", value], [...]]; // => if value is 1, it will take the next part of the string // receive: [["template", "flag", bool, value]], [...]]; line = line.explode_quoted(); out = []; newlist = []; [(defaults ?= [])] = defaults; while (line) { [x, @line] = line; if (x && ((x[1]) in ["-", "+"])) { opt = 0; v = ""; part = x.subrange(2); if ("=" in part) { part = part.explode("=", 1); [part, v] = part; } for t in (defaults) { if (part.match_template(t[1])) { opt = [t[1], part, (x[1]) == "+"]; if ((| t[2] |) && ((!v) && line)) { [v, @line] = line; if (v == "=") [(v ?= ""), @line] = line; } opt += [v]; } } if (!opt) opt = [0, part, (x[1]) == "+", ""]; out += [opt]; } else { newlist += [x]; } } return [newlist, out]; }; public method .html_traceback() { arg t, status; var line, out, x; out = ("<h2>" + (((t[1])[2]).to_html())) + "</h2>"; out += ("<i><b>Thrown by " + (._html_traceback(@t[2]))) + "</b></i><p>"; for x in [3 .. listlen(t)] out += ((("<code><i>" + ((t[x])[1])) + "</i>: ") + (._html_traceback(@t[x]))) + "</code><br>"; return $http.response(status, out + "</p>"); }; public method .object_match() { arg name, @who; var msg; // .object_match("name"[, who]) // -> 0 name was the empty string // -> ~objnf nothing matched name // -> ~ambig more than one object matched name // Attempt to match an object name with who.match_environment(). If one // is found, return it. Else, print a message and return one of the above // false values. // 'who' defaults to sender(). who = who ? (who[1]) : sender(); if (!name) { (| who.tell("You must give the name of something.") |); return 0; } catch ~objnf, ~ambig { return who.match_environment(name); } with { switch (error()) { case ~objnf: msg = ("I don't see any \"" + name) + "\" here."; case ~ambig: msg = ("I don't know which \"" + name) + "\" you mean."; } (| who.tell(msg) |); return error(); } }; public method .opt() { arg line, @defs; var out, a, l, x, m, args, opts, o, i, v; // submit: ["template", "template"..] // => if value is 1, it will take the next part of the string // receive: [["template", "flag", bool, value]], [...]]; opts = (args = []); line = line.explode_quoted(); l = listlen(line); x = 1; while (x <= l) { a = line[x]; if ((m = regexp(a, "^[+-]"))) { o = (m[1]) == "+"; v = ""; a = substr(a, 2); if ((i = "=" in a)) { if (i == strlen(a)) { v = line[++x]; a = substr(a, 1, strlen(a) - 1).trim(); } else { [a, v] = explode(a, "=", 1); } } if ((i = find m in (defs) where (match_template(a, m)))) opts += [[defs[i], a, o, v]]; else opts += [[0, a, o, v]]; } else { args += [a]; } x++; } return [args, opts]; }; public method .ordinal() { return ordinal; }; public method .ordinal_reference() { arg str; var rx, num; if (!(rx = regexp(str, "^ *(first|second|third|fourth|fifth|sixth|seventh|eighth|ninth|tenth|1st|2nd|3rd|[456789]th|10th) *(.*)$"))) return 0; num = toint(rx[1]) || ((rx[1]) in ordinal); return [rx[2], num]; // Original code from LamdaMOO, Author Unknown }; public method .parse_method_access() { arg str; var t; for t in (["pub?lic", "pro?tected", "pri?vate", "r?oot", "dr?iver", "f?rob"]) { if (match_template(str, t)) return tosym(t.strip("?")); } return 'public; }; public method .parse_method_flags() { arg flags; var t, out, flag; out = []; for flag in (flags.explode(",")) { for t in (["no?override", "l?ocked", "f?orked", "na?tive"]) { if (match_template(flag, t)) out += [tosym(t.strip("?"))]; } } return out; }; public method .possessive_reference() { arg str; var rx; if ((rx = regexp(str, "^my$|^my +(.+)?"))) return ["me", (| rx[1] |) || ""]; else if ((rx = regexp(str, "^([^ ]+s'|[^ ]+'s) *(.+)?"))) return [substr(rx[1], 1, strlen(rx[1]) - 2), rx[2]]; return 0; }; public method .range() { arg str; var out; out = split(str, " *- *"); if ((out.length()) == 1) { if ("," in str) return ['specific, str]; out = [(> ._range(str) <), 'single]; } else if ((out.length()) == 2) { out = out.replace(1, (> ._range(out[1]) <)); out = out.replace(2, (> ._range(out[2]) <)); } else { throw(~range, "Invalid range reference."); } return out; }; public method .ref() { arg str, @args; var def, me, obj, reg, member, match, type, second; [(me ?= sender())] = args; if ((args.length()) > 1) match = args[2]; else match = [me, 'match_environment, []]; if (str == ".") { // shortcut obj = (> (match[1]).(match[2])("", @match[3]) <); return ['object, obj, obj, 0, 0]; } if ((reg = regexp(str, "^(.*)<([^>]*)>(.*)$"))) { def = (> (match[1]).(match[2])(reg[2], @match[3]) <); str = (reg[1]) + (reg[3]); } if ((reg = regexp(str, "([^\.,]*)([\.,]+)([^\( ]*)"))) { obj = reg[1]; member = reg[3]; type = reg[2]; if (((type.length()) > 1) && (((type[1]) == ".") && (!obj))) { type = type.subrange(2); obj = (> (match[1]).(match[2])("", @match[3]) <); } else { obj = obj ? (> (match[1]).(match[2])(obj, @match[3]) <) : me; } if ("." in type) { if ("," in type) second = 'variable; type = 'method; } else { type = 'variable; } } else { obj = (> (match[1]).(match[2])(str, @match[3]) <); type = 'object; } return [type, obj, def || obj, member, second]; }; public method .traceback() { arg traceback, @args; var line, out, pre, lines, cur, x, error; // $parse_lib.traceback(traceback(), lines, pre); // -1 lines represents the full error // pre is set to "! " unless otherwise specified. [(lines ?= -1), (pre ?= "! "), (error ?= 0)] = args; // The initial string out = [(pre + "=> ") + ((traceback[1])[2])]; pre += " "; // The primary error if (error == 0) out += [(pre + "Thrown by ") + (._traceback(@(traceback[2]).subrange(2)))]; else out += [(((pre + "Error ") + error) + " caused by ") + (._traceback(@(traceback[2]).subrange(2)))]; // The rest of it for x in [1 .. (traceback.length()) - 2] { if ((x <= lines) || (lines == (-1))) { line = ((traceback[x + 2])[1]) + ": "; line += ._traceback(@(traceback[x + 2]).subrange(2)); out += [pre + line]; } } return out; };