To record the names of all adjectives.
- §1. Adjectives are not their meanings
- §2. Adjectival phrases
- §6. Parsing adjectives
- §8. Testing agreement
- §9. Logging
§1. Adjectives are not their meanings. Adjectives are simpler than verbs, since they define unary rather than
binary predicates. The word "open" applies to only one term — logically, we
regard it as open(x)
, whereas a verb like "suspects" would appear
in formulae as suspects(x, y)
.
But they are nevertheless complicated enough to have multiple meanings. For instance, two of the senses of "empty" in the Standard Rules are:
Definition: a text is empty rather than non-empty if it is "".
Definition: a table name is empty rather than non-empty if the number of filled rows in it is 0.
(Which also defines two of the senses of "non-empty", another adjective.)
The clause empty(x)
can be fully understood only when we know what
kind of value x has; for a text, the first sense applies, and for a table
name, the second.
Adjectives may also need to inflect, though not in English. (Let's not argue about the word "blond"/"blonde", which is the only counterexample anybody ever brings up.)
§2. Adjectival phrases. Because of this we need a structure to represent an adjective as distinct from its meaning, and this is it.
@default ADJECTIVE_MEANING_TYPE void
typedef struct adjectival_phrase { struct name_cluster *adjective_names; #ifdef CORE_MODULE struct inter_name *aph_iname; struct package_request *aph_package; #endif ADJECTIVE_MEANING_TYPE *meanings; MEMORY_MANAGEMENT } adjectival_phrase;
The structure adjectival_phrase is private to this section.
§3. The following declares a new adjective, creating it only if necessary:
adjectival_phrase *Adjectives::declare(wording W, PREFORM_LANGUAGE_TYPE *nl) { adjectival_phrase *aph; LOOP_OVER(aph, adjectival_phrase) { wording C = Clusters::get_name_in_play(aph->adjective_names, FALSE, nl); if (Wordings::match(C, W)) return aph; } return Adjectives::from_word_range(W, nl); }
The function Adjectives::declare is used in §8.
§4. Whereas this simply creates it:
adjectival_phrase *Adjectives::from_word_range(wording W, PREFORM_LANGUAGE_TYPE *nl) { adjectival_phrase *aph = NULL; if (Wordings::nonempty(W)) aph = Adjectives::parse(W); if (aph) return aph; aph = CREATE(adjectival_phrase); aph->adjective_names = Clusters::new(); Clusters::add_with_agreements(aph->adjective_names, W, nl); aph->meanings = NULL; #ifdef EMPTY_ADJECTIVE_MEANING aph->meanings = EMPTY_ADJECTIVE_MEANING(); #endif #ifdef CORE_MODULE aph->aph_package = Hierarchy::package(Modules::current(), ADJECTIVES_HAP); aph->aph_iname = Hierarchy::make_iname_in(ADJECTIVE_HL, aph->aph_package); #endif if ((nl == NULL) && (Wordings::nonempty(W))) { #ifdef ADJECTIVE_NAME_VETTING if (ADJECTIVE_NAME_VETTING(W)) { #endif ExcerptMeanings::register(ADJECTIVE_MC, W, STORE_POINTER_adjectival_phrase(aph)); LOOP_THROUGH_WORDING(n, W) Preform::mark_word(n, <adjective-name>); #ifdef ADJECTIVE_NAME_VETTING } #endif } return aph; }
The function Adjectives::from_word_range is used in §3.
wording Adjectives::get_text(adjectival_phrase *aph, int plural) { return Clusters::get_name(aph->adjective_names, plural); }
The function Adjectives::get_text is used in §9, 3/au (§2).
§6. Parsing adjectives. This does what its name suggests: matches the name of any adjective known to Inform.
<adjective-name> internal { parse_node *p = ExParser::parse_excerpt(ADJECTIVE_MC, W); if (p) { *XP = RETRIEVE_POINTER_adjectival_phrase( ExcerptMeanings::data(ParseTree::get_meaning(p))); return TRUE; } return FALSE; }
§7. These are registered as excerpt meanings with the ADJECTIVE_MC
meaning
code, so parsing a word range to match an adjective is easy. By construction
there is only one adjectival_phrase
for any given excerpt of text, so
the following is unambiguous:
adjectival_phrase *Adjectives::parse(wording W) { if (<adjective-name>(W)) return <<rp>>; return NULL; }
The function Adjectives::parse is used in §4.
void Adjectives::test_adjective(OUTPUT_STREAM, wording W) { adjectival_phrase *aph = Adjectives::declare(W, NULL); if (aph == NULL) { WRITE("Failed test\n"); return; } int g, n; for (g = NEUTER_GENDER; g <= FEMININE_GENDER; g++) { switch (g) { case NEUTER_GENDER: WRITE("neuter "); break; case MASCULINE_GENDER: WRITE("masculine "); break; case FEMININE_GENDER: WRITE("feminine "); break; } for (n = 1; n <= 2; n++) { if (n == 1) WRITE("singular: "); else WRITE(" / plural: "); wording C = Clusters::get_name_general(aph->adjective_names, NULL, n, g); WRITE("%W", C); } WRITE("^"); } }
The function Adjectives::test_adjective appears nowhere else.
§9. Logging. To identify an adjective in the debugging log:
void Adjectives::log(adjectival_phrase *aph) { if (aph == NULL) { LOG("<null adjectival phrase>"); return; } wording W = Adjectives::get_text(aph, FALSE); if (Streams::I6_escapes_enabled(DL)) LOG("'%W'", W); else LOG("A%d'%W'", aph->allocation_id, W); }
The function Adjectives::log appears nowhere else.