ParseNoun entry point

According to DM4:

ParseNoun(obj)

To do the job of parsing the name property (if parse_name hasn’t done it already). This takes one argument, the object in question, and returns a value as if it were a parse_name routine.

Routine returns The number of words matched, or 0 if there is no match, or −1 to decline to make a decision and give the job back to the parser. Note that if −1 is returned, the word number variable wn must be left set to the first word the parser should look at — probably the same value it had when ParseNoun was called, but not necessarily.

I’m reading the specification and looking at the code that calls ParseNoun (line 4544 in parser.h in library v6.12.5), and I can’t get my head around how it’s supposed to work and how it might be put to use in a game.

The way I read the specification, it seems wn can have any value if I return 0 or a positive number, just as in parse_name. I don’t find that to be the case though. And I’ve tried to write an example which consumes a word (increases wn by 1) and returns -1, but I find that the parser gets all confused after this.

Can anyone enlighten me? Can anyone provide a real-world example of a ParseNoun routine that returns -1 and increases wn?

Contrary to the description in DM4, I don’t think that ParseNoun() is free to leave wn in an arbitrary place. It seems to be allowed for parse_name() only because wn is saved before the call and restored if the return result is negative. This appears to have been true even for StdLib 6/9.

With the following changes (note: tested vs StdLib 6/11, not 6.12.5 but they seem substantially similar), I think it can be made to work closer to the way that it is described in DM4:

...
#Ifdef DEBUG;
if (threshold >= 0 && parser_trace >= 5) print "    ParseNoun returned ", threshold, "^";
#Endif; ! DEBUG
! MODIFIED - don't arbitrarily increase wn when ParseNoun() returns -1
if (threshold > 0) { k = threshold; wn = j + k; jump MMbyPN; } ! MODIFIED - force wn to match claimed consumption
if (threshold == 0 || Refers(obj,wn) == 0) { ! MODIFIED - check wn instead of wn-1
  .NoWordsMatch;
    if (indef_mode ~= 0) {
        k = 0; parser_action = NULL; wn = j; ! MODIFIED - restore wn to pre-ParseNoun() state
        jump MMbyPN;
...
if (threshold < 0) {
    threshold = wn - j; ! MODIFIED - set threshold to reflect any words consumed by ParseNoun()
    w = NextWord(); ! MODIFIED (order) - ensure w contains actual first word of noun phrase if ParseNoun() moved wn
    dict_flags_of_noun = (w->#dict_par1) & $$01110100;
    while (Refers(obj, wn-1)) {
...

With that in place, it becomes possible to use it productively by leaving wn where you want it and returning -1. I worked up an example to parse the word 'your' as a possessive pronoun based on an owner property for objects, for use when talking to an NPC.

2 Likes

I have filed an issue for this.