Inform 6 - more sophisticated preposition use

I posted this over on RAIF, but haven’t gotten any replies yet so hoping someone here may be able to help me out. I’m trying to imitate the feature that Anson Turner added to Platypus to allow commands such as

GET THE DOCUMENTS IN THE FOLDER UNDER THE DESK

PUT THE COINS IN THE BAG IN THE TREASURE CHEST

By following what Anson did in Platypus I’ve cobbled together the following code. It basically does work, but it breaks the parsing of PUT ALL and GET ALL FROM. I think the problem is that when I enable TRACE 4 I can see that without this extension, PUT ALL IN CHEST treats word 4 as CHEST, but with the extension word 4 is treated as IN. This has me totally baffled, so if anyone can offer any help at all I would be very grateful.

The extension consists of a replacement for TryGivenObject() and two new routines, ParseObj() and WordLeft().

[ TryGivenObject obj threshold k w;

#ifdef DEBUG;
   if (parser_trace>=5)
       print "    Trying ", (the) obj, " (", obj, ") at word ", wn, "^";
#endif;

   dict_flags_of_noun = 0;

!  If input has run out

    if (wn > num_words) {
        if (indef_mode ~= 0)
            dict_flags_of_noun = $$01110000;  ! Reject "plural" bit
        MakeMatch(obj,0);
        #Ifdef DEBUG;
        if (parser_trace >= 5) print "    Matched (0)^";
        #Endif; ! DEBUG
        return 1;
    }

   parser_action = NULL;

   w = NounWord();

   if (w==1 && player==obj) { k=1; jump MMbyPN; }

   if (w == obj)
   {   k=1; jump MMbyPN; }

   wn--;

   threshold = ParseObj(obj);
#ifdef DEBUG;
   if (threshold>=0 && parser_trace>=5)
       print "    ParseObj returned ", threshold, "^";
#endif;
    k = threshold;


   .MMbyPN;

            if (parser_action == ##PluralFound)
               dict_flags_of_noun = dict_flags_of_noun | 4;

            if (dict_flags_of_noun & 4) {
                if (~~allow_plurals) k = 0;
                else {
                    if (indef_mode == 0) {
                        indef_mode = 1; indef_type = 0; indef_wanted = 0;
                    }
                    indef_type = indef_type | PLURAL_BIT;
                    if (indef_wanted == 0) indef_wanted = 100;
                }
            }

    if (~~k) rfalse;

   #ifdef DEBUG;
       if (parser_trace>=5)
       {   print "    Matched (", k, ")^";
       }
   #endif;
   MakeMatch(obj,k);
   return k;
];

[ ParseObj obj wd m n i ap;

	if (obj.parse_name ~= 0) {
		parser_action = NULL; i = wn;
		n = RunRoutines(obj, parse_name);
		if (n == 0) rfalse;
		if (n > 0) {
			wn = i + n;
			wd = NextWord();
			jump Prepositions1;
			}
	}
	n = ParseNoun(obj);
	if (n == 0) rfalse;
	if (n > 0) jump Prepositions1;
	n = 0;
	wd = NextWord(); i = 0;

	if (indef_wanted == 100) { n++; jump Prepositions1; }
	while (WordInProperty(wd, obj, name)) { n++; wd = NextWord(); }


	! Here we handle the case of PUT THE DAGGER IN THE SHEATH ON THE TABLE.

	.Prepositions1;

	if (~~parent(obj)) jump GiveResult;

	while (parent(obj) has container or supporter) {

        if ((parent(obj) has container && wd == 'in' or 'inside' or 'within')
		|| (parent(obj) has supporter && wd == 'on' or 'upon' or 'off')) {

            ! Are we sure we have PUT (DAGGER) IN (SHEATH) rather than PUT (DAGGER IN SHEATH)?
            if (line_ttype-->pcount == PREPOSITION_TT)
            {   i = pcount;
                if (WordLeft(line_tdata-->i)) jump Prepositions2;
                if ((line_token-->i)->0 & $20)
                {   do
                    {   if (WordLeft(line_tdata-->i)) jump Prepositions2;
                        i++;
                    } until ((line_token-->i == ENDIT_TOKEN)
                              || (((line_token-->i)->0 & $10) == 0));
                }
                jump GiveResult;
            }
            .Prepositions2;

		ap = allow_plurals;
		i = ParseObj(parent(obj));
		allow_plurals = ap;
		if (~~i) break;

		m = m + i + 1;
		obj = parent(obj);
	}
	else break;
	}

	.GiveResult;

	if (n == 0) rfalse; return m + n;
];

[ WordLeft wd o_wn cw flag;
    o_wn = wn;
    while ((cw = NextWordStopped()) ~= -1)
    {   if (flag)
        {   if (cw && (cw->#dict_par1) & 1) break;
            flag = 0;
        }
        if (cw == wd) { wn = o_wn; rtrue; }
        if (wd == COMMA_WORD or AND1__WD or AND2__WD or AND3__WD
        	or THEN1__WD or THEN2__WD or THEN3__WD)
		flag = 1;
    }
    wn = o_wn;
    rfalse;
];

I’ve worked out most of the kinks in this and uploaded it to the IF Archive as Positions.h.