Changing verb grammar at runtime

I’m trying to change the VerbRule grammar for an action at runtime. For this, it seems like I need to get to the GrammarProd object defined by the VerbRule macro? I can then apparently use the addAlt(), clearAlt(), etc, methods to modify the grammar.

However, I’m unable to find any examples. Has anyone delved in this before?

Issue is solved, but I forgot to post the solution for anyone landing here through a search:

First, we need to create a “match object”, which should inherit from the action we want to modify, as well as from DynamicProd. Here, we’ll use WaitAction:

local matchObj = TadsObject.createInstanceOf(WaitAction, DynamicProd);

Then, we set its “grammarTag” property:

matchObj.grammarTag = 'predicate(ModifiedWait)';

“predicate(Foo)” is what is used normally as the tag when you write “VerbRule(Foo)” rules, so we did the same here.

Next, we clear the grammar for the existing “Wait” rule. This is done through the “predicate” object:

predicate.deleteAlt('Wait');

We then add the new grammar:

predicate.addAlt( ''' 'z' | 'wait' | ('kill' | 'waste') ( | 'some') 'time' ''', matchObj, cmdDict, t3GetGlobalSymbols());

The new grammar is now in effect (entering KILL SOME TIME will perform a Wait action.)

For transitive actions that apply to objects/topics/etc, you can’t use the “dobj”, “dobjList”, etc macros. You need to use their expansions instead (defined in en_us.h).

There’s a caveat though: Mike Roberts pointed out a T3 VM bug where the above might not work correctly in all cases. It will be fixed in the next TADS 3 release.

Thanks for sharing the example Nikos. Two observations:

Is deleting the original alternative necessary (in your example)? Couldn’t you just add a new one that omits “wait” and “z”?

About transitive actions: my impression is that there is nothing special about those except that they use macros such as dobjList, singleIobj, etc, so I think you should check what those macros expand to and write the grammar definition string accordingly.

Yes, that works. The old grammar will still be active.

That works fine. I updated my post above.

(My use case is a bit different though. The above code is compiled at runtime, it does not exist in the static code of the game. The symbols of the expanded macro are not found by the dynamic compiler. I’m sure there’s a solution, but in my case I only needed to alter the grammar for a non-transitive action, so it’s fine.)