1
0
Fork 0
mirror of https://github.com/ganelson/inform.git synced 2024-07-05 16:44:21 +03:00
inform7/services/linguistics-module/Chapter 3/Special Meanings.w
2020-08-02 19:04:24 +01:00

117 lines
3.4 KiB
OpenEdge ABL

[SpecialMeanings::] Special Meanings.
To abstract non-standard, perhaps non-SVO, meanings of a verb.
@h Special meaning functions.
Regular meanings of verbs are represented by |VERB_MEANING_LINGUISTICS_TYPE|
pointers -- see //Verb Meanings//. In Inform, those are binary predicates.
They always take two terms.
However, Inform sometimes wants sentences which are written in non-standard
ways, with anything from one to three terms, and which don't correspond to
any of the relations. (For example, "Include Locksmith by Emily Short".)
These are represented by functions to perform the necessary business; the
type |special_meaning_fn| gives the type of such a function.
=
typedef int (*special_meaning_fn)(int, parse_node *, wording *);
@ This is a convenient generic special-meaning function; it simply accumulates
non-empty SPs and OPs as unparsed noun phrases and accepts them.
The first parameter is the task to be performed on the verb node pointed
to by the second. The task number must belong to the |*_SMFT| enumeration,
and the only task used by the Linguistics module is |ACCEPT_SMFT|. This should
look at the array of wordings and either accept this as a valid usage, build
a subtree from the verb node, and return |TRUE|, or else return |FALSE| to
say that the usage is invalid: see Verb Phrases for more.
The user is then free to define further SMF tasks, and Inform does so.
@e ACCEPT_SMFT from 0
=
int SpecialMeanings::generic_smf(int task, parse_node *V, wording *NPs) {
switch (task) {
case ACCEPT_SMFT: {
parse_node *A = V;
for (int i=0; i<3; i++) {
wording W = (NPs)?(NPs[i]):EMPTY_WORDING;
if (Wordings::nonempty(W)) {
<np-unparsed>(W);
parse_node *p = <<rp>>;
A->next = p; A = p;
}
}
return TRUE;
}
}
return FALSE;
}
@h Special meaning holders.
Although a SM is basically encapsulated by a function, it's convenient to
have some metadata with it too:
@ =
typedef struct special_meaning_holder {
int (*sm_func)(int, parse_node *, wording *); /* (compiler doesn't like typedef here) */
struct text_stream *sm_name;
int metadata_N;
CLASS_DEFINITION
} special_meaning_holder;
@ =
special_meaning_holder *SpecialMeanings::declare(special_meaning_fn func,
text_stream *name, int p) {
special_meaning_holder *smh = CREATE(special_meaning_holder);
if (func == NULL) func = SpecialMeanings::generic_smf;
smh->sm_func = func;
smh->sm_name = Str::duplicate(name);
smh->metadata_N = p;
return smh;
}
@ SMHs can be found by name:
=
special_meaning_holder *SpecialMeanings::find_from_wording(wording W) {
TEMPORARY_TEXT(name)
WRITE_TO(name, "%W", W);
special_meaning_holder *smh;
LOOP_OVER(smh, special_meaning_holder)
if (Str::eq_insensitive(smh->sm_name, name))
break;
DISCARD_TEXT(name)
return smh;
}
@ Metadata access:
=
int SpecialMeanings::get_metadata_N(special_meaning_holder *smh) {
if (smh == NULL) return 0;
return smh->metadata_N;
}
text_stream *SpecialMeanings::get_name(special_meaning_holder *smh) {
if (smh == NULL) return NULL;
return smh->sm_name;
}
int SpecialMeanings::is(special_meaning_holder *smh, special_meaning_fn func) {
if (smh == NULL) return FALSE;
if (smh->sm_func == func) return TRUE;
return FALSE;
}
@ Calling:
=
int SpecialMeanings::call(special_meaning_holder *smh, int task, parse_node *V,
wording *NPs) {
if ((smh == NULL) || (smh->sm_func == NULL)) return FALSE;
return (*(smh->sm_func))(task, V, NPs);
}