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/Verb Meanings.w
2020-06-29 23:41:10 +01:00

205 lines
7 KiB
OpenEdge ABL

[VerbMeanings::] Verb Meanings.
To abstract the meaning of a verb.
@h Other modukes.
We allow the modules using us to have their own data about the semantics of
a verb, which we will attach to our own |verb_meaning| structure. It has to
be a pointer to the type |VERB_MEANING_LINGUISTICS_TYPE|, and by default, there's none:
@default VERB_MEANING_LINGUISTICS_TYPE void
=
VERB_MEANING_LINGUISTICS_TYPE *VerbMeanings::reverse_VMT(VERB_MEANING_LINGUISTICS_TYPE *recto) {
#ifdef VERB_MEANING_REVERSAL_LINGUISTICS_CALLBACK
return VERB_MEANING_REVERSAL_LINGUISTICS_CALLBACK(recto);
#endif
#ifndef VERB_MEANING_REVERSAL_LINGUISTICS_CALLBACK
return recto;
#endif
}
@h Abstracting meaning.
Recall that each verb can have multiple forms: for example, "to go"
might occur in three forms -- "go" alone, "go to", or "go from", which
are distinguished in English by the use of prepositions such as "to" and
"from". Each of these three verb forms has its own meaning.
However, we can also use indirection to tie one meaning to another. This is
used, for example, to specify the meaning of "A is liking B". We regard
this as "to be" plus copular preposition "liking"; or sometimes the verb
is invisible, as in "someone liking B", which implicitly means "someone
who is liking B". The meaning of "to be" plus "liking" is set by
indirection so that it is always the same as "likes". Similarly, the
meaning of "liked by" is set to be the same as "likes", but reversed
(in that its subject and object must be switched). This ensures that
if the meaning of "likes" changes, its associated usages "is liking"
and "is liked by" automatically change with it.
@ The "meaning" is what state or change a verb describes. In Inform, some
verbs used in assertion sentences have special meanings, instructing the
compiler to do something: for example,
>> To disavow is a verb.
But most sentences set the state of some relation:
>> The bag is on the table.
Our abstraction stays close to that. We're going to assume that most
verbs have a regular meaning which can be represented in a piece of
data (of type |VERB_MEANING_LINGUISTICS_TYPE|, which for Inform 7 means a binary
predicate), while a few have special meanings which can only be handled
ad-hoc by a function. Here's the type for such a function:
=
typedef int (*special_meaning_fn)(int, parse_node *, wording *);
@ 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 following 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.
@e ACCEPT_SMFT from 0
=
typedef struct verb_meaning {
int reversed;
VERB_MEANING_LINGUISTICS_TYPE *regular_meaning; /* in I7, this will be a binary predicate */
int (*special_meaning)(int, parse_node *, wording *); /* (for tangling reasons, can't use typedef here) */
struct verb *take_meaning_from; /* "to like", in the example above */
struct parse_node *where_assigned; /* at which sentence this is assigned to a form */
} verb_meaning;
@ Here's how the indirection trick is done: if |vm| takes meaning from,
say, "to like", then we replace it with the meaning of "likes" plus no
preposition
=
verb_meaning *VerbMeanings::indirect_meaning(verb_meaning *vm) {
if ((vm) && (vm->take_meaning_from)) {
return VerbMeanings::get_regular_meaning_of_verb(vm->take_meaning_from, NULL, NULL);
}
return vm;
}
@ All VMs begin as meaningless, which indicates (e.g.) that no meaning
has been specified.
=
verb_meaning VerbMeanings::meaninglessness(void) {
verb_meaning vm;
vm.regular_meaning = NULL;
vm.special_meaning = NULL;
vm.reversed = FALSE;
vm.take_meaning_from = NULL;
vm.where_assigned = current_sentence;
return vm;
}
int VerbMeanings::is_meaningless(verb_meaning *vm) {
vm = VerbMeanings::indirect_meaning(vm);
if (vm == NULL) return TRUE;
if ((vm->regular_meaning == NULL) && (vm->special_meaning == NULL)) return TRUE;
return FALSE;
}
verb_meaning VerbMeanings::new(VERB_MEANING_LINGUISTICS_TYPE *rel, special_meaning_fn soa) {
verb_meaning vm = VerbMeanings::meaninglessness();
vm.regular_meaning = rel;
vm.special_meaning = soa;
return vm;
}
verb_meaning VerbMeanings::special(special_meaning_fn soa) {
verb_meaning vm = VerbMeanings::meaninglessness();
vm.special_meaning = soa;
return vm;
}
verb_meaning VerbMeanings::new_indirection(verb *from, int reversed) {
verb_meaning vm = VerbMeanings::meaninglessness();
vm.reversed = reversed;
vm.take_meaning_from = from;
return vm;
}
VERB_MEANING_LINGUISTICS_TYPE *VerbMeanings::get_relational_meaning(verb_meaning *vm) {
if (vm == NULL) return NULL;
int rev = vm->reversed;
vm = VerbMeanings::indirect_meaning(vm);
if (vm == NULL) return NULL;
if (VerbMeanings::is_meaningless(vm)) return NULL;
VERB_MEANING_LINGUISTICS_TYPE *rel = vm->regular_meaning;
if (rel == NULL) return NULL;
if (vm->reversed) rev = (rev)?FALSE:TRUE;
if (rev) rel = VerbMeanings::reverse_VMT(rel);
return rel;
}
special_meaning_fn VerbMeanings::get_special_meaning(verb_meaning *vm, int *rev) {
if (vm == NULL) return NULL;
*rev = vm->reversed;
vm = VerbMeanings::indirect_meaning(vm);
if (vm == NULL) return NULL;
if (vm->reversed) *rev = (*rev)?FALSE:TRUE;
return vm->special_meaning;
}
void VerbMeanings::add_special(verb_meaning *vm, special_meaning_fn spec) {
if (vm) vm->special_meaning = spec;
else internal_error("assigned special to null meaning");
}
parse_node *VerbMeanings::get_where_assigned(verb_meaning *vm) {
if (vm) return vm->where_assigned;
return NULL;
}
void VerbMeanings::set_where_assigned(verb_meaning *vm, parse_node *pn) {
if (vm) vm->where_assigned = pn;
else internal_error("assigned location to null meaning");
}
void VerbMeanings::log(OUTPUT_STREAM, void *vvm) {
verb_meaning *vm = (verb_meaning *) vvm;
if (vm == NULL) { WRITE("<none>"); return; }
if (vm->reversed) WRITE("reversed-");
if (vm->take_meaning_from) WRITE("<$w>=", vm->take_meaning_from);
if (VerbMeanings::get_relational_meaning(vm)) {
#ifdef CORE_MODULE
WRITE("(%S)", VerbMeanings::get_relational_meaning(vm)->debugging_log_name);
#else
WRITE("(relation)");
#endif
}
if (vm->special_meaning) {
if (VerbMeanings::get_relational_meaning(vm)) WRITE("/");
WRITE("(special)");
}
if ((VerbMeanings::get_relational_meaning(vm) == NULL) && (vm->special_meaning == NULL))
WRITE("(meaningless)");
}
@ Where:
=
verb_meaning *VerbMeanings::get_regular_meaning_of_verb(verb *V,
preposition *prep, preposition *second_prep) {
verb_form *vf = Verbs::find_form(V, prep, second_prep);
return VerbMeanings::get_regular_meaning_of_verb_form(vf);
}
verb_meaning *VerbMeanings::get_regular_meaning_of_verb_form(verb_form *vf) {
if (vf)
for (verb_sense *vs = vf->list_of_senses; vs; vs = vs->next_sense) {
int rev = 0;
if (VerbMeanings::get_special_meaning(&(vs->vm), &rev) == NULL)
return &(vs->vm);
}
return NULL;
}