That no.verb did not make sense in that context

There’s, I believe, a known issue in current Inform, where if you have any no.verb grammar lines (that is, Understand lines for actions that don’t start with a single fixed word) that start with a ROUTINE_FILTER token (that is, “[any whatever]”), the parser will say “that noun did not make sense in that context” instead of “that’s not a verb I recognize” for all unknown verbs.

The simplest solution is to just replace that error message, since “that noun did not make sense in that context” is an error that practically never comes up apart from this. (Formally speaking, NOTINCONTEXT_PE is thrown when a ROUTINE_FILTER or ATTR_FILTER token fails to match anything, which is pretty rare.)

Before printing a parser error when the latest parser error is the noun did not make sense in that context error: now the latest parser error is the not a verb I recognise error.

Is there a better or more standard solution to this problem, though? I’m sure I can’t be the only person to run into it. (In particular, including certain extensions—such as my own Boolean Variables—will always make it happen.)

1 Like

It looks like maybe the compiler is inserting the logic to set this error type as part of each generated scope_filter routine?

Verb 'no.verb'
	* scope=Scope_Filter_4  -> Examine

[ Scope_Filter_4 
	obj ! object loop variable
	o2 ! saved value of noun
	switch (scope_stage) {
	    1: rfalse;
	    2: obj=noun;
	    objectloop(noun ofclass Object && (((noun ofclass K2_thing) && (noun ofclass K2_thing)))) {
	        o2 = noun; noun = obj;
	        suppress_scope_loops = true; PlaceInScope(o2, true); suppress_scope_loops = false;
	        noun = o2;
	    3: nextbest_etype = NOTINCONTEXT_PE; return -1; ! <-- set here

That becomes the error reported as part of Parser Letter I:

if (etype == ASKSCOPE_PE) {
    scope_stage = 3;
    if (indirect(scope_error) == -1) {	! <-- NOTINCONTEXT_PE returned from call here
        best_etype = nextbest_etype;	! <-- assigned to best_etype, so that's the error produced
        if (~~((etype ofclass Routine) || (etype ofclass String)))
        jump GiveError;

However, the actual invocation of that code in scope_stage 3 is triggered via a routine called CantSee():

! ==== ==== ==== ==== ==== ==== ==== ==== ==== ====
! Parser.i6t: CantSee
! ==== ==== ==== ==== ==== ==== ==== ==== ==== ====

[ CantSee  i w e;

	if (scope_token ~= 0) {
	    scope_error = scope_token; return ASKSCOPE_PE;	! <-- here

	wn--; w = NextWord();
	if (w == pronoun_word) {
		w = NextWordStopped(); wn--;
		if ((w == -1) || (line_token-->(pcount) ~= ENDIT_TOKEN)) {
			if (pcount > 0) AnalyseToken(line_token-->(pcount-1));
			if ((pcount > 0) && (found_ttype == ROUTINE_FILTER_TT or ATTR_FILTER_TT))
			else {
				pronoun__word = pronoun_word; pronoun__obj = pronoun_obj;
				e = ITGONE_PE;
	if (etype > e) return etype;
	return e;

… so it’s possible to bypass it in this routine with something like:

if (scope_token ~= 0 && wn > 2) {	! MODIFIED
    scope_error = scope_token; return ASKSCOPE_PE;

That may break something else, of course.


You probably already know, but this kind of action grammar will not work with an NPC - see Weird difference in how action grammars are interpreted between "Frotz ball" and "Bob, Frotz ball"

That’s due to a different bug, which is addressable with certain caveats. See the analysis by @drpeterbatesuk at Bug? Topic-based actions not parsed if they share a verb word with another action for the cause and a fix.

EDIT: Oh, I see that’s already covered on the thread you mentioned. Well, I’ll leave this as a shortcut for anyone who lands here first.

How are you managing to get an attribute filter token in the first place? When I try to set up an action that would do that…

A thing can be zorky.

Zorking is an action applying to one thing. Understand "[something zorky]" as zorking.

I get a noun=<Routine> type of token in the generated I6:

Attribute p59_zorky;

Verb 'no.verb'
	* noun=Noun_Filter_4  -> A77_zorking

I don’t think I7 can actually generate them, but the parser code checks for 'em all the same.