This file is part of the TADS 2 Author’s Manual.
Copyright © 1987 - 2002 by Michael J. Roberts. All rights reserved.
Edited by NK Guy, tela design.


Chapter Seven


Parser Summary and Quick Reference

This section summarizes the entire sequence of function and method calls that the parser makes in the course of parsing and executing a command.

Reading a Command Line

The first thing the parser does at the start of each turn is read a new command line.

  commandPrompt(0);
  // the parser next reads a line of input from the keyboard
  commandAfterRead(0);

If commandPrompt() isn’t defined, the parser simply displays its default prompt, a blank line followed by a greater-than sign (“>”). If commandAfterRead() isn’t defined, the parser does nothing extra.

preparse

After reading the command line, the parser invokes preparse(), if defined.

  preparse(commandString);

Parsing

Next, the parser breaks the command into words, then divides the command into sentences if multiple sentences, separated with “then”, periods, semicolons, or other unambiguous sentence separators, are present. The parser then parses and executes each sentence individually.

The first step in parsing a sentence is checking for an actor. If the sentence starts with a noun phrase followed by a comma, the parser takes the noun phrase to refer to an actor.

After reading the noun phrase specifying the actor, the parser finds the other parts of the command: the verb and its associated preposition (for example, the parser considers the word “up” in “pick up” to be the verb preposition, because it’s effectively part of the verb); the direct object; the preposition introducing the indirect object (for example, the word “on” in “put box on shelf”); and the indirect object. Apart from the verb, all of these parts are optional.

Throughout this parsing phase, the parser invokes the game-defined parseNounPhrase(), if present, to allow the game to perform custom noun phrase parsing.

  parseNounPhrase(wordlist, typelist, currentIndex,
                  complainOnNoMatch, isActorCheck);

If the parser cannot identify a suitable verb, or if the sentence structure does not match a syntax pattern that the parser recognizes, the parser invokes the game-defined parseUnknownVerb() function, if defined.

  parseUnknownVerb(actor, wordlist, typelist, errnum);

Execution Sequence

Once the parser has finished parsing the command, the parser executes the command. On a command line with more than one command, the parser executes the first command before starting to parse the second.

To execute the command, the parser first invokes the preparseCmd() function, if defined by the game, passing a list of the strings making up the tokens of the command.

  preparseCmd(wordlist);

Next, the parser identifies the deepverb object for the command’s verb. Once the verb is identified, the parser invokes the roomCheck method in the current player character’s Actor object.

  parserGetMe().roomCheck(verb);

The parser now resolves and disambiguates any noun phrases in the command. (Note that the noun phrases were already parsed earlier, during the parsing phase; at this point, the parser resolves the words of the noun phrases to the game objects to which they refer.) To perform disambiguation, the parser invokes validDoList, validIoList, validDo, validIo, and the verification methods, verIoVerb (for an indirect object) and verDoVerb (for a direct object). If a noun phrase involving “all” was used, the parser will invoke the doDefault or ioDefault methods in the deepverb object to obtain the list of all available objects.

The parser will also invoke the methods disambigDobj and disambigIobj, as appropriate, on the deepverb object.

  verb.disambigDobj(actor, prep, iobj, verprop, wordlist, objlist, flaglist,
                    numberWanted, isAmbiguous, silent);

  verb.disambigIobj(actor, prep, dobj, verprop, wordlist, objlist, flaglist,
                    numberWanted, isAmbiguous, silent);

The parser next identifies the verb template (i.e., the verification and action methods for the verb).

If the verb has only templates for more objects than the player provided, the parser attempts to obtain the missing objects. (For example, the verb “take” requires a direct object; if the player types “take” without any object, the parser will try to obtain a direct object.) First, the parser tries using the default object mechanism, by calling the doDefault or ioDefault method in the deepverb object. If this fails to supply exactly one default object, the parser asks the player to provide the missing object.

Next, if the player’s command used multiple direct objects, or used a noun phrase involving “all” for the direct object, the parser will invoke the rejectMultiDobj method in the deepverb object.

  verb.rejectMultiDobj(preposition);

