/
html/
<HTML>
<HEAD>
<!-- This HTML file has been created by texi2html 1.51
     from ProgrammersManual.texinfo on 4 March 1997 -->

<TITLE>LambdaMOO Programmer's Manual - Parsing</TITLE>
</HEAD>
<BODY>
Go to the <A HREF="ProgrammersManual_1.html">first</A>, <A HREF="ProgrammersManual_7.html">previous</A>, <A HREF="ProgrammersManual_9.html">next</A>, <A HREF="ProgrammersManual_77.html">last</A> section, <A HREF="ProgrammersManual_toc.html">table of contents</A>.
<P><HR><P>


<H1><A NAME="SEC8" HREF="ProgrammersManual_toc.html#TOC8">The Built-in Command Parser</A></H1>

<P>
The MOO server is able to do a small amount of parsing on the commands
that a player enters.  In particular, it can break apart commands that
follow one of the following forms:

</P>

<PRE>
<VAR>verb</VAR>
<VAR>verb</VAR> <VAR>direct-object</VAR>
<VAR>verb</VAR> <VAR>direct-object</VAR> <VAR>preposition</VAR> <VAR>indirect-object</VAR>
</PRE>

<P>
Real examples of these forms, meaningful in the LambdaCore database, are
as follows:

</P>

<PRE>
look
take yellow bird
put yellow bird in cuckoo clock
</PRE>

<P>
Note that English articles (i.e., <SAMP>`the'</SAMP>, <SAMP>`a'</SAMP>, and <SAMP>`an'</SAMP>) are not
generally used in MOO commands; the parser does not know that they are
not important parts of objects' names.

</P>
<P>
To have any of this make real sense, it is important to understand
precisely how the server decides what to do when a player types a
command.

</P>
<P>
First, the server checks whether or not the first non-blank character in the
command is one of the following:

</P>

<PRE>
"        :        ;
</PRE>

<P>
If so, that character is replaced by the corresponding command below, followed
by a space:

</P>

<PRE>
say      emote    eval
</PRE>

<P>
For example, the command

</P>

<PRE>
"Hi, there.
</PRE>

<P>
is treated exactly as if it were as follows:

</P>

<PRE>
say Hi, there.
</PRE>

<P>
The server next breaks up the command into words.  In the simplest case,
the command is broken into words at every run of space characters; for example,
the command <SAMP>`foo bar baz'</SAMP> would be broken into the words <SAMP>`foo'</SAMP>,
<SAMP>`bar'</SAMP>, and <SAMP>`baz'</SAMP>.  To force the server to include spaces in a
"word", all or part of a word can be enclosed in double-quotes.  For example,
the command

</P>

<PRE>
foo "bar mumble" baz" "fr"otz" bl"o"rt
</PRE>

<P>
is broken into the words <SAMP>`foo'</SAMP>, <SAMP>`bar mumble'</SAMP>, <SAMP>`baz frotz'</SAMP>, and
<SAMP>`blort'</SAMP>.  Finally, to include a double-quote or a backslash in a word,
they can be preceded by a backslash, just like in MOO strings.

</P>
<P>
Having thus broken the string into words, the server next checks to see if the
first word names any of the six "built-in" commands: <SAMP>`.program'</SAMP>,
<SAMP>`PREFIX'</SAMP>, <SAMP>`OUTPUTPREFIX'</SAMP>, <SAMP>`SUFFIX'</SAMP>, <SAMP>`OUTPUTSUFFIX'</SAMP>, or the
connection's defined <STRONG>flush</STRONG> command, if any (<SAMP>`.flush'</SAMP> by default).
The first one of these is only available to programmers, the next four are
intended for use by client programs, and the last can vary from database to
database or even connection to connection; all six are described in the final
chapter of this document, "Server Commands and Database Assumptions".  If the
first word isn't one of the above, then we get to the usual case: a normal MOO
command.

