Subject: What I'd like to see in the next version

From: [email-masked] (Joseph Behrmann)
Date: Wed, 13 Oct 1993 08:08:11 -0700

One useful thing that I'd like to see in the next version is either
a server command to call the server parser and calling procedures or have
all parsing be done in the db.

	So:  server_parse(<object>, <string>);

	would call the in server parser with <string> as if <object> had
typed it.  Exactly as if <object> had typed it.

	Also, another useful additoin might to have the in server's parser
check recursively on the calling object's location to match for verbs, instead
of just the current location and no further.  So if an object is inside of
another object, inside of a room, then the object types in a verb, the server
checks to match on the object its in and the room that the object is in.

						Joe
						[email-masked]

---

From: Pavel Curtis <[email-masked]>
Date: Wed, 13 Oct 1993 10:19:33 -0700

> Date:	Wed, 13 Oct 1993 08:08:11 -0700
> From:	[email-masked] (Joseph Behrmann)
> 

There's no pressing need for a way to allow MOO code to invoke the built-in
parser, since what it does can already be implemented in MOO code, and has been
at least once on LambdaMOO.  In fact, I seem to recall that there's a verb to
do this included in LambdaCore, but I don't remember where.

Given the change to the semantics of the `x' bit that I've already described as
coming in 1.8.0, there isn't even much use for a way to get the server to
invoke commands for you.

What would still be useful, though, is some way to override the server's
invocation of the built-in parser, to allow either full or partial in-DB
parsing.  I am still thinking about what a good design for this might look
like.  The chief issues are achieving sufficiently high performance and keeping
easy things at least as easy as they are now.  Of course, there's also always
the issue of backwards compatibility, too... :-)

	Pavel

---

From: Greg Hudson <[email-masked]>
Date: Wed, 13 Oct 1993 12:05:48 -0700

> I am still thinking about what a good design for [in-db parsing]
> might look like.

For what it's worth, here's what I've gone with in Coldmud:

Each connection has a handler object (analagous to the player object
in MOO).  When a line of text arrives from the client, the server
sends a `parse' message to the handler object, with a single argument,
the string to parse.

Two primitives help with parsing, match_template() and
match_pattern().  match_template() matches strings against patterns
like the following:

	@desc?ribe * as *
	turn * to channel|station *

match_pattern() matching strings against simple wildcard patterns
containing asterixes.  It's useful for commands like `"*' or `:*',
which don't fit into the template model.

That's all the server does for you, and it can't get much fancier than
that without imposing ideas of topology, naming, etc., on the
database.

The Cold World database divides parsing up into three stages:
commands, verbs, and exit names.  Commands are arbitrary templates or
patterns stored on the player object, the room object, or their
ancestors.  Matching against them is reasonably cheap, since you're
only dealing with two objects and a limited number of ancestors.

Verbs are templates containing the word `%this' exactly once, and not
at the beginning.  For instance, `@desc?ribe %this as *' is a valid
verb template.  To match against a verb template, you simply
substitute "*" for "%this" in the verb template and use
match_template().  If the match succeeds, assume that this is the verb
the player wanted to match, check the text matching the "%this"
against the objects in the player's environment, and go from there.

Matching against verbs is expensive; I could be in a room with a
thousand other objects, for instance, and the straightforward approach
would result in a thousand calls of say, `match_template("@desc?ribe
%this as *", str)' when one would do.  To speed things up, i keep a
cache of possible verb templates on player objects corresponding to
connected players, which gets invalidated at the obvious times (when
an object adds or removes a verb definition in the current room, when
an object anywhere with children adds or removes a verb definition,
when an object moves in or out of the player's room, when the player
moves).  When it's necessary to build the cache, I union together the
ancestors of all the objects in the player's environment, and then
union together the verb templates on that list of objects.

The Cold World database also keeps a global list of remotely-
accessible verbs, on the system object, thus allowing for global
verbs.

My parser is somewhat more ambitious than MOO's, and the costs
associated with it may make it untenable for a server as active as
LambdaMOO.  On the other hand, in some cases, it may be faster--if
there are a thousand described objects in the room with my player
object, I still wind up matching against "@desc?ribe * as *" only
once, and only ask for the verb templates on Generic Described Object
once when I build the verb template cache.

It's also a rather complex system, and takes advantage of
non-overridable methods and private data to ensure consistency.  Since
MOO doesn't have private data (that is, all ancestors of an object use
the same variable namespace when referring to variables) and doesn't
have non-overridable verbs, such an elaborate system may be difficult
to use within the database.