Starting Execution

The parser next invokes the preCommand function, if defined:

  preCommand(actor, verb, dobj_list, prep, iobj)

This function can simply return to proceed with the command, or it can use exit to skip to the fuses and daemons, or it can use abort to skip directly to endCommand, bypassing fuses and daemons.

Direct Object Loop

The parser now executes a series of method calls on the direct objects in the command. For a command with multiple direct objects, the parser executes all of the steps below on the first direct object, then executes all of the steps on the second direct object, and so on.

If the current direct object is not the first in the command, the parser at this point re-validates the current direct object and indirect object. This re-validation is not necessary for the first direct object in the command, because the object resolution phase already did this for all of the objects, and nothing in the game state has changed since then, hence that earlier validation is still applicable. However, the game state might change in the course of executing the command for the first direct object, so the parser must re-validate all subsequent objects. To re-validate, the parser calls the deepverb object’s validDo method for the direct object, and the validIo method for the indirect object. If validation fails, the parser displays an error (using the cantReach method if the object is visible, otherwise using parser error 38, “You don't see that here any more”) and aborts the command.

  verb.validDo(actor, directObject, 1)
  verb.validIo(actor, indirectObject, 1)

The parser now executes the methods calls below for the current direct and indirect object.

If one of the methods below executes an abort statement, the parser terminates execution of the command entirely. If one of the methods executes an exit statement, the parser skips directly to the postAction function, then to the end-of-turn phase, then proceeds to parse and execute any remaining command on the command line. If one of the methods invokes exitobj, the parser skips the remaining steps for the current direct object only, calls postAction, then proceeds to execute all of the steps below on the next direct object in the current command.

  verb.verbAction(actor, directObject, preposition, indirectObject);
  actor.actorAction(verb, directObject, preposition, indirectObject);
  actor.location.roomAction(actor, verb, directObject, preposition, indirectObject);

  if (indirectObject != nil)
  {
    indirectObject.iobjCheck(actor, verb, directObject, preposition);
    if (indirectObject does not directly define ioVerb or verIoVerb)
      indirectObject.iobjGen(actor, verb, directObject, preposition);
  }

  if (directObject != nil)
  {
    directObject.iobjCheck(actor, verb, indirectObject, preposition);
    if (directObject does not directly define doVerb or verDoVerb)
      directObject.iobjGen(actor, verb, indirectObject, preposition);
  }

  if (directObject != nil && indirectObject != nil)
  {
    // if directObject doesn't define or inherit verDoVerb,
    // or if indirectObject doesn't define or inherit verIoVerb,
    // display an error ("I don't know how to...") and stop now

    if (verb has flag [disambigDobjFirst])
      directObject.verDoVerb(actor);
    else
      directObject.verDoVerb(actor, indirectObject);

    // stop now if any output occurred in verDoVerb

    if (verb has flag [disambigDobjFirst])
      indirectObject.verIoVerb(actor, directObject);
    else
      indirectObject.verIoVerb(actor);

    // stop now if any output occurred in verIoVerb

    indirectObject.ioVerb(actor, directObject);
  }
  else if (directObject != nil)
  {
    // if directObject doesn't define or inherit verDoVerb,
    // display an error ("I don't know how to...") and stop now

    directObject.verDoVerb(actor);

    // stop now if any output occurred in verDoVerb

    directObject.doVerb(actor);
  }
  else
  {
    verb.action(actor);
  }

Regardless of how the above sequence finishes (by successfully execution of all methods, or by execution of exit, exitobj, or abort), the parser next invokes the game-defined function postAction:

  postAction(actor, verb, dobj, prep, iobj, status);

The “status” code indicates how the command was terminated:

EC_SUCCESS   Successful completion of all methods
EC_EXIT   exit executed
EC_EXITOBJ   exitobj executed
EC_ABORT   abort executed

Fuses and Daemons

If none of the methods that the parser invoked so far executed an abort statement, the parser executes all pending fuses and daemons. Each daemon is executed once, and each fuse whose timer has reached zero is executed and then deleted.

endCommand

Finally, the parser invokes the game-defined function endCommand():

    endCommand(actor, verb, dobj_list, prep, iobj, status);

The “status” parameter has the same meaning as it does in the parser’s call to postAction(). The other parameters have the same values they did in the call to preCommand() at the start of the command.

The parser invokes endCommand() for every command that enters the execution phase (in other words, for every command that does not end with an error prior to execution, such as in syntax analysis or noun-phrase resolution). The parser calls endCommand() even when the execution phase is terminated with exit, exitobj, or abort.


Summary of Properties, Methods, Objects, and Functions

As described throughout this manual, the parser calls certain methods that objects in your game can define, and calls certain functions that your game can provide. All of these methods and functions are described in detail elsewhere in the manual. This section summarizes these properties and function; for full information, refer to the appropriate section elsewhere in the manual.


Properties and Methods


action(actor)

Called in a deepverb object during command execution to execute a command with no objects.


actorAction(verb, dobj, prep, iobj)

Called in the actor object during command execution.


adesc

Used to display an object’s short description with an indefinite article.


adjective

Defines words as adjectives, and associates them with the object.


anyvalue(num)

The parser calls this method on an object with a generic numeric adjective (adjective = '#') when the player uses “any” in a noun phrase involving the object. This method returns a number to use for the arbitrary choice the parser must make.


article

Defines words as articles.


cantReach(actor)

Called in an object (only if cantReach isn’t defined in the verb) when the object is visible but not accessible; this method is meant to display an explanation of this condition.


cantReach(actor, dolist, iolist, prep)

Called in a verb when the list of objects (only one of dolist or iolist will be non-nil) is visible but not accessible; this method is meant to display an explanation.


construct

Called immediately after an object is created with the new operator. Minimally, this method should install the object into its container’s contents list.


contents

The list of an object’s contents.


destruct

Called immediately before an object is destroyed with the delete operator. Minimally, this method should remove the object from its container’s contents list, and should make sure that the object is not referenced from any other lists or properties.


disambigDobj(actor, prep, iobj, verprop, wordlist, objlist, flaglist, numberWanted, isAmbiguous, silent)

The parser calls this method in the deepverb object to resolve an ordinary noun phrase used as a direct object. The parser calls this method for every ordinary noun phrase used as a direct object, whether or not the noun phrase is actually ambiguous.


disambigIobj(actor, prep, dobj, verprop, wordlist, objlist, flaglist, numberWanted, isAmbiguous, silent)

The parser calls this method in the deepverb object to resolve an ordinary noun phrase used as an indirect object. The parser calls this method for every ordinary noun phrase used as an indirect object, whether or not the noun phrase is actually ambiguous.


doAction

Direct Object Action; associated with a deepverb object. Defines the verb template for a single-object command for a verb, and specifies the suffix for to be used for the action and verification methods for the verb (doSuffix and verDoSuffix, respectively).


dobjCheck(actor, verb, iobj, prep)

General direct object check, called during command execution before dobjGen would be called.


dobjGen(actor, verb, iobj, prep)

General direct object handler, called during command execution on the direct object prior to processing the verb’s verification and action methods. The parser does not call this method if the object “overrides” it by explicitly defining, rather than merely inheriting, a verification method (verDoVerb) or action method (doVerb) for the verb.


doDefault(actor, prep, iobj)

Direct Object Default. Associated with a deepverb object. Returns the list of default objects for the verb.


ioAction(prep)

Indirect Object Action; associated with a deepverb object. Defines the verb template for a two-object command for a verb with the given preposition, and specifies the suffix for to be used for the action and verification methods for the verb (io Suffix and verIoSuffix, respectively).


iobjCheck(actor, verb, iobj, prep)

General indirect object check, called during command execution just before iobjGen would be called.


iobjGen(actor, verb, dobj, prep)

General indirect object handler, called during command execution on the indirect object prior to processing the verb’s verification and action methods. The parser does not call this method if the object “overrides” it by explicitly defining, rather than merely inheriting, a verification method (verIoVerb) or action method (ioVerb) for the verb.


ioDefault(actor, prep)

Indirect Object Default; associated with a deepverb object. Returns the list of default objects for the verb.


isEquivalent

Used to determine if an object should be treated as equivalent to other objects of its immediate superclass. If this property is true, the parser treats all objects of the same immediate superclass as this object as interchangeable during disambiguation.


isHim

If true, the object can be the antecedant for the pronoun “him.” This also affects certain default messages that adv.t displays for the object.


isHer

If true, the object can be the antecedant for the pronoun “her.” This also affects certain default messages that adv.t displays for the object.


isThem

Added: TADS 2.5.2

If true, the object can be the antecedant for the pronoun “them.” This also affects certain default messages that adv.t displays for the object. In other words, the parser recognizes the isThem property for the purposes of deciding on the pronoun to display when prompting for an indirect object. Prior to version 2.5.2, the parser only recognized the isHim and isHer properties, and used the pronoun “it” if neither of these properties were consistently defined for the objects matching the direct object. As of 2.5.2 the parser uses the pronoun “them” if the matching objects all have isThem set to true.


isVisible(vantage)

Used to determine if an object is visible from the given object. The parser uses this to determine how to complain when an object isn’t accessible: if it’s visible, but not accessible, the parser will use cantReach to complain, otherwise it will simply say “I can't see that here.”


location

The object which contains the object.


locationOK

If this property is true, it tells the compiler that you know that the location property is not an object constant, and the compiler therefore suppresses the warning it would otherwise generate.


multisdesc

Used by the parser to display the current object when iterating through a list of direct objects in a command. Note that the parser will not call this method if the object defines or inherits a prefixdesc method.


newNumbered(actor, verb, num)

The parser calls this method on an object with a generic numeric adjective (adjective = '#') when the player uses the object in a noun phrase. This method returns the object to use as the resolution of the noun phrase; num gives the number that the player used in the noun phrase (for example, in “look in box 55”, num will be the number 55).


nilPrep

Associated with a deepverb object; used by the parser to determine the preposition to use when a command of the form VERB IOBJ DOBJ is entered. If undefined, the preposition object associated with the word “to” is used by default.


noun

Defines words as nouns, and associates them with the object.


parseUnknownDobj(actor, prep, iobj, wordlist)

The parser calls this method to resolve a noun phrase (the token strings of which are given by wordlist) which contains an unknown word to a direct object. This method is invoked on the deepverb object for the command’s verb.


parseUnknownIobj(actor, prep, iobj, wordlist)

The parser calls this method to resolve a noun phrase (the token strings of which are given by wordlist) which contains an unknown word to an indirect object. This method is invoked on the deepverb object for the command’s verb.


plural

Defines words as plurals, and associates them with the object.


pluraldesc

Displays a description of the object in the plural. The parser, and certain utility functions in adv.t, use this to display a collective name for a group of indistinguishable objects ("five gold coins”).


preferredActor

Used by the parser to determine if an object is a “preferred” actor; if this property is true, the object is chosen as the actor in cases where the actor is ambiguous and none of the other objects are preferred actors.


prefixdesc(show, current_index, count, multi_flags)

Called by the parser before the execution phase for each direct object in a command, to display a prefix for the object before its execution results are displayed. The parser calls this method for each direct object in a command, regardless of whether the command has a single direct object or multiple direct objects. The parser calls this method in preference to multisdesc.


prepDefault

Associated with a deepverb object. The parser uses this property to find the default preposition object to use when the player enters a partial command that starts with the verb and a direct object, but omits the preposition and indirect object.


preposition

Defines words as prepositions, and associates them with the object.


rejectMultiDobj(prep)

Associated with a deepverb object. If this method returns true, the verb doesn’t allow multiple direct objects or “all.”


roomAction(actor, verb, dobj, prep, iobj)

Called in the actor’s location during command execution.


roomCheck(verb)

Called in the actor at the beginning of execution, before object disambiguation.


sdesc

Short description. Used by the parser to display an object’s name.


statusLine

Called in the actor’s location to update the statue line.


thedesc

Displays the object’s name with a definite article.


validActor

Called by the parser to determine if the object is valid as an actor. This method doesn’t check to see if the object is logical to use as an actor, but simply if the object is accessible as the target of a command.


validDo(actor, obj, seqno)

Associated with a deepverb object. Returns true if the object is accessible as a direct object for the verb.


validDoList(actor, prep, iobj)

Associated with a deepverb object. Returns a list of possibly-valid direct objects for the verb. The objects returned will be tested for validity with validDo, so the list can contain invalid objects as well, but it must contain all of the valid direct objects for the verb.


validIo(actor, obj, seqno)

Associated with a deepverb object. Returns true if the object is accessible as an indirect object for the verb.


validIoList(actor, prep, dobj)

Associated with a deepverb object. Returns a list of possibly-valid indirect objects for the verb. The objects returned will be tested for validity with validIo, so the list can contain invalid objects as well, but it must contain all of the valid indirect objects for the verb.


value

The parser sets this property of the strObj or numObj object to the actual value of the string or number (respectively) entered in a command.


verb

Defines words as verbs, and associates them with the object. Strings in this list can consist of one or two words; the second word must also be separately defined as a preposition.


verbAction(actor, dobj, prep, iobj)

The parser calls this method on the deepverb object for the command, just before calling the actorAction method on the command’s actor.


Objects


againVerb

The deepverb object with the vocabulary for “again.” The parser internally handles the “again” processing when this verb’s vocabulary word is entered as the command.


Me

The default player actor object. When a command is not explicitly directed to another actor, this object is the actor to which the command is sent. When the game is first loaded, the parser uses Me as the default player character, but the game can change this using the parserSetMe() built-in function.


numObj

A special object which is used as the direct object when a number is entered in a command (such as in “enter 30 on calculator,” in which numObj is the direct object). The value property is set to the number actually entered in the command.


strObj

A special object which is used as the direct object when a quoted string is entered in a command (such as in ‘type "hello" on keyboard,’ in which strObj is the direct object). The value property is set to the string actually entered in the command.


takeVerb

Formerly required, but no longer directly used by the parser.


Functions


commandPrompt(type)

The parser calls this function, if defined, to display the prompt before asking for a command. The type code specifies the type of input being requested: 0 is a normal command; 1 is a command entered after the parser complains about an unknown word; 2 is a command entered in response to a disambiguation question; 3 is a command entered when the parser asks for a direct object; and 4 is a command entered when the parser asks for an indirect object.


commandAfterRead(type)

The parser calls this function, if defined, immediately after the player finishes entering each command line. This function can reverse any text effects that commandPrompt established just before the command line. The type code has the same value as in the preceding commandPrompt call.

This new function is intended to make it easier to customize certain aspects of your game’s user interface. In particular, if you’re using special formatting for the player command in the HTML interpreter (for example, you want to use a special typeface or font color for player commands), you can use commandAfterRead to turn off the special formatting you turned on in commandPrompt. Each call to commandPrompt is matched by an equivalent call to commandAfterRead, so you can always count on being able to undo any formatting changes you make in commandPrompt by placing the matching formatting commands in commandAfterRead.


endCommand(actor, verb, dobj_list, prep, iobj, status)

The parser invokes this function, if defined, at the end of the command, after executing daemons and fuses.


init

The system calls this immediately after loading the game, and again whenever the game is restarted. This function can perform any startup operations, such as setting fuses and daemons, and displaying an introductory message. Note that the system does not call init() when the player starts the TADS interpreter and specifies on the command line (or local equivalent) a saved game position to restore; in this case, the system instead calls initRestore(). (However, if initRestore() isn’t defined, the system does call init() in all cases.)


initRestore(savedGameFileName)

The system calls this function when the player starts the TADS interpreter and specifies a game to restore on the command line (or local equivalent). The purpose of this function is to allow the game to skip any introductory text that init() would normally display when starting a new game; since the player is explicitly jumping to a saved position, the player presumably doesn’t need to see the introductory text again. If this function isn’t defined, the system simply calls init() as though the game had been started without a saved game file.


pardon

The parser calls this function whenever the player enters an empty command. You can display an error message, if you wish.


parseAskobj(verb, ...)

The parser calls this function, if defined, to prompt for a missing direct or indirect object. If parseAskobjActor is defined, parseAskobj is ignored. If two arguments are provided, an indirect object is being requested, and the second argument is a preposition (which may be nil); otherwise, a direct object is being requested.


parseAskobjActor(actor, verb, ...)

The parser calls this function, if defined, to prompt for a missing direct or indirect object. If three arguments are provided, an indirect object is being requested, and the third argument is a preposition (which may be nil); otherwise, a direct object is being requested.


parseAskobjIndirect(actor, verb, prep, objectList)

The parser calls this function, if defined, to prompt for a missing indirect object. This is the parser’s first choice when prompting for an indirect object; the parser calls this function in preference to parseAskobjActor() or parseAskobj().


parseDefault(obj, prep)

The parser calls this function, if defined, to display a message indicating that the object (and the preposition, if not nil) are being used by default.


parseDisambig(nameString, objList)

The parser calls this function, if defined, to prompt for more information when the player enters an ambiguous object name. The nameString is the string of words entered by the player (given as a single-quoted string), and the objList is a list of the objects matching the name.


parseError(num, str)

The parser calls this function, if defined, to get the text of an error message. num is the message number, and str is the text of the message that the parser would display by default if this function weren’t defined. Note that the parser never calls this function if your game defines a parseErrorParam function.


parseErrorParam(num, str, ...)

The parser calls this function, if defined, to get the text of an error message. num is the message number, and str is the text of the message that the parser would display by default if this function weren’t defined. Additional parameters are specify the values for any “%s” (string) or “%d” (number) sequences in the default message string.


parseError2(verb, dobj, prep, iobj)

The parser calls this function, if defined, to display a message indicating that the verb can’t be applied to these objects (because one of the objects doesn’t define or inherit a verification method for the verb).


parseNounPhrase(wordlist, typelist, currentIndex, complainOnNoMatch, isActorCheck)

The parser calls this function, if defined, to parse each noun phrase. This function can do its own noun phrase parsing for custom noun phrase syntax, or can defer to the standard built-in noun phrase parser.


parseUnknownVerb(actor, wordlist, typelist, errnum)

The parser calls this function, if defined, to parse a sentence that the parser doesn’t recognize. The parser invokes this function if the command does not have a valid verb, or if the sentence does not fit a syntax pattern that the parser accepts.


preCommand(actor, verb, dobj_list, prep, iobj)

The parser invokes this function, if defined, at the start of the execution phase.


postAction(actor, verb, dobj, prep, iobj, status)

The parser invokes this function, if defined, at the end of the execution phase. The parser calls this function once for each direct object in a command with multiple direct objects. The parser invokes this function even when the execution phase terminates with exit, exitobj, or abort.


preinit

Called by the compiler, after compilation is complete, to perform any desired initialization. This function can’t set any fuses or daemons, or display any messages; these functions are not saved in the compiled game file, so they must wait until the init function, which is invoked at run-time. The preinit function is intended to perform any time-consuming computation - for example, setting up lists of objects or initializing property values - that would otherwise be done in init every time the game is started. By performing these functions in preinit, the work can be done at compile-time, saving players from having to wait for it each time they run the game. Note that this function won’t be called until run-time if the game is compiled for debugging; while this doesn’t affect the behavior of the game (apart from slowing down run-time startup), it allows you to use the debugger to step through your preinit function.


preparse(cmd)

The parser calls this function with a (single-quoted) string giving the full text of the command line each time the player enters a new command.


preparseCmd(wordList)

The parser calls this function with a list of (single-quoted) strings giving the words of the current command. This function is called for each individual command on a command line.



Chapter Six Table of Contents Eight