</P>
<P>
The server next gives code in the database a chance to handle the command.  If
the verb <CODE>$do_command()</CODE> exists, it is called with the words of the
command passed as its arguments and <CODE>argstr</CODE> set to the raw command typed
by the user.  If <CODE>$do_command()</CODE> does not exist, or if that verb-call
completes normally (i.e., without suspending or aborting) and returns a false
value, then the built-in command parser is invoked to handle the command as
described below.  Otherwise, it is assumed that the database code handled the
command completely and no further action is taken by the server for that
command.

</P>
<P>
If the built-in command parser is invoked, the server tries to parse the
command into a verb, direct object, preposition and indirect object.  The first
word is taken to be the verb.  The server then tries to find one of the
prepositional phrases listed at the end of the previous section, using the
match that occurs earliest in the command.  For example, in the very odd
command <SAMP>`foo as bar to baz'</SAMP>, the server would take <SAMP>`as'</SAMP> as the
preposition, not <SAMP>`to'</SAMP>.

</P>
<P>
If the server succeeds in finding a preposition, it considers the words
between the verb and the preposition to be the direct object and those
after the preposition to be the indirect object.  In both cases, the
sequence of words is turned into a string by putting one space between
each pair of words.  Thus, in the odd command from the previous
paragraph, there are no words in the direct object (i.e., it is
considered to be the empty string, <CODE>""</CODE>) and the indirect object is
<CODE>"bar to baz"</CODE>.

</P>
<P>
If there was no preposition, then the direct object is taken to be all
of the words after the verb and the indirect object is the empty string.

</P>
<P>
The next step is to try to find MOO objects that are named by the direct
and indirect object strings.

</P>
<P>
First, if an object string is empty, then the corresponding object is the
special object <CODE>#-1</CODE> (aka <CODE>$nothing</CODE> in LambdaCore).  If an object
string has the form of an object number (i.e., a hash mark (<SAMP>`#'</SAMP>) followed
by digits), and the object with that number exists, then that is the named
object.  If the object string is either <CODE>"me"</CODE> or <CODE>"here"</CODE>, then the
player object itself or its location is used, respectively.

</P>
<P>
Otherwise, the server considers all of the objects whose location is either
the player (i.e., the objects the player is "holding", so to speak) or the
room the player is in (i.e., the objects in the same room as the player); it
will try to match the object string against the various names for these
objects.

</P>
<P>
The matching done by the server uses the <SAMP>`aliases'</SAMP> property of each of the
objects it considers.  The value of this property should be a list of strings,
the various alternatives for naming the object.  If it is not a list, or the
object does not have an <SAMP>`aliases'</SAMP> property, then the empty list is used.
In any case, the value of the <SAMP>`name'</SAMP> property is added to the list for the
purposes of matching.

</P>
<P>
The server checks to see if the object string in the command is either exactly
equal to or a prefix of any alias; if there are any exact matches, the prefix
matches are ignored.  If exactly one of the objects being considered has a
matching alias, that object is used.  If more than one has a match, then the
special object <CODE>#-2</CODE> (aka <CODE>$ambiguous_match</CODE> in LambdaCore) is used.
If there are no matches, then the special object <CODE>#-3</CODE> (aka
<CODE>$failed_match</CODE> in LambdaCore) is used.

</P>
<P>
So, now the server has identified a verb string, a preposition string,
and direct- and indirect-object strings and objects.  It then looks at
each of the verbs defined on each of the following four objects, in
order:

</P>

<OL>
<LI>

the player who typed the command,
<LI>

the room the player is in,
<LI>

the direct object, if any, and
<LI>

the indirect object, if any.
</OL>

<P>
For each of these verbs in turn, it tests if all of the the following
are true:

</P>

<UL>
<LI>

the verb string in the command matches one of the names for the
verb,
<LI>

the direct- and indirect-object values found by matching are allowed by
the corresponding argument specifiers for the verb, and
<LI>

the preposition string in the command is matched by the preposition
specifier for the verb.
</UL>

<P>
I'll explain each of these criteria in turn.

</P>
<P>
Every verb has one or more names; all of the names are kept in a single
string, separated by spaces.  In the simplest case, a verb-name is just
a word made up of any characters other than spaces and stars (i.e., ` '
and <SAMP>`*'</SAMP>).  In this case, the verb-name matches only itself; that
is, the name must be matched exactly.

</P>
<P>
If the name contains a single star, however, then the name matches any prefix
of itself that is at least as long as the part before the star.  For example,
the verb-name <SAMP>`foo*bar'</SAMP> matches any of the strings <SAMP>`foo'</SAMP>,
<SAMP>`foob'</SAMP>, <SAMP>`fooba'</SAMP>, or <SAMP>`foobar'</SAMP>; note that the star itself is not
considered part of the name.