I suppose I should give a vaporware software update for those who
haven't heard of Coldmud: Coldmud is an object-oriented server with a
somewhat different approach than that of MOO.  Version 0.5.1 of
Coldmud and version 0.2.1 of the Cold World core database are
available on ftp.ccs.neu.edu in pub/mud/incoming.  A few features and
a lot of testing are still between me and a 1.0 release, which should
hopefully be usable in production.  To join the coldmud discussion
list, send mail to [email-masked].  Coldmud documentation
is available on the web at
"http://www.mit.edu:8001/afs/sipb/project/coldmud/html/Top.html".

--GBH

---

From: David Engberg <[email-masked]>
Date: Wed, 13 Oct 1993 13:12:39 -0700

> > I am still thinking about what a good design for [in-db parsing]

my first version of parsing looked similar (well, uglier syntax, same effect)

> 	turn * to channel|station *

this works very well for actually determining which verb/method is to be
invoked, although it doesn't provide a 'near-miss' default to allow you to
return something more helpful than "I don't understand that" ... that's a
problem i still can't resolve.
adding a second command "@desc?ribe *" to catch illformed input totally
destroys everything you've gained from a full line match.... *sigh*

anyway...
the biggest problem my users had with this matching that all of the information
that the parser uses to cut up the input line is lost after matching:
extracting the arguments becomes a manual chore left to the users, where
in Moo/Cool (with their imposed syntax structure) the arguments are handed
to the method neatly sliced.

so i tried to provide a mechanism whereby in matching the input line to the
command, you'd be creating the list of appropriate arguments ...
a way to say:  match "whisper X to Y" and get a divided list of
  {"whisper" "X" "to" "Y"}
if the match is found

to do this, a command is structured as a sentece of tokens, such that each
token will match part of the input string and separate its match from the
rest of the input line.  the simplest token would be a string.  more complex
symbols would be provided by the system to match certain regular expressions:
  {"push" "button" NUMBER}
would match the input line  "push button 1234"  and tell you that the list
for that is  {"push" "button" "1234")

to expand the power, two in-depth functional tokens will allow you to
match alternative strings, or match all of the material BEFORE a string:
  {"@desc" (or "ribe" " ") (before " as ") "as" REST}
would match:
  "@desc me as big and ugly"   -->  {"@desc" " " "me" "as" "big and ugly"}
  "@describe me as silly"      -->  {"@desc" "ribe" "me" "as" "silly"}

that way, the object argument is always the third element of the list, the
other argument is always the fifth.

this provides much more versatility than Moo:
  {"@set" WORD " on " (before " to ") "to" REST}
will match:
  "@set pi on comfy chair to 3.1415"
      -->   {"@set" "pi" "on" "comfy chair" "to" "3.1415"}

  {"whisper" (or (before " to ") (before "=")) (or "to" "=") REST}
will match:
  "whisper something important to trauma"
      -->   {"whisper" "something important" "to" "trauma"}
  "whisper trauma=something important"
      -->   {"whisper" "trauma" "=" "something important"}
[by checking the third argument, you can easily support both Tiny- and ghond-
 style syntax.]

ah, well... just a long 2cents to support Greg in saying that _general_
parsing is possible in the DB to avoid hard-coded server syntaxes.

-dave