</P>
<P>
If the verb name <EM>ends</EM> in a star, then it matches any string that begins
with the part before the star.  For example, the verb-name <SAMP>`foo*'</SAMP> matches
any of the strings <SAMP>`foo'</SAMP>, <SAMP>`foobar'</SAMP>, <SAMP>`food'</SAMP>, or <SAMP>`foogleman'</SAMP>,
among many others.  As a special case, if the verb-name is <SAMP>`*'</SAMP> (i.e., a
single star all by itself), then it matches anything at all.

</P>
<P>
Recall that the argument specifiers for the direct and indirect objects are
drawn from the set <SAMP>`none'</SAMP>, <SAMP>`any'</SAMP>, and <SAMP>`this'</SAMP>.  If the specifier
is <SAMP>`none'</SAMP>, then the corresponding object value must be <CODE>#-1</CODE> (aka
<CODE>$nothing</CODE> in LambdaCore); that is, it must not have been specified.  If
the specifier is <SAMP>`any'</SAMP>, then the corresponding object value may be
anything at all.  Finally, if the specifier is <SAMP>`this'</SAMP>, then the
corresponding object value must be the same as the object on which we found
this verb; for example, if we are considering verbs on the player, then the
object value must be the player object.

</P>
<P>
Finally, recall that the argument specifier for the preposition is
either <SAMP>`none'</SAMP>, <SAMP>`any'</SAMP>, or one of several sets of prepositional
phrases, given above.  A specifier of <SAMP>`none'</SAMP> matches only if there
was no preposition found in the command.  A specifier of <SAMP>`any'</SAMP>
always matches, regardless of what preposition was found, if any.  If
the specifier is a set of prepositional phrases, then the one found must
be in that set for the specifier to match.

</P>
<P>
So, the server considers several objects in turn, checking each of their
verbs in turn, looking for the first one that meets all of the criteria
just explained.  If it finds one, then that is the verb whose program
will be executed for this command.  If not, then it looks for a verb
named <SAMP>`huh'</SAMP> on the room that the player is in; if one is found,
then that verb will be called.  This feature is useful for implementing
room-specific command parsing or error recovery.  If the server can't
even find a <SAMP>`huh'</SAMP> verb to run, it prints an error message like
<SAMP>`I couldn't understand that.'</SAMP> and the command is considered complete.

</P>
<P>
At long last, we have a program to run in response to the command typed by the
player.  When the code for the program begins execution, the following
built-in variables will have the indicated values:

</P>

<PRE>
player    an object, the player who typed the command
this      an object, the object on which this verb was found
caller    an object, the same as <SAMP>`player'</SAMP>
verb      a string, the first word of the command
argstr    a string, everything after the first word of the command
args      a list of strings, the words in <SAMP>`argstr'</SAMP>
dobjstr   a string, the direct object string found during parsing
dobj      an object, the direct object value found during matching
prepstr   a string, the prepositional phrase found during parsing
iobjstr   a string, the indirect object string
iobj      an object, the indirect object value
</PRE>

<P>
The value returned by the program, if any, is ignored by the server.

</P>
<P><HR><P>
Go to the <A HREF="ProgrammersManual_1.html">first</A>, <A HREF="ProgrammersManual_7.html">previous</A>, <A HREF="ProgrammersManual_9.html">next</A>, <A HREF="ProgrammersManual_77.html">last</A> section, <A HREF="ProgrammersManual_toc.html">table of contents</A>.
</BODY>
</HTML>