diff --git a/README.md b/README.md index 0bfdd09e5..a5af5098b 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Inform 7 -v10.1.0-alpha.1+6Q52 'Krypton' (22 May 2020) +v10.1.0-alpha.1+6Q53 'Krypton' (23 May 2020) ## About Inform 7 diff --git a/build.txt b/build.txt index ed8e9fed8..65acd418a 100644 --- a/build.txt +++ b/build.txt @@ -1,3 +1,3 @@ Prerelease: alpha.1 -Build Date: 22 May 2020 -Build Number: 6Q52 +Build Date: 23 May 2020 +Build Number: 6Q53 diff --git a/docs/core-module/1-wtc.html b/docs/core-module/1-wtc.html index c4ff75c3a..3c94661c6 100644 --- a/docs/core-module/1-wtc.html +++ b/docs/core-module/1-wtc.html @@ -132,7 +132,7 @@ thing which is being compiled when it is. inform7_task->stage_of_compilation = -1; inform7_task->next_resource_number = 3; - English_language = Projects::get_language_of_syntax(project); + InflectionDefns::set_default_nl(Projects::get_language_of_syntax(project)); int rv = Sequence::carry_out(TargetVMs::debug_enabled(inform7_task->task->for_vm)); inform7_task = NULL; diff --git a/docs/core-module/3-pd.html b/docs/core-module/3-pd.html index 601e3b7eb..2b0d2d0c7 100644 --- a/docs/core-module/3-pd.html +++ b/docs/core-module/3-pd.html @@ -103,7 +103,7 @@ trouble to search the existing dictionary here. wording P = Node::get_text(V->next->next); Forbid plural declarations containing quoted text2.1; if (Assertions::Creator::vet_name_for_noun(P) == FALSE) return TRUE; - Pluralisation::register(S, P, English_language); + Pluralisation::register(S, P, InflectionDefns::default_nl(NULL)); return TRUE; } break; diff --git a/docs/core-module/4-am.html b/docs/core-module/4-am.html index 83168b842..c371955d4 100644 --- a/docs/core-module/4-am.html +++ b/docs/core-module/4-am.html @@ -1527,7 +1527,7 @@ prefaced "(of a rulebook)", "(of an activity)", and so on.
 <adaptive-adjective> internal {
-    if (Projects::get_language_of_play(Task::project()) == English_language) return FALSE;
+    if (Projects::get_language_of_play(Task::project()) == InflectionDefns::default_nl(NULL)) return FALSE;
     adjectival_phrase *aph;
     LOOP_OVER(aph, adjectival_phrase) {
         wording AW = Clusters::get_name_general(aph->adjective_names, Projects::get_language_of_play(Task::project()), 1, -1);
@@ -1544,7 +1544,7 @@ prefaced "(of a rulebook)", "(of an activity)", and so on.
 
 
 void Adjectives::Meanings::agreements(void) {
-    if (Projects::get_language_of_play(Task::project()) == English_language) return;
+    if (Projects::get_language_of_play(Task::project()) == InflectionDefns::default_nl(NULL)) return;
     adjectival_phrase *aph;
     LOOP_OVER(aph, adjectival_phrase) {
         wording PW = Clusters::get_name_general(aph->adjective_names, Projects::get_language_of_play(Task::project()), 1, -1);
diff --git a/docs/core-module/5-un.html b/docs/core-module/5-un.html
index 0da5131e4..c834001b4 100644
--- a/docs/core-module/5-un.html
+++ b/docs/core-module/5-un.html
@@ -185,7 +185,7 @@ and is a somewhat provisional feature for now.
     inform_language *nl = Node::get_defn_language(pn->next->next);
     int g = Annotations::read_int(pn->next->next, gender_reference_ANNOT);
     if (nl == NULL) internal_error("No such NL");
-    if (nl == English_language) {
+    if (nl == InflectionDefns::default_nl(NULL)) {
         StandardProblems::sentence_problem(Task::syntax_tree(), _p_(PM_CantTranslateIntoEnglish),
             "you can't translate into English",
             "only out of it.");
diff --git a/docs/core-module/6-nv.html b/docs/core-module/6-nv.html
index f65d29654..678c564df 100644
--- a/docs/core-module/6-nv.html
+++ b/docs/core-module/6-nv.html
@@ -165,7 +165,7 @@ as the object.
 
 <verb-implies-sentence-subject> ::=
     in <natural-language> <infinitive-declaration> |    ==> R[2]; <<inform_language:nl>> = (inform_language *) (RP[1]);
-    <infinitive-declaration>							==> R[1]; <<inform_language:nl>> = English_language;
+    <infinitive-declaration>							==> R[1]; <<inform_language:nl>> = InflectionDefns::default_nl(NULL);
 
 <infinitive-declaration> ::=
     to <infinitive-usage> ( ... ) |    ==> R[1]; <<giving-parts>> = TRUE
@@ -715,7 +715,7 @@ foreign verbs (4).
     binary_predicate *bp = VerbMeanings::get_relational_meaning(&vm);
     if (bp == a_has_b_predicate) p = 1;
     if (bp == R_equality) p = 2;
-    if ((nl) && (nl != English_language)) p = 5;
+    if ((nl) && (nl != InflectionDefns::default_nl(NULL))) p = 5;
     ++new_verb_sequence_count;
     vi = Verbs::new_verb(vc, FALSE);
     vc->vc_conjugates = vi;
@@ -801,13 +801,13 @@ foreign verbs (4).
     NewVerbs::declare_sm(Sentences::VPs::omit_from_SMF,						I"omit-from", 4);
 
     word_assemblage infinitive = PreformUtilities::wording(<bootstrap-verb>, 0);
-    verb_conjugation *vc = Conjugation::conjugate(infinitive, English_language);
+    verb_conjugation *vc = Conjugation::conjugate(infinitive, InflectionDefns::default_nl(NULL));
     verb_identity *vi = Verbs::new_verb(vc, TRUE);
     vc->vc_conjugates = vi;
     VerbUsages::register_all_usages_of_verb(vi, FALSE, 2);
 
     infinitive = PreformUtilities::wording(<bootstrap-verb>, 1);
-    vc = Conjugation::conjugate(infinitive, English_language);
+    vc = Conjugation::conjugate(infinitive, InflectionDefns::default_nl(NULL));
     vi = Verbs::new_verb(vc, FALSE);
     vc->vc_conjugates = vi;
     VerbUsages::register_all_usages_of_verb(vi, FALSE, 3);
@@ -1341,7 +1341,7 @@ usages to the debugging log.
     if (vu == NULL) { LOG("(null verb usage)"); return; }
     LOG("VU: $f ", &(vu->vu_text));
     if (vu->negated_form_of_verb) LOG("(negated) ");
-    Linguistics::log_tense_number(DL, vu->tensed);
+    InflectionDefns::log_tense_number(DL, vu->tensed);
 }
 
 void NewVerbs::log_all(void) {
diff --git a/docs/if-module/3-tnt.html b/docs/if-module/3-tnt.html
index d1165716d..788f53457 100644
--- a/docs/if-module/3-tnt.html
+++ b/docs/if-module/3-tnt.html
@@ -266,7 +266,7 @@ from sentences, and this can include I6 properties with no I7 analogue.
                 this_is_named_for_something_with_a_printed_name = TRUE;
         Issue problem message if the name contains a comma11.1.1;
         if (this_has_a_printed_name == FALSE) Assert the printed name property11.1.2;
-        if (Projects::get_language_of_play(Task::project()) != English_language)
+        if (Projects::get_language_of_play(Task::project()) != InflectionDefns::default_nl(NULL))
             Assert male, female, neuter adjectives from grammatical gender11.1.4;
     }
 
diff --git a/docs/inflections-module/1-im.html b/docs/inflections-module/1-im.html index 19f98b9ff..4c792dfec 100644 --- a/docs/inflections-module/1-im.html +++ b/docs/inflections-module/1-im.html @@ -127,7 +127,7 @@ which use this module:
diff --git a/docs/inflections-module/2-ld.html b/docs/inflections-module/2-ld.html index 37497e125..fe2695c28 100644 --- a/docs/inflections-module/2-ld.html +++ b/docs/inflections-module/2-ld.html @@ -72,11 +72,13 @@ function togglePopup(material_id) {

define NO_KNOWN_GENDERS 3
-define NEUTER_GENDER 1				 can be used as Scandinavian "common gender"
+define NEUTER_GENDER 1  or can be used as Scandinavian "common gender"
 define MASCULINE_GENDER 2
 define FEMININE_GENDER 3
 
-

§2. There are six "persons": +

§2. There are six "persons". The sequence corresponds to the defined constants +in the English Language extension, which we assume will be followed by other +languages.

define NO_KNOWN_PERSONS 6
@@ -101,15 +103,9 @@ function togglePopup(material_id) {
 define ACTIVE_MOOD 0
 define PASSIVE_MOOD 1
 
-

§5. 25 cases ought to be plenty, though some languages are pretty scary this -way: Hungarian, for example, has 18. We only require one case to exist, the -nominative, which is required to be case 0. -

- -

But this covers a pretty decent selection. Note that, as with the -persons above, the sequence corresponds to the defined constants in the -English Language extension, which we assume will be followed by other -languages. +

§5. 25 cases sounds like plenty, but some languages are pretty scary this +way: Hungarian has 18. We only require one case to exist, the nominative, +which is required to be case 0.

define MAX_GRAMMATICAL_CASES 25
@@ -126,18 +122,20 @@ tense 5 for the past historic.
 define HASBEEN_TENSE 2 	 Present perfect
 define HADBEEN_TENSE 3 	 Past perfect
 define WILLBE_TENSE 4 	 Future (not used in assertions or conditions)
+define CUSTOM1_TENSE 5
+define CUSTOM2_TENSE 6
 
-void Linguistics::log_tense_number(OUTPUT_STREAM, int t) {
+void InflectionDefns::log_tense_number(OUTPUT_STREAM, int t) {
     switch (t) {
-        case IS_TENSE: WRITE("IS_TENSE"); break;
-        case WAS_TENSE: WRITE("WAS_TENSE"); break;
+        case IS_TENSE:      WRITE("IS_TENSE"); break;
+        case WAS_TENSE:     WRITE("WAS_TENSE"); break;
         case HASBEEN_TENSE: WRITE("HASBEEN_TENSE"); break;
         case HADBEEN_TENSE: WRITE("HADBEEN_TENSE"); break;
-        case WILLBE_TENSE: WRITE("WILLBE_TENSE"); break;
-        case 5: WRITE("CUSTOM1_TENSE"); break;
-        case 6:  WRITE("CUSTOM2_TENSE"); break;
-        default: WRITE("<invalid-tense>"); break;
+        case WILLBE_TENSE:  WRITE("WILLBE_TENSE"); break;
+        case CUSTOM1_TENSE: WRITE("CUSTOM1_TENSE"); break;
+        case CUSTOM2_TENSE: WRITE("CUSTOM2_TENSE"); break;
+        default:            WRITE("<invalid-tense>"); break;
     }
 }
 
@@ -146,15 +144,19 @@ in its run.

-NATURAL_LANGUAGE_WORDS_TYPE *English_language = NULL;  until created, early in run
+NATURAL_LANGUAGE_WORDS_TYPE *default_language_for_linguistics = NULL;
 
-NATURAL_LANGUAGE_WORDS_TYPE *Linguistics::default_nl(NATURAL_LANGUAGE_WORDS_TYPE *nl) {
+void InflectionDefns::set_default_nl(NATURAL_LANGUAGE_WORDS_TYPE *nl) {
+    default_language_for_linguistics = nl;
+}
+
+NATURAL_LANGUAGE_WORDS_TYPE *InflectionDefns::default_nl(NATURAL_LANGUAGE_WORDS_TYPE *nl) {
     if (nl) return nl;
-    return English_language;
+    return default_language_for_linguistics;
 }
 
diff --git a/docs/inflections-module/2-tai.html b/docs/inflections-module/2-tai.html index 8b207d036..af156d4a7 100644 --- a/docs/inflections-module/2-tai.html +++ b/docs/inflections-module/2-tai.html @@ -83,7 +83,7 @@ the same as the original.

-int Inflections::suffix_inflection(OUTPUT_STREAM, match_avinue *T, text_stream *from) {
+int Inflections::suffix_inflection(OUTPUT_STREAM, match_avinue *T, text_stream *from) {
     wchar_t *result = Tries::search_avinue(T, from);
     return Inflections::follow_suffix_instruction(OUT, from, result);
 }
@@ -116,7 +116,7 @@ do more than simply fiddle with the final letters.
 

-word_assemblage Inflections::apply_trie_to_wa(word_assemblage wa, match_avinue *T) {
+word_assemblage Inflections::apply_trie_to_wa(word_assemblage wa, match_avinue *T) {
     vocabulary_entry **words;
     int no_words;
     WordAssemblages::as_array(&wa, &words, &no_words);
@@ -139,7 +139,7 @@ do more than simply fiddle with the final letters.
 }
 
diff --git a/docs/inflections-module/3-ai.html b/docs/inflections-module/3-ai.html index e8ac10588..3ba23f471 100644 --- a/docs/inflections-module/3-ai.html +++ b/docs/inflections-module/3-ai.html @@ -58,9 +58,7 @@

To inflect "a" into "an", and so forth.

-
- -

§1. The indefinite article trie. Here we take text such as "UNESCO document" and put an article in front, to +

§1. Here we take text such as "UNESCO document" and put an article in front, to get "a UNESCO document" (and not "an UNESCO document": these things are much trickier than they look).

@@ -68,20 +66,20 @@ trickier than they look).
 match_avinue *indef_trie = NULL;
 
-void ArticleInflection::preface_by_article(OUTPUT_STREAM, text_stream *initial_text,
-    NATURAL_LANGUAGE_WORDS_TYPE *nl) {
+void ArticleInflection::preface_by_article(OUTPUT_STREAM,
+    text_stream *initial_text, NATURAL_LANGUAGE_WORDS_TYPE *nl) {
     if (indef_trie == NULL)
         indef_trie =
             PreformUtilities::define_trie(
                 <singular-noun-to-its-indefinite-article>, TRIE_START,
-                Linguistics::default_nl(NULL));
+                InflectionDefns::default_nl(NULL));
     wchar_t *result = Tries::search_avinue(indef_trie, initial_text);
     if (result == NULL) result = L"a";
     WRITE("%w %S", result, initial_text);
 }
 
diff --git a/docs/inflections-module/3-dcl.html b/docs/inflections-module/3-dcl.html index bdb4c5e31..5338568ca 100644 --- a/docs/inflections-module/3-dcl.html +++ b/docs/inflections-module/3-dcl.html @@ -80,15 +80,15 @@ function togglePopup(material_id) {

§2.

-declension Declensions::decline(wording W, NATURAL_LANGUAGE_WORDS_TYPE *nl, int gen, int num) {
-    if (nl == NULL) nl = English_language;
+declension Declensions::decline(wording W, NATURAL_LANGUAGE_WORDS_TYPE *nl, int gen, int num) {
+    nl = InflectionDefns::default_nl(nl);
     declension D = Declensions::decline_inner(W, nl, gen, num, <noun-declension>);
     Fix the origin2.1;
     return D;
 }
 
 declension Declensions::decline_article(wording W, NATURAL_LANGUAGE_WORDS_TYPE *nl, int gen, int num) {
-    if (nl == NULL) nl = English_language;
+    nl = InflectionDefns::default_nl(nl);
     declension D = Declensions::decline_inner(W, nl, gen, num, <article-declension>);
     Fix the origin2.1;
     return D;
@@ -110,7 +110,7 @@ function togglePopup(material_id) {
 
 
 declension Declensions::decline_inner(wording W, NATURAL_LANGUAGE_WORDS_TYPE *nl, int gen, int num, nonterminal *nt) {
-    if (nl == NULL) nl = English_language;
+    nl = InflectionDefns::default_nl(nl);
     declension D;
     D.within_language = nl;
     for (production_list *pl = nt->first_pl; pl; pl = pl->next_pl) {
@@ -189,7 +189,7 @@ function togglePopup(material_id) {
     D.within_language = nl;
     TEMPORARY_TEXT(from);
     WRITE_TO(from, "%+W", W);
-    match_avinue *group_trie = PreformUtilities::define_trie(gnt, TRIE_END, Linguistics::default_nl(nl));
+    match_avinue *group_trie = PreformUtilities::define_trie(gnt, TRIE_END, InflectionDefns::default_nl(nl));
     wchar_t *result = Tries::search_avinue(group_trie, from);
     DISCARD_TEXT(from);
     if (result == NULL) {
@@ -248,7 +248,7 @@ function togglePopup(material_id) {
     return D;
 }
 
-wording Declensions::in_case(declension *D, int c) {
+wording Declensions::in_case(declension *D, int c) {
     if ((c < 0) || (c >= Declensions::no_cases(D->within_language))) internal_error("case out of range");
     return D->name_cased[c];
 }
@@ -293,7 +293,7 @@ function togglePopup(material_id) {
 }
 
diff --git a/docs/inflections-module/3-ga.html b/docs/inflections-module/3-ga.html index 214c296b7..cf8ef371c 100644 --- a/docs/inflections-module/3-ga.html +++ b/docs/inflections-module/3-ga.html @@ -59,9 +59,7 @@

To inflect adjectives into comparative and superlative forms.

-
- -

§1. Constructing comparatives. In English, the comparative of an adjective can generally be formed by +

§1. In English, the comparative of an adjective can generally be formed by suffixing the inflected form with "than"; thus, "big" to "bigger than". The following does the suffixing:

@@ -71,7 +69,8 @@ The following does the suffixing: ... than
-

§2.

+

§2. This is essentially a wrapper function for the trie <adjective-to-comparative>. +

 wording Grading::make_comparative(wording W, NATURAL_LANGUAGE_WORDS_TYPE *nl) {
@@ -81,9 +80,10 @@ The following does the suffixing:
         WRITE_TO(comprised, "some-long-text");
     else
         WRITE_TO(comprised, "%N", Wordings::first_wn(W));
-    if (nl == NULL) nl = English_language;
+    nl = InflectionDefns::default_nl(nl);
     match_avinue *comp_trie =
-        PreformUtilities::define_trie(<adjective-to-comparative>, TRIE_END, Linguistics::default_nl(nl));
+        PreformUtilities::define_trie(<adjective-to-comparative>, TRIE_END,
+            InflectionDefns::default_nl(nl));
     Inflections::suffix_inflection(transformed, comp_trie, comprised);
     wording PW = Feeds::feed_text(transformed);
     word_assemblage merged =
@@ -95,7 +95,11 @@ The following does the suffixing:
     DISCARD_TEXT(comprised);
     return PW;
 }
+
+

§3. This is essentially a wrapper function for the trie <adjective-to-superlative>. +

+
 wording Grading::make_superlative(wording W, NATURAL_LANGUAGE_WORDS_TYPE *nl) {
     TEMPORARY_TEXT(comprised);
     TEMPORARY_TEXT(transformed);
@@ -103,9 +107,10 @@ The following does the suffixing:
         WRITE_TO(comprised, "some-long-text");
     else
         WRITE_TO(comprised, "%N", Wordings::first_wn(W));
-    if (nl == NULL) nl = English_language;
+    nl = InflectionDefns::default_nl(nl);
     match_avinue *comp_trie =
-        PreformUtilities::define_trie(<adjective-to-superlative>, TRIE_END, Linguistics::default_nl(nl));
+        PreformUtilities::define_trie(<adjective-to-superlative>, TRIE_END,
+            InflectionDefns::default_nl(nl));
     Inflections::suffix_inflection(transformed, comp_trie, comprised);
     wording PW = Feeds::feed_text(transformed);
     LOGIF(CONSTRUCTED_PLURALS, "[Superlative of %W is %W]\n", W, PW);
@@ -114,10 +119,10 @@ The following does the suffixing:
     return PW;
 }
 
-

§3. There has to be a better term than "quiddity" for this grammatical construct, +

§4. This is essentially a wrapper function for the trie <adjective-to-quiddity>. +There has to be a better term than "quiddity" for this grammatical concept, but what I mean is the property for which the given adjective makes a -comparison: for instance, "tallness" for "tall", or "steeliness" for -"steely". +comparison: for instance, "tallness" for "tall", or "steeliness" for "steely".

@@ -128,9 +133,10 @@ comparison: for instance, "tallness" for "tall", or "steeliness" for
         WRITE_TO(comprised, "some-long-text");
     else
         WRITE_TO(comprised, "%N", Wordings::first_wn(W));
-    if (nl == NULL) nl = English_language;
+    nl = InflectionDefns::default_nl(nl);
     match_avinue *comp_trie =
-        PreformUtilities::define_trie(<adjective-to-quiddity>, TRIE_END, Linguistics::default_nl(nl));
+        PreformUtilities::define_trie(<adjective-to-quiddity>, TRIE_END,
+            InflectionDefns::default_nl(nl));
     Inflections::suffix_inflection(transformed, comp_trie, comprised);
     wording PW = Feeds::feed_text(transformed);
     LOGIF(CONSTRUCTED_PLURALS, "[Quiddity of %W is %W]\n", W, PW);
@@ -140,7 +146,7 @@ comparison: for instance, "tallness" for "tall", or "steeliness" for
 }
 
diff --git a/docs/inflections-module/2-nc.html b/docs/inflections-module/3-nc.html similarity index 75% rename from docs/inflections-module/2-nc.html rename to docs/inflections-module/3-nc.html index ee0349d10..78bd8a92d 100644 --- a/docs/inflections-module/2-nc.html +++ b/docs/inflections-module/3-nc.html @@ -63,10 +63,10 @@ function togglePopup(material_id) {
+

Name clusters are sets of noun or adjective forms, perhaps multiple or in multiple languages, which have in common that they share a meaning.

-
+

§1. Cluster. A cluster is a linked list of wordings, in effect, but they are annotated with lingistic roles. For example, the cluster of names for the common noun @@ -82,7 +82,7 @@ with lingistic roles. For example, the cluster of names for the common noun

 typedef struct name_cluster {
-    struct individual_name *first_name;
+    struct linked_list *listed;  of individual_name
     CLASS_DEFINITION
 } name_cluster;
 
@@ -91,8 +91,7 @@ with lingistic roles. For example, the cluster of names for the common noun
     struct declension name;  text of name
     int name_number;  1 for singular, 2 for plural
     int name_gender;  1 is neuter, 2 is masculine, 3 is feminine
-    NATURAL_LANGUAGE_WORDS_TYPE *name_language;  always non-null
-    struct individual_name *next;  within its cluster
+    NATURAL_LANGUAGE_WORDS_TYPE *name_language;
     CLASS_DEFINITION
 } individual_name;
 
@@ -103,7 +102,7 @@ with lingistic roles. For example, the cluster of names for the common noun
 name_cluster *Clusters::new(void) {
     name_cluster *names = CREATE(name_cluster);
-    names->first_name = NULL;
+    names->listed = NEW_LINKED_LIST(individual_name);
     return names;
 }
 
@@ -111,26 +110,28 @@ with lingistic roles. For example, the cluster of names for the common noun

-individual_name *Clusters::add(name_cluster *names, wording W,
-    NATURAL_LANGUAGE_WORDS_TYPE *nl, int gender, int number, int pluralise) {
-    if (nl == NULL) nl = English_language;
+individual_name *Clusters::add_one(name_cluster *names, wording W,
+    NATURAL_LANGUAGE_WORDS_TYPE *nl, int gender, int number) {
+    nl = InflectionDefns::default_nl(nl);
     individual_name *in = CREATE(individual_name);
     in->principal_meaning = NULL_GENERAL_POINTER;
     in->name = Declensions::decline(W, nl, gender, number);
     in->name_language = nl;
     in->name_number = number;
     in->name_gender = gender;
-    in->next = NULL;
-    if (names->first_name == NULL) names->first_name = in;
-    else {
-        individual_name *in2;
-        for (in2 = names->first_name; ((in2) && (in2->next)); in2 = in2->next) ;
-        in2->next = in;
-    }
-    if ((pluralise) && (number == 1))
-        Add plural names as well3.1;
+    ADD_TO_LINKED_LIST(in, individual_name, names->listed);
     return in;
 }
+
+linked_list *Clusters::add(name_cluster *names, wording W,
+    NATURAL_LANGUAGE_WORDS_TYPE *nl, int gender, int number, int pluralise) {
+    linked_list *L = NEW_LINKED_LIST(individual_name);
+    individual_name *in = Clusters::add_one(names, W, nl, gender, number);
+    ADD_TO_LINKED_LIST(in, individual_name, L);
+    if ((pluralise) && (number == 1))
+        Add plural names as well3.1;
+    return L;
+}
 

§3.1. The following makes all possible plurals and registers those too. (Note that every instance gets a plural name: even something palpably unique, like @@ -150,13 +151,13 @@ so there may be any number of names registered: for instance, the kind wording PW = EMPTY_WORDING; pde = Pluralisation::make(W, &PW, pde, nl); if (Wordings::nonempty(PW)) { - LOGIF(CONSTRUCTED_PLURALS, "(%d) Reading plural of <%W> as <%W>\n", k, - W, PW); - Clusters::add(names, PW, nl, gender, 2, FALSE); + LOGIF(CONSTRUCTED_PLURALS, "(%d) Plural of <%W>: <%W>\n", k, W, PW); + individual_name *in = Clusters::add_one(names, PW, nl, gender, 2); + ADD_TO_LINKED_LIST(in, individual_name, L); } } while (pde);

- +

§4. The following is more suited to adjectives, or to words which are used adjectivally, such as past participles in French. This time we generate all possible gender and number agreements — except in English, where no variation @@ -169,15 +170,14 @@ combinations. Here we only work through six, ignoring animation:

-void Clusters::add_with_agreements(name_cluster *cl, wording W, NATURAL_LANGUAGE_WORDS_TYPE *nl) {
-    if (nl == NULL) nl = English_language;
-    if (nl == English_language) {
-        Clusters::add(cl, W, nl, NEUTER_GENDER, 1, FALSE);
-    } else {
-        int gna;
-        for (gna = 0; gna < 6; gna++)
-            Generate agreement form in this GNA and add to the declension4.1;
-    }
+void Clusters::add_with_agreements(name_cluster *cl, wording W,
+    NATURAL_LANGUAGE_WORDS_TYPE *nl) {
+    nl = InflectionDefns::default_nl(nl);
+    if (nl == InflectionDefns::default_nl(NULL))
+        Clusters::add(cl, W, nl, NEUTER_GENDER, 1, FALSE);
+    else
+        for (int gna = 0; gna < 6; gna++)
+            Generate agreement form in this GNA and add to the declension4.1;
 }
 

§4.1. We use tries to modify the base text, which is taken to be the neuter @@ -206,10 +206,10 @@ singular form, into the other five forms. case 5: step1 = <adjective-to-plural>; break; } wording FW = EMPTY_WORDING; - Process via the agreement trie in this pipeline4.1.1; - Clusters::add(cl, FW, nl, form_gender, form_number, FALSE); + Process via the agreement trie in this pipeline4.1.1; + Clusters::add(cl, FW, nl, form_gender, form_number, FALSE);

- +

§4.1.1. Not much of a pipeline, really: we start with the base case and work through one or two tries.

@@ -221,13 +221,15 @@ through one or two tries. word_assemblage wa = WordAssemblages::from_wording(W); if (step1) wa = Inflections::apply_trie_to_wa(wa, - PreformUtilities::define_trie(step1, TRIE_END, Linguistics::default_nl(nl))); + PreformUtilities::define_trie(step1, TRIE_END, + InflectionDefns::default_nl(nl))); if (step2) wa = Inflections::apply_trie_to_wa(wa, - PreformUtilities::define_trie(step2, TRIE_END, Linguistics::default_nl(nl))); + PreformUtilities::define_trie(step2, TRIE_END, + InflectionDefns::default_nl(nl))); FW = WordAssemblages::to_wording(&wa); - +

§5. Plural fixing. Less elegantly, we can force the plural of a name in a cluster to a given fixed text, overwriting it if it's already there. In practice this is done only when the built-in kinds are being given plural names; some of these @@ -236,14 +238,15 @@ and wouldn't pass through the pluralising tries intact.

-void Clusters::set_plural_name(name_cluster *cl, wording W, NATURAL_LANGUAGE_WORDS_TYPE *nl) {
+void Clusters::set_plural_name(name_cluster *cl, wording W,
+    NATURAL_LANGUAGE_WORDS_TYPE *nl) {
     individual_name *in;
-    for (in = cl->first_name; in; in = in->next)
+    LOOP_OVER_LINKED_LIST(in, individual_name, cl->listed)
         if (in->name_number == 2) {
             in->name = Declensions::decline(W, nl, NEUTER_GENDER, 2);
             return;
         }
-    Clusters::add(cl, W, NULL, NEUTER_GENDER, 2, FALSE);
+    Clusters::add(cl, W, NULL, NEUTER_GENDER, 2, FALSE);
 }
 

§6. Searching declensions. These are always quite small, so there's no need for any efficient device @@ -255,11 +258,11 @@ or plural):

-wording Clusters::get_name(name_cluster *cl, int plural_flag) {
+wording Clusters::get_name(name_cluster *cl, int plural_flag) {
     int number_sought = 1;
     if (plural_flag) number_sought = 2;
     individual_name *in;
-    for (in = cl->first_name; in; in = in->next)
+    LOOP_OVER_LINKED_LIST(in, individual_name, cl->listed)
         if (in->name_number == number_sought)
             return Declensions::in_case(&(in->name), NOMINATIVE_CASE);
     return EMPTY_WORDING;
@@ -270,15 +273,16 @@ falling back on English if there's none registered:
 

-wording Clusters::get_name_in_play(name_cluster *cl, int plural_flag, NATURAL_LANGUAGE_WORDS_TYPE *nl) {
+wording Clusters::get_name_in_play(name_cluster *cl, int plural_flag,
+    NATURAL_LANGUAGE_WORDS_TYPE *nl) {
     int number_sought = 1;
     if (plural_flag) number_sought = 2;
     individual_name *in;
-    for (in = cl->first_name; in; in = in->next)
+    LOOP_OVER_LINKED_LIST(in, individual_name, cl->listed)
         if ((in->name_number == number_sought) &&
             (in->name_language == nl))
             return Declensions::in_case(&(in->name), NOMINATIVE_CASE);
-    return Clusters::get_name(cl, plural_flag);
+    return Clusters::get_name(cl, plural_flag);
 }
 

§8. A more specific search, which can optionally test for number and gender. @@ -288,7 +292,7 @@ falling back on English if there's none registered: wording Clusters::get_name_general(name_cluster *cl, NATURAL_LANGUAGE_WORDS_TYPE *nl, int number_sought, int gender_sought) { individual_name *in; - for (in = cl->first_name; in; in = in->next) + LOOP_OVER_LINKED_LIST(in, individual_name, cl->listed) if (((number_sought == -1) || (number_sought == in->name_number)) && ((gender_sought == -1) || (gender_sought == in->name_gender)) && (in->name_language == nl)) @@ -308,12 +312,14 @@ to an excerpt_meaning< } general_pointer Clusters::get_principal_meaning(name_cluster *cl) { - if (cl->first_name == NULL) return NULL_GENERAL_POINTER; - return cl->first_name->principal_meaning; + individual_name *in; + LOOP_OVER_LINKED_LIST(in, individual_name, cl->listed) + return in->principal_meaning; + return NULL_GENERAL_POINTER; }

diff --git a/docs/inflections-module/3-plr.html b/docs/inflections-module/3-plr.html index 3bfa5f849..c3e889614 100644 --- a/docs/inflections-module/3-plr.html +++ b/docs/inflections-module/3-plr.html @@ -108,9 +108,9 @@ one not found in the dictionary).

-plural_dictionary_entry *Pluralisation::make(wording W, wording *PW,
+plural_dictionary_entry *Pluralisation::make(wording W, wording *PW,
     plural_dictionary_entry *search_from, NATURAL_LANGUAGE_WORDS_TYPE *nl) {
-    if (nl == NULL) nl = English_language;
+    nl = InflectionDefns::default_nl(nl);
 
     plural_dictionary_entry *pde;
 
@@ -169,14 +169,15 @@ has a plural, and modifies it to the plural form.
 
 
 int Pluralisation::regular(OUTPUT_STREAM, text_stream *from, NATURAL_LANGUAGE_WORDS_TYPE *nl) {
-    if (nl == NULL) nl = English_language;
+    nl = InflectionDefns::default_nl(nl);
     match_avinue *plural_trie =
-        PreformUtilities::define_trie(<singular-noun-to-its-plural>, TRIE_END, Linguistics::default_nl(nl));
+        PreformUtilities::define_trie(<singular-noun-to-its-plural>, TRIE_END,
+            InflectionDefns::default_nl(nl));
     return Inflections::suffix_inflection(OUT, plural_trie, from);
 }
 
diff --git a/docs/inflections-module/3-pp.html b/docs/inflections-module/3-pp.html index 6372a3661..b0290f4af 100644 --- a/docs/inflections-module/3-pp.html +++ b/docs/inflections-module/3-pp.html @@ -104,12 +104,13 @@ above. It expects only a single word.
 int PastParticiples::pasturise_text(OUTPUT_STREAM, text_stream *from) {
     match_avinue *past_trie =
-        PreformUtilities::define_trie(<pasturise-participle>, TRIE_START, Linguistics::default_nl(NULL));
+        PreformUtilities::define_trie(<pasturise-participle>, TRIE_START,
+            InflectionDefns::default_nl(NULL));
     return Inflections::suffix_inflection(OUT, past_trie, from);
 }
 
diff --git a/docs/inflections-module/3-vc.html b/docs/inflections-module/3-vc.html index de7e31a7b..46cb2a39b 100644 --- a/docs/inflections-module/3-vc.html +++ b/docs/inflections-module/3-vc.html @@ -125,7 +125,7 @@ conjugation to another. verb_conjugation *Conjugation::conjugate_with_overrides(word_assemblage base_text, word_assemblage *overrides, int no_overrides, NATURAL_LANGUAGE_WORDS_TYPE *nl) { - if (nl == NULL) nl = English_language; + nl = InflectionDefns::default_nl(nl); if (WordAssemblages::nonempty(base_text) == FALSE) internal_error("No base text for verb conjugation"); @@ -516,7 +516,7 @@ example: verb_forms[n] = Inflections::apply_trie_to_wa( verb_forms[BASE_FORM_TYPE], - PreformUtilities::define_trie(content_token->nt_pt, TRIE_END, Linguistics::default_nl(nl))); + PreformUtilities::define_trie(content_token->nt_pt, TRIE_END, InflectionDefns::default_nl(nl))); else if (content_token->ptoken_category == FIXED_WORD_PTC) verb_forms[n] = Conjugation::expand_with_endings(content_token->ve_pt, verb_forms); @@ -996,7 +996,7 @@ from our dictionary of 14,000 or so present and past participles.
 void Conjugation::test_participle(OUTPUT_STREAM, wording W) {
     verb_conjugation *vc = Conjugation::conjugate(
-        WordAssemblages::from_wording(W), English_language);
+        WordAssemblages::from_wording(W), InflectionDefns::default_nl(NULL));
     if (vc == NULL) { WRITE("Failed test\n"); return; }
     Conjugation::write_participle(OUT, vc);
     DESTROY(vc, verb_conjugation);
@@ -1022,7 +1022,7 @@ as markers in verb conjugations.
 
diff --git a/docs/inflections-module/4-ei.html b/docs/inflections-module/4-ei.html index 345d6211b..ea5e68b7b 100644 --- a/docs/inflections-module/4-ei.html +++ b/docs/inflections-module/4-ei.html @@ -59,76 +59,9 @@

To define how English nouns and verbs are inflected.

-
+
-

§1. Preface. Inflections are modifications of words — usually word endings or beginnings — -for different circumstances. English is often called an uninflected language, -but this is an exaggeration. For example, we spell the word "tree" as -"trees" if it refers to more than one of them. Inform sometimes needs -to take text in one form and change it to another — for example, to turn -a singular noun into a plural one — and ordinary Preform parsing isn't good -enough to express this. -

- -

Inform uses a data structure called a "trie" as an efficient way to match -prefix and/or suffix patterns in words, and then to modify them. These tries -are created using the same notation as for Preform grammar, which is -convenient in many ways, but also a little misleading — they are parsed quite -differently. The rules are as follows: -

- - -

lead gold turns "lead" into "gold" -

- -

codex codices turns "codex" to "codices" -

- -

*mouse 5mice turns "mouse" to "mice", or "fieldmouse" to "fieldmice" -

- -

Designing a trie is not quite as easy as it looks. It looks as if this is a -sequence of tests to perform in succession, but it's better to think of the -rules all being performed at once. In general, if you need one inflection -rule to take precedence over another, put it in an earlier trie, rather than -putting it earlier in the same trie. -

- -

§2. Tries are highly language specific and should not be translated as such: -instead, an appropriate version needs to be written for every language. -

- -

Except at the very top level, translators are free to created new tries -and name them as they please. For example, the Spanish implementation of -

- -
-    <singular-noun-to-its-indefinite-article>
-
-

may look entirely unlike its English version, but at the top level it still -has to have that name. -

- -

Lower-level tries used in the implementation should have names beginning -with a language code: hence the names "en-" used below. -

- -

§3. Noun inflections. The following trie looks at the start of a word, which we assume to be a +

§1. Noun inflections. The following trie looks at the start of a word, which we assume to be a noun, and decides whether to use the indefinite article "a" or "an". This is much more complicated than simply looking for a vowel as the first letter, as people often think until they try a few cases. @@ -145,7 +78,7 @@ dictionary and the "Official Scrabble Wordlist". <en-trie-indef-c>

-

§4. Exceptions to the exceptions: +

§2. Exceptions to the exceptions:

@@ -158,7 +91,7 @@ dictionary and the "Official Scrabble Wordlist".
     uvarovite*		an 			 a rare emerald-green garnet, Ca3Cr2(SiO4)3
 
-

§5. Then the exceptions: +

§3. Then the exceptions:

@@ -228,7 +161,7 @@ dictionary and the "Official Scrabble Wordlist".
     uvu*			a
 
-

§6. And finally the basic rules: +

§4. And finally the basic rules:

@@ -288,7 +221,7 @@ dictionary and the "Official Scrabble Wordlist".
     yw*				an
 
-

§7. Plural inflections. The following takes a single word, assumes it to be a noun which meaningfully +

§5. Plural inflections. The following takes a single word, assumes it to be a noun which meaningfully has a plural, and modifies it to the plural form. ("Golf" is a noun which doesn't sensibly have a plural; the algorithm here would return "golves".)

@@ -334,7 +267,7 @@ of a sibilant plus "o" suffix to include an "e", so that Conway produces ... <en-trie-plural-append-s> -

§8. See Conway's table A.2. The following nouns, mostly names of kinds of animal, +

§6. See Conway's table A.2. The following nouns, mostly names of kinds of animal, have the same plural as singular form: for example, chamois, salmon, goldfish.

@@ -392,7 +325,7 @@ have the same plural as singular form: for example, chamois, salmon, goldfish. pincers 0 -

§9. We may as well pluralise pronouns while we're at it. +

§7. We may as well pluralise pronouns while we're at it.

@@ -421,7 +354,7 @@ have the same plural as singular form: for example, chamois, salmon, goldfish.
     oneself			oneselves
 
-

§10. We now reach Conway step 4. These are irregular plurals mostly coming +

§8. We now reach Conway step 4. These are irregular plurals mostly coming from archaisms.

@@ -442,7 +375,7 @@ from archaisms. trilby trilbys -

§11. Step 5. Now we reach a batch of irregular but fairly general inflected +

§9. Step 5. Now we reach a batch of irregular but fairly general inflected endings; for example, protozoon to protozoa, or metamorphosis to metamorphoses. Note that we differ from Conway in pluralizing blouse as blouses, not blice.

@@ -462,7 +395,7 @@ Note that we differ from Conway in pluralizing blouse as blouses, not blice. *xis 3xes -

§12. Step 6. These are inflections from Latin and Greek which have survived +

§10. Step 6. These are inflections from Latin and Greek which have survived into modern English:

@@ -494,7 +427,7 @@ into modern English: ovum ova -

§13. Step 11a. (We're not implementing Conway's steps in sequence: see below.) +

§11. Step 11a. (We're not implementing Conway's steps in sequence: see below.) These -o endings are mostly loan words from Romance languages whose original inflections are assimilated.

@@ -535,7 +468,7 @@ inflections are assimilated. tempo tempos -

§14. Conway steps 8 to 11. These are regular inflections depending only on +

§12. Conway steps 8 to 11. These are regular inflections depending only on word endings.

@@ -621,7 +554,7 @@ word endings. *zo 0s -

§15. Lastly, the fallback if none of the above cases match: append an -s, of +

§13. Lastly, the fallback if none of the above cases match: append an -s, of course.

@@ -630,7 +563,7 @@ course. * 0s Step 13 -

§16. Verb inflections. "Le verbe est l'âme d'une langue" (attributed to Georges Duhamel). And the +

§14. Verb inflections. "Le verbe est l'âme d'une langue" (attributed to Georges Duhamel). And the care of the soul is, of course, complicated. For example, the source text can say something like this:

@@ -666,7 +599,7 @@ of the possibilities we need to make, and write a trie to handle each one. is, how the different word forms map onto the possible tenses, persons, numbers, and so on. -

§17. This gives us a certain amount of choice. What exactly is "too irregular"? +

§15. This gives us a certain amount of choice. What exactly is "too irregular"? In French, are all -er, -ir, and -re verbs "regular"? (Consider "aller", for example.) In English, it's possible to say that there are seven or so classes of verbs, all regular by their own standards; but most people say @@ -701,7 +634,7 @@ example, to set has just three distinct forms — to set, he sets, he set, h had set, setting.

-

§18. Form types are numbered from 0 up to, potentially, a constant +

§16. Form types are numbered from 0 up to, potentially, a constant called MAX_FORM_TYPES. (This is so large that there shouldn't ever be need for more.) Form type 0 is always the original text, and is used as the basis from which the others are generated. For English verbs Inform always sets form @@ -728,7 +661,7 @@ each language. English needs two: the present (5) and past (6) forms. define ADJOINT_INFINITIVE_FORM_TYPE 4 define MAX_FORM_TYPES 123 -

§19. We're now ready to write the <verb-conjugation-instructions>. This is +

§17. We're now ready to write the <verb-conjugation-instructions>. This is a block which looks at the infinitive of the verb and decides which of several conjugations should be used. Badly irregular verbs get conjugations of their own, and others are grouped together. In French, @@ -754,7 +687,7 @@ least one line, and the best way to ensure that is to finish up with -

§20. The instructions for English are quite concise, except for the presence +

§18. The instructions for English are quite concise, except for the presence of the awkward contracted informal forms of verbs. (These aren't used in Inform assertion sentences, but are needed for text substitutions.)

@@ -788,7 +721,7 @@ Inform assertion sentences, but are needed for text substitutions.) ... <regular-verb-conjugation> -

§21. We will start with two auxiliary verbs, that is, verbs used to construct +

§19. We will start with two auxiliary verbs, that is, verbs used to construct forms of other verbs. The first is "to have"; as we'll see, English uses this to construct perfect tenses:

@@ -851,7 +784,7 @@ for "[have]". <to-have-tabulation> -

§22. Tabulations give instructions for how to construct 120 possible versions +

§20. Tabulations give instructions for how to construct 120 possible versions of the verb. These are divided up first into active and passive "moods":

@@ -990,7 +923,7 @@ are used for the six persons. a2- had not -

§23. And this is an example of splitting into cases for the six persons, +

§21. And this is an example of splitting into cases for the six persons, 1PS, 2PS, 3PS, 1PP, 2PP, 3PP. I have, you have, he has, we have, you have, they have. (This is more excitingly varied in other languages, of course.)

@@ -1000,7 +933,7 @@ they have. (This is more excitingly varied in other languages, of course.) have | have | has | have | have | have -

§24. Next we have "to do", which is like "to have" in being fairly regular, +

§22. Next we have "to do", which is like "to have" in being fairly regular, as irregular verbs go. But we treat this as a special case because, again, we're going to need as an auxiliary verb when forming negatives ("Peter does not wear the hat" — note the "does not"). But this time we give @@ -1066,7 +999,7 @@ may have to revisit this for languages other than English.) do | do | does | do | do | do

-

§25. Regular English verbs, then, look like so. We will, for the first time, +

§23. Regular English verbs, then, look like so. We will, for the first time, make heavy use of our numbered verb forms: for example, for the verb "to take", they would be "take" (1), "taking" (2), "taken" (3), "takes" (5) and "took" (6). We start with the infinitive ("take") @@ -1098,7 +1031,7 @@ to "grabs onto", "grabbing onto" and so on. <regular-verb-tabulation>

-

§26. Here we see our auxiliary verbs in use. For the negated present tense, +

§24. Here we see our auxiliary verbs in use. For the negated present tense, "Peter does not carry the ball"; for the negated past tense, "Peter did not carry the ball" — in both cases, this is "to do" plus the infinitive "take". For the perfect tenses, "to have" plus the past participle — @@ -1122,7 +1055,7 @@ a bequest".) p* 3 by

-

§27. This looks odd, but what it says is that the present tense of a regular +

§25. This looks odd, but what it says is that the present tense of a regular English verb is always the infinitive (I take, you take, we take, and so on) except for third person singular (he takes), which is different. (It's usually what the plural of the infinitive would be if the infinitive were a noun, @@ -1134,7 +1067,7 @@ as we'll see.) 1 | 1 | 5 | 1 | 1 | 1

-

§28. Now for our most irregular verb: "to be". +

§26. Now for our most irregular verb: "to be".

@@ -1160,7 +1093,7 @@ as we'll see.)
     was | were | was | were | were | were
 
-

§29. Except for tense formation (Peter "will" take the ball), the most common +

§27. Except for tense formation (Peter "will" take the ball), the most common modal verb which can be used in Inform source text is "can". For example:

@@ -1199,7 +1132,7 @@ to elide, so we always pronounce it that way and the spelling now follows. a5- will not be able to ++1 -

§30. Inform has only a simple understanding of what "can" means, so it doesn't +

§28. Inform has only a simple understanding of what "can" means, so it doesn't allow the source text to use "can" in combination with arbitrary verbs. Instead, each legal combination has to be declared explicitly:

@@ -1242,7 +1175,7 @@ Jane". p ( be able to ) be 3 ( 4 ) by -

§31. The following handles the other English modal verbs ("might", "should" +

§29. The following handles the other English modal verbs ("might", "should" and so on) surprisingly easily. The notation ++1 means that the verb being modified should appear in verb form 1, and so on: for example, "might not lead" as "might not" plus form 1 of "to lead", i.e., "lead". @@ -1267,7 +1200,7 @@ being modified should appear in verb form 1, and so on: for example, a5- 4 not ++1

-

§32. That completes our basic kit of verbs nicely. What's left is used only +

§30. That completes our basic kit of verbs nicely. What's left is used only for generating text at run-time — for printing adaptive messages, that is; none of these oddball exceptional cases is otherwise used as a verb in Inform source text. None of them has any meaning to Inform. @@ -1329,7 +1262,7 @@ dialects — and we aren't even going to try to cope with that. wasn't | weren't | wasn't | weren't | weren't | weren't

-

§33. And now "to 've", the contracted form of "to have". A subtle dialect +

§31. And now "to 've", the contracted form of "to have". A subtle dialect point here concerns the negated present tense:

@@ -1380,7 +1313,7 @@ go with those. 've | 've | 's | 've | 've | 've -

§34. Now we come to "aren't", a negated form of "to be", but where the +

§32. Now we come to "aren't", a negated form of "to be", but where the contraction occurs between the verb and the "not" rather than between the subject and the verb.

@@ -1418,7 +1351,7 @@ that option here.) haven't been | haven't been | hasn't been | haven't been | haven't been | haven't been -

§35. And finally: the contracted informal negatives of various modal verbs which +

§33. And finally: the contracted informal negatives of various modal verbs which it's useful to be able to print, like the "can't" in

@@ -1451,7 +1384,7 @@ of "modal" itself arguable. This is the best we can do. 1 | 1 | 7 | 1 | 1 | 1 -

§36. Together with special rules for can't, which is inevitably slightly different: +

§34. Together with special rules for can't, which is inevitably slightly different:

@@ -1469,7 +1402,7 @@ of "modal" itself arguable. This is the best we can do.
     a5+		won't be able to ++1
 
-

§37. We have special tries just to list the forms of the cases we will +

§35. We have special tries just to list the forms of the cases we will deal with. Tries can do fancy things (see below), but here they act just as a look-up table: for example, "won't" has present "won't", past "wouldn't" and future "won't". @@ -1517,7 +1450,7 @@ signs can be used if we absolutely have to introduce spaces. shouldn't shouldn't

-

§38. That's the end of the conjugations — the easy part, it turns out. We now +

§36. That's the end of the conjugations — the easy part, it turns out. We now need to create the four tries to make verb forms out of the infinitive: the present participle, the past participle, the third-person singular present tense, and the past tense. @@ -1560,7 +1493,7 @@ no easy way to tell. Consider deter to deterring (stress on second syllable of deter), but meter to metering (stress on first syllable of meter).

-

§39. The following algorithm is due to Toby Nelson, who produced it from a +

§37. The following algorithm is due to Toby Nelson, who produced it from a dictionary of 14,689 English verbs, some of them quite obscure (to torpefy, anyone? to spuilzie? to cachinnate?). It's essentially a more detailed version of Greenbaum's rules above. @@ -1575,7 +1508,7 @@ version of Greenbaum's rules above. ... <en-trie-regular-c-present-participle>

-

§40. First of all there are some irregular cases — some for the usual suspects, +

§38. First of all there are some irregular cases — some for the usual suspects, but others for oddball verbs where English breaks the normal phonetic rules for the sake of clarity. For example, the participle of "singe" ought to be "singing", but in fact we write "singeing", purely to make it different @@ -1771,7 +1704,7 @@ from the act of producing a song. undersaye 1ing

-

§41. Now some exceptional forms where consonant doubling doesn't occur: +

§39. Now some exceptional forms where consonant doubling doesn't occur:

@@ -1792,7 +1725,7 @@ from the act of producing a song.
     *daub     0ing        daubing, bedaubing
 
-

§42. And now rules for consonant doubling: +

§40. And now rules for consonant doubling:

@@ -1844,7 +1777,7 @@ from the act of producing a song.
     *iz                    0zing
 
-

§43. Finally: +

§41. Finally:

@@ -1858,7 +1791,7 @@ from the act of producing a song.
     *            0ing
 
-

§44. Next the past participle. As noted above, for most verbs this is the same +

§42. Next the past participle. As noted above, for most verbs this is the same as the past (e.g., he agreed and it was agreed); but there's a list of exceptions for Anglo-Saxon survivals (e.g., he chose and it was chosen). The exceptional cases were derived from Wikipedia's catalogue of irregular @@ -2025,7 +1958,7 @@ removed. write written

-

§45. That's the mandatory participles sorted out; so now we move on to the two +

§43. That's the mandatory participles sorted out; so now we move on to the two additional verb forms used by English. First, the present form: a curiosity of English is that this is almost always formed as if it were the plural of the infinitive — thus "touch" becomes "touches". There are just a handful @@ -2043,7 +1976,7 @@ of exceptions to this. do does

-

§46. Second, the past. This is harder. Once again we have a catalogue of +

§44. Second, the past. This is harder. Once again we have a catalogue of Anglo-Saxon past forms (e.g., he chose, not he chooses); and after those are out of the way, the rules are the same as for the present participle, except for adding -ed instead of -ing. The tricky part, again, is spotting @@ -2676,7 +2609,7 @@ when to double the consonant, which again depends on stress. * 0ed

-

§47. Present to past participles. Sentences like +

§45. Present to past participles. Sentences like

@@ -3185,7 +3118,7 @@ cases followed by two general rules. *ing 3ed e.g., "smashing" to "smashed" -

§48. Adjective agreements. English doesn't inflect adjectives at all (let's not argue about "blond" +

§46. Adjective agreements. English doesn't inflect adjectives at all (let's not argue about "blond" and "blonde"), so the following are just stubs.

@@ -3206,7 +3139,7 @@ and "blonde"), so the following are just stubs. * 0 -

§49. Grading of adjectives is more interesting. These spelling rules are taken +

§47. Grading of adjectives is more interesting. These spelling rules are taken from the Oxford English Grammar at 4.24, "Gradability and comparison". Something we can't easily implement is that a final vowel plus consonant doesn't result in doubling the consonant (in the way that "big" becomes @@ -3238,7 +3171,7 @@ rare in English adjectives. * 0est

-

§50. To the best of my knowledge there's no technical term for "the noun which +

§48. To the best of my knowledge there's no technical term for "the noun which is formed from an adjective to refer to the quality it measures", so the Inform source code calls this the "quiddity". English permits several competing forms of these to be constructed, depending on the adjective's @@ -3258,7 +3191,7 @@ sometimes less elegant, but never means the wrong thing. * 0ness

-

§51. English has almost no noun cases at all, with the only exceptions being +

§49. English has almost no noun cases at all, with the only exceptions being Anglo-Saxon pronouns (thus we distinguish "they" and "them" as nominative and accusative, for example); and pronouns we handle separately in any case. We won't bother to distinguish gender: @@ -3272,7 +3205,7 @@ case. We won't bother to distinguish gender: * <en-noun-declension-group> <en-noun-declension-tables>

-

§52. And the sorting into groups sorts everything into "group 1", the only group: +

§50. And the sorting into groups sorts everything into "group 1", the only group:

@@ -3283,7 +3216,7 @@ case. We won't bother to distinguish gender:
     <en-noun-declension-uninflected>
 
-

§53. And in this single group, nominative and accusative forms are identical +

§51. And in this single group, nominative and accusative forms are identical to the stem in both singular and plural.

@@ -3293,7 +3226,7 @@ to the stem in both singular and plural. 0 | 0 -

§54. English articles only inflect slightly, to show indefinite plurals; they +

§52. English articles only inflect slightly, to show indefinite plurals; they don't distinguish nominative from accusative.

@@ -3309,7 +3242,7 @@ don't distinguish nominative from accusative. diff --git a/docs/inflections-module/P-htitm.html b/docs/inflections-module/P-htitm.html new file mode 100644 index 000000000..bb11226f3 --- /dev/null +++ b/docs/inflections-module/P-htitm.html @@ -0,0 +1,99 @@ + + + + How To Include This Module + + + + + + + + + + + + + + + +
+ + +

What to do to make use of the inflections module in a new command-line tool.

+ +
+ +

§1. Status. The inflections module is provided as one of the "services" suite of modules, +which means that it was built with a view to potential incorporation in +multiple tools. It can be found, for example, in inform7 and +inflections-test. +

+ +

By convention, the modules considered as "services" have no dependencies on +other modules except for foundation and other "services" modules. +

+ +

A tool can import inflections only if it also imports foundation, +words and syntax. +

+ +

§2. Importing the module. We'll use the term "parent" to mean the tool which is importing inflections, +that is, which will include its code and be able to use it. As with any +imported module, +

+ + +
+Import: somepath/inflections
+
+ + + +
+ + + diff --git a/docs/inflections-module/P-wtmd.html b/docs/inflections-module/P-wtmd.html new file mode 100644 index 000000000..d598881f7 --- /dev/null +++ b/docs/inflections-module/P-wtmd.html @@ -0,0 +1,191 @@ + + + + What This Module Does + + + + + + + + + + + + + + + + +
+ + +

An overview of the inflections module's role and abilities.

+ +
+ +

§1. Prerequisites. The inflections module is a part of the Inform compiler toolset. It is +presented as a literate program or "web". Before diving in: +

+ + +

§2. Inflections. Inflections are modifications of words — usually word endings or beginnings — +for different circumstances. English is often called an uninflected language, +but this is an exaggeration. For example, we spell the word "tree" as +"trees" when we refer to more than one of them. Inform sometimes needs +to take text in one form and change it to another — for example, to turn +a singular noun into a plural one — and ordinary Preform parsing isn't good +enough to express this. +

+ +

Inform uses a data structure called a "trie" as an efficient way to match +prefix and/or suffix patterns in words, and then to modify them. +

+ +

Tries are provided as basic data structures by Tries and Avinues (in foundation), +and the code for initialising them from Preform grammar is provided by +Preform Utilities (in words). +

+ +

§3. Though tries are, as just mentioned, created from Preform grammar, they're +parsed quite differently. The rules are as follows: +

+ + +
+    <fiddle-with-words> ::=
+        <fiddle-with-exceptions> |
+        ... <fiddle-with-irregular-endings> |
+        ... <fiddle-with-regular-endings>
+
+

means try <fiddle-with-exceptions> first (on the whole word), then +<fiddle-with-irregular-endings> (on the tail), and finally <fiddle-with-regular-endings> +(also on the tail). +

+ + +
+    <pluralise> ::=
+        lead lead |
+        codex codices |
+        *mouse 5mice
+
+

This would pluralise "lead" as "lead", "codex" as "codices", "mouse" as "mice", +and "fieldmouse" as "fieldmice". +

+ +

Designing a trie is not quite as easy as it looks. It looks as if this is a +sequence of tests to perform in succession, but it's better to think of the +rules all being performed at once. In general, if you need one inflection +rule to take precedence over another, put it in an earlier trie, rather than +putting it earlier in the same trie. +

+ +

For the implementation of these rules, see Tries and Inflections. +

+ +

§4. Once we have that general inflection machinery, most of what we need to +do becomes a simple matter of writing wrapper functions for tries. +

+ + +

§5. Tries are highly language specific and should not be translated as such: +instead, an appropriate version needs to be written for every language. +The tries for English are in English Inflections. +

+ +

Except at the very top level, translators are free to created new tries +and name them as they please. For example, the Spanish implementation of +

+ +
+    <singular-noun-to-its-indefinite-article>
+
+

may look entirely unlike its English version, but at the top level it still +has to have that name. +

+ +

Lower-level tries used in the implementation should have names beginning +with a language code: hence the names "en-" used in English Inflections. +

+ + + +
+ + + diff --git a/docs/inflections-module/index.html b/docs/inflections-module/index.html index f59213d73..6e0ade6e8 100644 --- a/docs/inflections-module/index.html +++ b/docs/inflections-module/index.html @@ -56,6 +56,22 @@
  • @@ -102,6 +113,11 @@ Declensions - Declensions are sets of inflected variations of a common stem according to grammatical case.

  • +
  • +

    + Name Clusters - + Name clusters are sets of noun or adjective forms, perhaps multiple or in multiple languages, which have in common that they share a meaning.

    +
  • Pluralisation - diff --git a/docs/inflections-test/1-ut.html b/docs/inflections-test/1-ut.html index 8486aaebd..899bdd9bb 100644 --- a/docs/inflections-test/1-ut.html +++ b/docs/inflections-test/1-ut.html @@ -65,9 +65,9 @@ function togglePopup(material_id) { if (Lexer::word(i) == PARBREAK_V) continue; wording W = Wordings::one_word(i); PRINT("%W --> ", W); - PRINT("comparative: %W, ", Grading::make_comparative(W, English_language)); - PRINT("superlative: %W, ", Grading::make_superlative(W, English_language)); - PRINT("quiddity: %W\n", Grading::make_quiddity(W, English_language)); + PRINT("comparative: %W, ", Grading::make_comparative(W, InflectionDefns::default_nl(NULL))); + PRINT("superlative: %W, ", Grading::make_superlative(W, InflectionDefns::default_nl(NULL))); + PRINT("quiddity: %W\n", Grading::make_quiddity(W, InflectionDefns::default_nl(NULL))); } } } @@ -86,7 +86,7 @@ function togglePopup(material_id) { TEMPORARY_TEXT(T); WRITE_TO(T, "%W", W); TEMPORARY_TEXT(AT); - ArticleInflection::preface_by_article(AT, T, English_language); + ArticleInflection::preface_by_article(AT, T, InflectionDefns::default_nl(NULL)); PRINT("%S --> %S\n", T, AT); DISCARD_TEXT(AT); DISCARD_TEXT(T); @@ -113,12 +113,12 @@ function togglePopup(material_id) { if (Lexer::word(i) == f_V) { gen = FEMININE_GENDER; continue; } if (Lexer::word(i) == n_V) { gen = NEUTER_GENDER; continue; } wording W = Wordings::one_word(i); - declension D = Declensions::decline(W, English_language, gen, 1); - declension AD = Declensions::decline_article(PW, English_language, gen, 1); + declension D = Declensions::decline(W, InflectionDefns::default_nl(NULL), gen, 1); + declension AD = Declensions::decline_article(PW, InflectionDefns::default_nl(NULL), gen, 1); PRINT("%W --> ", W); Declensions::writer(STDOUT, &D, &AD); - D = Declensions::decline(W, English_language, gen, 2); - AD = Declensions::decline_article(PW, English_language, gen, 2); + D = Declensions::decline(W, InflectionDefns::default_nl(NULL), gen, 2); + AD = Declensions::decline_article(PW, InflectionDefns::default_nl(NULL), gen, 2); PRINT("pl --> "); Declensions::writer(STDOUT, &D, &AD); PRINT("\n"); @@ -157,7 +157,7 @@ function togglePopup(material_id) { TEMPORARY_TEXT(G); WRITE_TO(G, "%W", W); TEMPORARY_TEXT(ASAGIG); - Pluralisation::regular(ASAGIG, G, English_language); + Pluralisation::regular(ASAGIG, G, InflectionDefns::default_nl(NULL)); PRINT("%S --> %S\n", G, ASAGIG); DISCARD_TEXT(ASAGIG); DISCARD_TEXT(G); @@ -180,7 +180,7 @@ function togglePopup(material_id) { if (c++ < 10) { PRINT("Verb %W -->\n", W); TEMPORARY_TEXT(T); - Conjugation::test(T, W, English_language); + Conjugation::test(T, W, InflectionDefns::default_nl(NULL)); Regexp::replace(T, L"%^", L"\n", REP_REPEATING); PRINT("%S\n", T); DISCARD_TEXT(T); diff --git a/docs/kinds-module/2-dk.html b/docs/kinds-module/2-dk.html index 61180e170..4a1858c06 100644 --- a/docs/kinds-module/2-dk.html +++ b/docs/kinds-module/2-dk.html @@ -599,7 +599,7 @@ so on. For example: void Kinds::Textual::write_articled(OUTPUT_STREAM, kind *K) { TEMPORARY_TEXT(TEMP); Kinds::Textual::write_inner(TEMP, K, FALSE, TRUE); - ArticleInflection::preface_by_article(OUT, TEMP, English_language); + ArticleInflection::preface_by_article(OUT, TEMP, InflectionDefns::default_nl(NULL)); DISCARD_TEXT(TEMP); } diff --git a/docs/linguistics-module/3-nns.html b/docs/linguistics-module/3-nns.html index b345dd9ad..940b8a448 100644 --- a/docs/linguistics-module/3-nns.html +++ b/docs/linguistics-module/3-nns.html @@ -184,9 +184,10 @@ we add a new one.

     individual_name *Nouns::add_to_noun_and_reg(noun *t,
         wording W, NATURAL_LANGUAGE_WORDS_TYPE *foreign_language, int gender, int number, int options) {
    -    individual_name *in = Clusters::add(t->names, W, foreign_language, gender, number,
    +    linked_list *L = Clusters::add(t->names, W, foreign_language, gender, number,
             (options & REGISTER_PLURAL_NTOPT)?TRUE:FALSE);
    -    for (; in; in = in->next)
    +    individual_name *in;
    +    LOOP_OVER_LINKED_LIST(in, individual_name, L)
             if ((options & REGISTER_SINGULAR_NTOPT) && (t->registration_category != NOUN_HAS_NO_MC)) {
                 excerpt_meaning *em = ExcerptMeanings::register(
                     t->registration_category,
    diff --git a/docs/linguistics-module/4-apoo.html b/docs/linguistics-module/4-apoo.html
    index 1dd1937b4..a8ff0b6ba 100644
    --- a/docs/linguistics-module/4-apoo.html
    +++ b/docs/linguistics-module/4-apoo.html
    @@ -139,7 +139,7 @@ time".
             default: WRITE(": <invalid-units>"); break;
         }
         if (tp->tense != IS_TENSE) {
    -        WRITE(": "); Linguistics::log_tense_number(OUT, tp->tense);
    +        WRITE(": "); InflectionDefns::log_tense_number(OUT, tp->tense);
         }
         WRITE(">");
     }
    diff --git a/docs/linguistics-module/4-vu.html b/docs/linguistics-module/4-vu.html
    index 32cddc775..3f8742287 100644
    --- a/docs/linguistics-module/4-vu.html
    +++ b/docs/linguistics-module/4-vu.html
    @@ -449,7 +449,7 @@ list, with lower priority numbers before higher ones.
     int VerbUsages::is_foreign(verb_usage *vu) {
         if ((vu->verb_used) &&
             (vu->verb_used->conjugation->defined_in) &&
    -        (vu->verb_used->conjugation->defined_in != English_language)) {
    +        (vu->verb_used->conjugation->defined_in != InflectionDefns::default_nl(NULL))) {
             return TRUE;
         }
         return FALSE;
    diff --git a/docs/linguistics-test/1-ut.html b/docs/linguistics-test/1-ut.html
    index cd5ed0796..9f9914111 100644
    --- a/docs/linguistics-test/1-ut.html
    +++ b/docs/linguistics-test/1-ut.html
    @@ -115,7 +115,7 @@ any text but then fail.
     
     
     <stock> ::=
    -    verb <cardinal-number> ...	==> R[1]; *XP = Conjugation::conjugate(WordAssemblages::from_wording(FW[1]), English_language);
    +    verb <cardinal-number> ...	==> R[1]; *XP = Conjugation::conjugate(WordAssemblages::from_wording(FW[1]), InflectionDefns::default_nl(NULL));
     

    §6. Syntax tree.

    diff --git a/docs/supervisor-module/5-ls.html b/docs/supervisor-module/5-ls.html index 8bd96c699..7c1a6a2cc 100644 --- a/docs/supervisor-module/5-ls.html +++ b/docs/supervisor-module/5-ls.html @@ -184,7 +184,7 @@ detect the language of play for a story file without actually running it.
     void Languages::write_ISO_code(OUTPUT_STREAM, inform_language *L) {
         #ifdef CORE_MODULE
    -    if (L == NULL) L = English_language;
    +    if (L == NULL) L = InflectionDefns::default_nl(NULL);
         #endif
         if (Wordings::nonempty(L->language_field[ISO_639_CODE_LFIELD]))
             WRITE("%+W", L->language_field[ISO_639_CODE_LFIELD]);
    diff --git a/docs/words-module/4-pu.html b/docs/words-module/4-pu.html
    new file mode 100644
    index 000000000..50608a4f1
    --- /dev/null
    +++ b/docs/words-module/4-pu.html
    @@ -0,0 +1,368 @@
    +
    +
    +	
    +		Preform Utilities
    +
    +		
    +		
    +		
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +		
    +	
    +	
    +		
    +		
    + + +

    Other uses for Preform grammar, including the generation of adaptive text, and word inflection.

    + +
    + +

    §1. Specifying generated text. Our main operation here is a "merge". This extracts the text from a production, +substituting the ingredient text in place of any ... it finds. (Other +wildcards and nonterminals are ignored.) For example, merging the production +

    + +
    +    fried ... tomatoes
    +
    +

    with "orange" results in "fried orange tomatoes". +

    + +
    +word_assemblage PreformUtilities::merge(nonterminal *nt, int pnum,
    +    word_assemblage ingredient) {
    +    for (production_list *pl = nt->first_pl; pl; pl = pl->next_pl) {
    +        int N = 0;
    +        for (production *pr = pl->first_pr; pr; pr = pr->next_pr) {
    +            if (N == pnum) {
    +                word_assemblage wa = WordAssemblages::lit_0();
    +                ptoken *pt;
    +                for (pt = pr->first_pt; pt; pt = pt->next_pt) {
    +                    if (pt->ptoken_category == FIXED_WORD_PTC) {
    +                        wa = WordAssemblages::join(wa, WordAssemblages::lit_1(pt->ve_pt));
    +                    } else if (pt->ptoken_category == MULTIPLE_WILDCARD_PTC) {
    +                        wa = WordAssemblages::join(wa, ingredient);
    +                    }
    +                }
    +                return wa;
    +            }
    +            N++;
    +        }
    +    }
    +    return WordAssemblages::lit_0();  give up, in other words
    +}
    +
    +

    §2. Thus we can simply extract the wording by performing a merge with the empty +ingredient text: +

    + +
    +word_assemblage PreformUtilities::wording(nonterminal *nt, int pnum) {
    +    return PreformUtilities::merge(nt, pnum, WordAssemblages::lit_0());
    +}
    +
    +

    §3. And here we take just one word: +

    + +
    +vocabulary_entry *PreformUtilities::word(nonterminal *nt, int pnum) {
    +    word_assemblage wa = PreformUtilities::merge(nt, pnum, WordAssemblages::lit_0());
    +    vocabulary_entry **words;
    +    int num_words;
    +    WordAssemblages::as_array(&wa, &words, &num_words);
    +    if (num_words == 1) return words[0];
    +    return NULL;
    +}
    +
    +

    §4. Specifying replacements. The following looks for a word in one nonterminal and returns the +corresponding word in another. If the word isn't found, it's left unchanged. +

    + +
    +vocabulary_entry *PreformUtilities::find_corresponding_word(vocabulary_entry *ve,
    +    nonterminal *nt_from, nonterminal *nt_to) {
    +    for (production_list *pl_from = nt_from->first_pl, *pl_to = nt_to->first_pl;
    +        ((pl_from) && (pl_to));
    +        pl_from = pl_from->next_pl, pl_to = pl_to->next_pl)
    +        for (production *pr_from = pl_from->first_pr, *pr_to = pl_to->first_pr;
    +            ((pr_from) && (pr_to));
    +            pr_from = pr_from->next_pr, pr_to = pr_to->next_pr)
    +            for (ptoken *pt_from = pr_from->first_pt, *pt_to = pr_to->first_pt;
    +                ((pt_from) && (pt_to));
    +                pt_from = pt_from->next_pt, pt_to = pt_to->next_pt)
    +                if ((pt_from->ptoken_category == FIXED_WORD_PTC) &&
    +                    (pt_to->ptoken_category == FIXED_WORD_PTC))
    +                    if (ve == pt_from->ve_pt)
    +                        return pt_to->ve_pt;
    +    return ve;  no change, in other words
    +}
    +
    +

    §5. Lexicon entry. This is only a convenience for putting particles into the Lexicon: +

    + +
    +#ifdef CORE_MODULE
    +void PreformUtilities::enter_lexicon(nonterminal *nt, int pos, char *category, char *gloss) {
    +    for (production_list *pl = nt->first_pl; pl; pl = pl->next_pl)
    +        for (production *pr = pl->first_pr; pr; pr = pr->next_pr)
    +            for (ptoken *pt = pr->first_pt; pt; pt = pt->next_pt)
    +                for (ptoken *alt = pt; alt; alt = alt->alternative_ptoken)
    +                    if (alt->ve_pt)
    +                        Index::Lexicon::new_entry_with_details(EMPTY_WORDING, pos,
    +                            WordAssemblages::lit_1(alt->ve_pt), category, gloss);
    +}
    +#endif
    +
    +

    §6. Making tries. Properly speaking, we make "avinues". Note that we expect to make a different +avinue for each natural language; this matters so that we can pluralise words +correctly in both English and French in the same run of Inform, for example. +But we are going to need to use these avinues frequently, so we cache them once +created. +

    + +
    +match_avinue *PreformUtilities::define_trie(nonterminal *nt, int end,
    +    NATURAL_LANGUAGE_WORDS_TYPE *nl) {
    +    match_avinue *ave = NULL;
    +    for (production_list *pl = nt->first_pl; pl; pl = pl->next_pl)
    +        if (pl->definition_language == nl) {
    +            if (pl->as_avinue) return pl->as_avinue;
    +            Construct a new avinue from this nonterminal6.1;
    +            pl->as_avinue = ave;
    +        }
    +    return ave;
    +}
    +
    +

    §6.1. The grammar for this nonterminal is either a "list grammar", meaning that it +lists other nonterminals which each define avinues, and we have to string those +together into one long avinue; or else it contains the actual content of a +single avinue. +

    + +

    Construct a new avinue from this nonterminal6.1 = +

    + +
    +    int list_grammar = NOT_APPLICABLE;  i.e., we don't know yet
    +    for (production *pr = pl->first_pr; pr; pr = pr->next_pr) {
    +        ptoken *first = pr->first_pt;
    +        if (first == NULL) continue;
    +        ptoken *second = first->next_pt;
    +        if ((second) && (second->next_pt)) {
    +            Instrumentation::log_production(pr, FALSE);
    +            PreformUtilities::production_error(nt, pr,
    +                "trie line with more than 2 words");
    +        }
    +        Consider the one- or two-token production in this nonterminal6.1.1;
    +    }
    +
    +
    • This code is used in §6.
    +

    §6.1.1. Each production contains one or two tokens. There are four possibilities for +the production: +

    + +
    +    (1)   ... <some-nonterminal>
    +    (2)   <some-nonterminal> ...
    +    (3)   <some-nonterminal>
    +    (4)   pattern-word instructions-word
    +
    +

    Cases (1), (2) and (3) are allowed only in list grammars; case (4) is allowed +only in content grammars. The ... indicates whether the trie in the named +nonterminal will act on the start or end of a word — this is needed only to +override the normal convention. +

    + +

    Consider the one- or two-token production in this nonterminal6.1.1 = +

    + +
    +    int this_end = end;
    +    ptoken *entry = NULL;
    +    if ((first->ptoken_category == MULTIPLE_WILDCARD_PTC) &&
    +        (second) && (second->ptoken_category == NONTERMINAL_PTC)) {
    +        entry = second; this_end = TRIE_END;
    +    }
    +    if ((first->ptoken_category == NONTERMINAL_PTC) &&
    +        (second) && (second->ptoken_category == MULTIPLE_WILDCARD_PTC)) {
    +        entry = first; this_end = TRIE_START;
    +    }
    +    if ((first->ptoken_category == NONTERMINAL_PTC) && (second == NULL)) {
    +        entry = first;
    +    }
    +
    +    if (entry) {
    +        if (list_grammar == FALSE) Throw problem for a mixed trie nonterminal6.1.1.1;
    +        Recurse to make an avinue from the nonterminal named here, and add it to our result6.1.1.2;
    +        list_grammar = TRUE;
    +    } else {
    +        if (list_grammar == TRUE) Throw problem for a mixed trie nonterminal6.1.1.1;
    +        if (second == NULL)
    +            PreformUtilities::production_error(nt, pr,
    +                "there should be two words here, a pattern and an instruction");
    +        Add this pattern and instruction to the trie, creating it if necessary6.1.1.3;
    +        list_grammar = FALSE;
    +    }
    +
    +
    • This code is used in §6.1.
    +

    §6.1.1.1. Throw problem for a mixed trie nonterminal6.1.1.1 = +

    + +
    +    PreformUtilities::production_error(nt, pr,
    +        "this should either be a list of other nonterminals, or a list of patterns "
    +        "and instructions, but not a mixture");
    +
    +
    • This code is used in §6.1.1 (twice).
    +

    §6.1.1.2. Recurse to make an avinue from the nonterminal named here, and add it to our result6.1.1.2 = +

    + +
    +    match_avinue *next_mt =
    +        Tries::duplicate_avinue(PreformUtilities::define_trie(entry->nt_pt, this_end, nl));
    +    if (ave == NULL) ave = next_mt;
    +    else {
    +        match_avinue *m = ave;
    +        while (m->next) m = m->next;
    +        m->next = next_mt;
    +    }
    +
    + +

    §6.1.1.3. Add this pattern and instruction to the trie, creating it if necessary6.1.1.3 = +

    + +
    +    if (ave == NULL) ave = Tries::new_avinue(end);
    +    TEMPORARY_TEXT(from);
    +    WRITE_TO(from, "%V", first->ve_pt);
    +    Tries::add_to_avinue(ave, from, Vocabulary::get_exemplar(second->ve_pt, FALSE));
    +    DISCARD_TEXT(from);
    +
    + +

    §7. The following may be useful for debugging: +

    + +
    +void PreformUtilities::log_avinues(void) {
    +    nonterminal *nt;
    +    LOOP_OVER(nt, nonterminal)
    +        for (production_list *pl = nt->first_pl; pl; pl = pl->next_pl)
    +            if (pl->as_avinue)
    +                LOG("\n\n%V ($J)\n%a",
    +                    nt->nonterminal_id, pl->definition_language, pl->as_avinue);
    +}
    +
    +

    §8. Errors. People are going to get their tries wrong; it's a very hard notation +to learn. No end users of Inform will ever write them at all — this is a +low-level feature for translators only — but translators need all the help +they can get, so we'll try to provide good problem messages. +

    + +
    +void PreformUtilities::production_error(nonterminal *nt, production *pr, char *message) {
    +    PreformUtilities::error(WordAssemblages::lit_0(), nt, pr, message);
    +}
    +
    +

    §9. Some tools using this module will want to push simple error messages out to +the command line; others will want to translate them into elaborate problem +texts in HTML. So the client is allowed to define PREFORM_ERROR_WORDS_CALLBACK +to some routine of her own, gazumping this one. +

    + +
    +void PreformUtilities::error(word_assemblage base_text, nonterminal *nt,
    +    production *pr, char *message) {
    +    #ifdef PREFORM_ERROR_WORDS_CALLBACK
    +    PREFORM_ERROR_WORDS_CALLBACK(base_text, nt, pr, message);
    +    #endif
    +    #ifndef PREFORM_ERROR_WORDS_CALLBACK
    +    if (pr) {
    +        LOG("The production at fault is:\n");
    +        Instrumentation::log_production(pr, FALSE); LOG("\n");
    +    }
    +    TEMPORARY_TEXT(ERM);
    +    if (nt == NULL)
    +        WRITE_TO(ERM, "(no nonterminal)");
    +    else
    +        WRITE_TO(ERM, "nonterminal %w",
    +            Vocabulary::get_exemplar(nt->nonterminal_id, FALSE));
    +    WRITE_TO(ERM, ": ");
    +
    +    if (WordAssemblages::nonempty(base_text))
    +        WRITE_TO(ERM, "can't conjugate verb '%A': ", &base_text);
    +
    +    if (pr) {
    +        TEMPORARY_TEXT(TEMP);
    +        for (ptoken *pt = pr->first_pt; pt; pt = pt->next_pt) {
    +            Instrumentation::write_ptoken(TEMP, pt);
    +            if (pt->next_pt) WRITE_TO(TEMP, " ");
    +        }
    +        WRITE_TO(ERM, "line %d ('%S'): ", pr->match_number, TEMP);
    +        DISCARD_TEXT(TEMP);
    +    }
    +    WRITE_TO(ERM, "%s", message);
    +    Errors::with_text("Preform error: %S", ERM);
    +    DISCARD_TEXT(ERM);
    +    #endif
    +}
    +
    + + +
    + + + diff --git a/inbuild/supervisor-module/Chapter 5/Language Services.w b/inbuild/supervisor-module/Chapter 5/Language Services.w index b60345775..768f57a96 100644 --- a/inbuild/supervisor-module/Chapter 5/Language Services.w +++ b/inbuild/supervisor-module/Chapter 5/Language Services.w @@ -107,7 +107,7 @@ detect the language of play for a story file without actually running it. = void Languages::write_ISO_code(OUTPUT_STREAM, inform_language *L) { #ifdef CORE_MODULE - if (L == NULL) L = English_language; + if (L == NULL) L = InflectionDefns::default_nl(NULL); #endif if (Wordings::nonempty(L->language_field[ISO_639_CODE_LFIELD])) WRITE("%+W", L->language_field[ISO_639_CODE_LFIELD]); diff --git a/inform7/core-module/Chapter 1/What To Compile.w b/inform7/core-module/Chapter 1/What To Compile.w index b42e202fb..4a8c62fbc 100644 --- a/inform7/core-module/Chapter 1/What To Compile.w +++ b/inform7/core-module/Chapter 1/What To Compile.w @@ -64,7 +64,7 @@ int Task::carry_out(build_step *S) { inform7_task->stage_of_compilation = -1; inform7_task->next_resource_number = 3; - English_language = Projects::get_language_of_syntax(project); + InflectionDefns::set_default_nl(Projects::get_language_of_syntax(project)); int rv = Sequence::carry_out(TargetVMs::debug_enabled(inform7_task->task->for_vm)); inform7_task = NULL; diff --git a/inform7/core-module/Chapter 3/Plural Dictionary.w b/inform7/core-module/Chapter 3/Plural Dictionary.w index 8d982a3cf..522a8b216 100644 --- a/inform7/core-module/Chapter 3/Plural Dictionary.w +++ b/inform7/core-module/Chapter 3/Plural Dictionary.w @@ -33,7 +33,7 @@ int Plurals::plural_SMF(int task, parse_node *V, wording *NPs) { wording P = Node::get_text(V->next->next); @; if (Assertions::Creator::vet_name_for_noun(P) == FALSE) return TRUE; - Pluralisation::register(S, P, English_language); + Pluralisation::register(S, P, InflectionDefns::default_nl(NULL)); return TRUE; } break; diff --git a/inform7/core-module/Chapter 4/Adjective Meanings.w b/inform7/core-module/Chapter 4/Adjective Meanings.w index d29dd0f80..501e18ed9 100644 --- a/inform7/core-module/Chapter 4/Adjective Meanings.w +++ b/inform7/core-module/Chapter 4/Adjective Meanings.w @@ -1283,7 +1283,7 @@ prefaced "(of a rulebook)", "(of an activity)", and so on. = internal { - if (Projects::get_language_of_play(Task::project()) == English_language) return FALSE; + if (Projects::get_language_of_play(Task::project()) == InflectionDefns::default_nl(NULL)) return FALSE; adjectival_phrase *aph; LOOP_OVER(aph, adjectival_phrase) { wording AW = Clusters::get_name_general(aph->adjective_names, Projects::get_language_of_play(Task::project()), 1, -1); @@ -1298,7 +1298,7 @@ prefaced "(of a rulebook)", "(of an activity)", and so on. = void Adjectives::Meanings::agreements(void) { - if (Projects::get_language_of_play(Task::project()) == English_language) return; + if (Projects::get_language_of_play(Task::project()) == InflectionDefns::default_nl(NULL)) return; adjectival_phrase *aph; LOOP_OVER(aph, adjectival_phrase) { wording PW = Clusters::get_name_general(aph->adjective_names, Projects::get_language_of_play(Task::project()), 1, -1); diff --git a/inform7/core-module/Chapter 5/Using Nametags.w b/inform7/core-module/Chapter 5/Using Nametags.w index b9ee1263f..474a83004 100644 --- a/inform7/core-module/Chapter 5/Using Nametags.w +++ b/inform7/core-module/Chapter 5/Using Nametags.w @@ -108,7 +108,7 @@ void UseNouns::nl_translates(parse_node *pn) { inform_language *nl = Node::get_defn_language(pn->next->next); int g = Annotations::read_int(pn->next->next, gender_reference_ANNOT); if (nl == NULL) internal_error("No such NL"); - if (nl == English_language) { + if (nl == InflectionDefns::default_nl(NULL)) { StandardProblems::sentence_problem(Task::syntax_tree(), _p_(PM_CantTranslateIntoEnglish), "you can't translate into English", "only out of it."); diff --git a/inform7/core-module/Chapter 6/New Verbs.w b/inform7/core-module/Chapter 6/New Verbs.w index 07b302a02..5f0cfd2d1 100644 --- a/inform7/core-module/Chapter 6/New Verbs.w +++ b/inform7/core-module/Chapter 6/New Verbs.w @@ -89,7 +89,7 @@ as the object. = ::= in | ==> R[2]; <> = (inform_language *) (RP[1]); - ==> R[1]; <> = English_language; + ==> R[1]; <> = InflectionDefns::default_nl(NULL); ::= to ( ... ) | ==> R[1]; <> = TRUE @@ -552,7 +552,7 @@ foreign verbs (4). binary_predicate *bp = VerbMeanings::get_relational_meaning(&vm); if (bp == a_has_b_predicate) p = 1; if (bp == R_equality) p = 2; - if ((nl) && (nl != English_language)) p = 5; + if ((nl) && (nl != InflectionDefns::default_nl(NULL))) p = 5; ++new_verb_sequence_count; vi = Verbs::new_verb(vc, FALSE); vc->vc_conjugates = vi; @@ -634,13 +634,13 @@ void NewVerbs::bootstrap(void) { NewVerbs::declare_sm(Sentences::VPs::omit_from_SMF, I"omit-from", 4); word_assemblage infinitive = PreformUtilities::wording(, 0); - verb_conjugation *vc = Conjugation::conjugate(infinitive, English_language); + verb_conjugation *vc = Conjugation::conjugate(infinitive, InflectionDefns::default_nl(NULL)); verb_identity *vi = Verbs::new_verb(vc, TRUE); vc->vc_conjugates = vi; VerbUsages::register_all_usages_of_verb(vi, FALSE, 2); infinitive = PreformUtilities::wording(, 1); - vc = Conjugation::conjugate(infinitive, English_language); + vc = Conjugation::conjugate(infinitive, InflectionDefns::default_nl(NULL)); vi = Verbs::new_verb(vc, FALSE); vc->vc_conjugates = vi; VerbUsages::register_all_usages_of_verb(vi, FALSE, 3); @@ -1135,7 +1135,7 @@ void NewVerbs::log(verb_usage *vu) { if (vu == NULL) { LOG("(null verb usage)"); return; } LOG("VU: $f ", &(vu->vu_text)); if (vu->negated_form_of_verb) LOG("(negated) "); - Linguistics::log_tense_number(DL, vu->tensed); + InflectionDefns::log_tense_number(DL, vu->tensed); } void NewVerbs::log_all(void) { diff --git a/inform7/if-module/Chapter 3/The Naming Thicket.w b/inform7/if-module/Chapter 3/The Naming Thicket.w index 55c183884..f3c0448e0 100644 --- a/inform7/if-module/Chapter 3/The Naming Thicket.w +++ b/inform7/if-module/Chapter 3/The Naming Thicket.w @@ -189,7 +189,7 @@ from sentences, and this can include I6 properties with no I7 analogue. this_is_named_for_something_with_a_printed_name = TRUE; @; if (this_has_a_printed_name == FALSE) @; - if (Projects::get_language_of_play(Task::project()) != English_language) + if (Projects::get_language_of_play(Task::project()) != InflectionDefns::default_nl(NULL)) @; } diff --git a/inform7/kinds-module/Chapter 2/Describing Kinds.w b/inform7/kinds-module/Chapter 2/Describing Kinds.w index 76caaaabd..f3f5aa9f5 100644 --- a/inform7/kinds-module/Chapter 2/Describing Kinds.w +++ b/inform7/kinds-module/Chapter 2/Describing Kinds.w @@ -468,7 +468,7 @@ void Kinds::Textual::write_plural(OUTPUT_STREAM, kind *K) { void Kinds::Textual::write_articled(OUTPUT_STREAM, kind *K) { TEMPORARY_TEXT(TEMP); Kinds::Textual::write_inner(TEMP, K, FALSE, TRUE); - ArticleInflection::preface_by_article(OUT, TEMP, English_language); + ArticleInflection::preface_by_article(OUT, TEMP, InflectionDefns::default_nl(NULL)); DISCARD_TEXT(TEMP); } diff --git a/services/inflections-module/Chapter 2/Linguistic Definitions.w b/services/inflections-module/Chapter 2/Linguistic Definitions.w index c3173d528..2e9bee9a8 100644 --- a/services/inflections-module/Chapter 2/Linguistic Definitions.w +++ b/services/inflections-module/Chapter 2/Linguistic Definitions.w @@ -1,4 +1,4 @@ -[Linguistics::] Linguistic Definitions. +[InflectionDefns::] Linguistic Definitions. Some basic linguistic constants are defined. @@ -6,11 +6,13 @@ Some basic linguistic constants are defined. First, we support three genders: @d NO_KNOWN_GENDERS 3 -@d NEUTER_GENDER 1 /* can be used as Scandinavian "common gender" */ +@d NEUTER_GENDER 1 /* or can be used as Scandinavian "common gender" */ @d MASCULINE_GENDER 2 @d FEMININE_GENDER 3 -@ There are six "persons": +@ There are six "persons". The sequence corresponds to the defined constants +in the English Language extension, which we assume will be followed by other +languages. @d NO_KNOWN_PERSONS 6 @d FIRST_PERSON_SINGULAR 0 @@ -32,14 +34,9 @@ First, we support three genders: @d ACTIVE_MOOD 0 @d PASSIVE_MOOD 1 -@ 25 cases ought to be plenty, though some languages are pretty scary this -way: Hungarian, for example, has 18. We only require one case to exist, the -nominative, which is required to be case 0. - -But this covers a pretty decent selection. Note that, as with the -persons above, the sequence corresponds to the defined constants in the -English Language extension, which we assume will be followed by other -languages. +@ 25 cases sounds like plenty, but some languages are pretty scary this +way: Hungarian has 18. We only require one case to exist, the nominative, +which is required to be case 0. @d MAX_GRAMMATICAL_CASES 25 @d NOMINATIVE_CASE 0 @@ -54,18 +51,20 @@ tense 5 for the past historic. @d HASBEEN_TENSE 2 /* Present perfect */ @d HADBEEN_TENSE 3 /* Past perfect */ @d WILLBE_TENSE 4 /* Future (not used in assertions or conditions) */ +@d CUSTOM1_TENSE 5 +@d CUSTOM2_TENSE 6 = -void Linguistics::log_tense_number(OUTPUT_STREAM, int t) { +void InflectionDefns::log_tense_number(OUTPUT_STREAM, int t) { switch (t) { - case IS_TENSE: WRITE("IS_TENSE"); break; - case WAS_TENSE: WRITE("WAS_TENSE"); break; + case IS_TENSE: WRITE("IS_TENSE"); break; + case WAS_TENSE: WRITE("WAS_TENSE"); break; case HASBEEN_TENSE: WRITE("HASBEEN_TENSE"); break; case HADBEEN_TENSE: WRITE("HADBEEN_TENSE"); break; - case WILLBE_TENSE: WRITE("WILLBE_TENSE"); break; - case 5: WRITE("CUSTOM1_TENSE"); break; - case 6: WRITE("CUSTOM2_TENSE"); break; - default: WRITE(""); break; + case WILLBE_TENSE: WRITE("WILLBE_TENSE"); break; + case CUSTOM1_TENSE: WRITE("CUSTOM1_TENSE"); break; + case CUSTOM2_TENSE: WRITE("CUSTOM2_TENSE"); break; + default: WRITE(""); break; } } @@ -74,9 +73,13 @@ The following is in effect also a constant; Inform sets it to English early in its run. = -NATURAL_LANGUAGE_WORDS_TYPE *English_language = NULL; /* until created, early in run */ +NATURAL_LANGUAGE_WORDS_TYPE *default_language_for_linguistics = NULL; -NATURAL_LANGUAGE_WORDS_TYPE *Linguistics::default_nl(NATURAL_LANGUAGE_WORDS_TYPE *nl) { - if (nl) return nl; - return English_language; +void InflectionDefns::set_default_nl(NATURAL_LANGUAGE_WORDS_TYPE *nl) { + default_language_for_linguistics = nl; +} + +NATURAL_LANGUAGE_WORDS_TYPE *InflectionDefns::default_nl(NATURAL_LANGUAGE_WORDS_TYPE *nl) { + if (nl) return nl; + return default_language_for_linguistics; } diff --git a/services/inflections-module/Chapter 3/Article Inflection.w b/services/inflections-module/Chapter 3/Article Inflection.w index afeb7b984..23f9fe75d 100644 --- a/services/inflections-module/Chapter 3/Article Inflection.w +++ b/services/inflections-module/Chapter 3/Article Inflection.w @@ -2,21 +2,20 @@ To inflect "a" into "an", and so forth. -@h The indefinite article trie. -Here we take text such as "UNESCO document" and put an article in front, to +@ Here we take text such as "UNESCO document" and put an article in front, to get "a UNESCO document" (and not "an UNESCO document": these things are much trickier than they look). = match_avinue *indef_trie = NULL; -void ArticleInflection::preface_by_article(OUTPUT_STREAM, text_stream *initial_text, - NATURAL_LANGUAGE_WORDS_TYPE *nl) { +void ArticleInflection::preface_by_article(OUTPUT_STREAM, + text_stream *initial_text, NATURAL_LANGUAGE_WORDS_TYPE *nl) { if (indef_trie == NULL) indef_trie = PreformUtilities::define_trie( , TRIE_START, - Linguistics::default_nl(NULL)); + InflectionDefns::default_nl(NULL)); wchar_t *result = Tries::search_avinue(indef_trie, initial_text); if (result == NULL) result = L"a"; WRITE("%w %S", result, initial_text); diff --git a/services/inflections-module/Chapter 3/Declensions.w b/services/inflections-module/Chapter 3/Declensions.w index d31a1934f..c33fb3dc2 100644 --- a/services/inflections-module/Chapter 3/Declensions.w +++ b/services/inflections-module/Chapter 3/Declensions.w @@ -13,14 +13,14 @@ typedef struct declension { @ = declension Declensions::decline(wording W, NATURAL_LANGUAGE_WORDS_TYPE *nl, int gen, int num) { - if (nl == NULL) nl = English_language; + nl = InflectionDefns::default_nl(nl); declension D = Declensions::decline_inner(W, nl, gen, num, ); @; return D; } declension Declensions::decline_article(wording W, NATURAL_LANGUAGE_WORDS_TYPE *nl, int gen, int num) { - if (nl == NULL) nl = English_language; + nl = InflectionDefns::default_nl(nl); declension D = Declensions::decline_inner(W, nl, gen, num, ); @; return D; @@ -36,7 +36,7 @@ declension Declensions::decline_article(wording W, NATURAL_LANGUAGE_WORDS_TYPE * @ = declension Declensions::decline_inner(wording W, NATURAL_LANGUAGE_WORDS_TYPE *nl, int gen, int num, nonterminal *nt) { - if (nl == NULL) nl = English_language; + nl = InflectionDefns::default_nl(nl); declension D; D.within_language = nl; for (production_list *pl = nt->first_pl; pl; pl = pl->next_pl) { @@ -115,7 +115,7 @@ declension Declensions::decline_from_groups(wording W, NATURAL_LANGUAGE_WORDS_TY D.within_language = nl; TEMPORARY_TEXT(from); WRITE_TO(from, "%+W", W); - match_avinue *group_trie = PreformUtilities::define_trie(gnt, TRIE_END, Linguistics::default_nl(nl)); + match_avinue *group_trie = PreformUtilities::define_trie(gnt, TRIE_END, InflectionDefns::default_nl(nl)); wchar_t *result = Tries::search_avinue(group_trie, from); DISCARD_TEXT(from); if (result == NULL) { diff --git a/services/inflections-module/Chapter 3/Grading Adjectives.w b/services/inflections-module/Chapter 3/Grading Adjectives.w index fef3ec035..7e3784d72 100644 --- a/services/inflections-module/Chapter 3/Grading Adjectives.w +++ b/services/inflections-module/Chapter 3/Grading Adjectives.w @@ -2,8 +2,7 @@ To inflect adjectives into comparative and superlative forms. -@h Constructing comparatives. -In English, the comparative of an adjective can generally be formed by +@ In English, the comparative of an adjective can generally be formed by suffixing the inflected form with "than"; thus, "big" to "bigger than". The following does the suffixing: @@ -11,7 +10,9 @@ The following does the suffixing: ::= ... than -@ = +@ This is essentially a wrapper function for the trie . + += wording Grading::make_comparative(wording W, NATURAL_LANGUAGE_WORDS_TYPE *nl) { TEMPORARY_TEXT(comprised); TEMPORARY_TEXT(transformed); @@ -19,9 +20,10 @@ wording Grading::make_comparative(wording W, NATURAL_LANGUAGE_WORDS_TYPE *nl) { WRITE_TO(comprised, "some-long-text"); else WRITE_TO(comprised, "%N", Wordings::first_wn(W)); - if (nl == NULL) nl = English_language; + nl = InflectionDefns::default_nl(nl); match_avinue *comp_trie = - PreformUtilities::define_trie(, TRIE_END, Linguistics::default_nl(nl)); + PreformUtilities::define_trie(, TRIE_END, + InflectionDefns::default_nl(nl)); Inflections::suffix_inflection(transformed, comp_trie, comprised); wording PW = Feeds::feed_text(transformed); word_assemblage merged = @@ -34,6 +36,9 @@ wording Grading::make_comparative(wording W, NATURAL_LANGUAGE_WORDS_TYPE *nl) { return PW; } +@ This is essentially a wrapper function for the trie . + += wording Grading::make_superlative(wording W, NATURAL_LANGUAGE_WORDS_TYPE *nl) { TEMPORARY_TEXT(comprised); TEMPORARY_TEXT(transformed); @@ -41,9 +46,10 @@ wording Grading::make_superlative(wording W, NATURAL_LANGUAGE_WORDS_TYPE *nl) { WRITE_TO(comprised, "some-long-text"); else WRITE_TO(comprised, "%N", Wordings::first_wn(W)); - if (nl == NULL) nl = English_language; + nl = InflectionDefns::default_nl(nl); match_avinue *comp_trie = - PreformUtilities::define_trie(, TRIE_END, Linguistics::default_nl(nl)); + PreformUtilities::define_trie(, TRIE_END, + InflectionDefns::default_nl(nl)); Inflections::suffix_inflection(transformed, comp_trie, comprised); wording PW = Feeds::feed_text(transformed); LOGIF(CONSTRUCTED_PLURALS, "[Superlative of %W is %W]\n", W, PW); @@ -52,10 +58,10 @@ wording Grading::make_superlative(wording W, NATURAL_LANGUAGE_WORDS_TYPE *nl) { return PW; } -@ There has to be a better term than "quiddity" for this grammatical construct, +@ This is essentially a wrapper function for the trie . +There has to be a better term than "quiddity" for this grammatical concept, but what I mean is the property for which the given adjective makes a -comparison: for instance, "tallness" for "tall", or "steeliness" for -"steely". +comparison: for instance, "tallness" for "tall", or "steeliness" for "steely". = wording Grading::make_quiddity(wording W, NATURAL_LANGUAGE_WORDS_TYPE *nl) { @@ -65,9 +71,10 @@ wording Grading::make_quiddity(wording W, NATURAL_LANGUAGE_WORDS_TYPE *nl) { WRITE_TO(comprised, "some-long-text"); else WRITE_TO(comprised, "%N", Wordings::first_wn(W)); - if (nl == NULL) nl = English_language; + nl = InflectionDefns::default_nl(nl); match_avinue *comp_trie = - PreformUtilities::define_trie(, TRIE_END, Linguistics::default_nl(nl)); + PreformUtilities::define_trie(, TRIE_END, + InflectionDefns::default_nl(nl)); Inflections::suffix_inflection(transformed, comp_trie, comprised); wording PW = Feeds::feed_text(transformed); LOGIF(CONSTRUCTED_PLURALS, "[Quiddity of %W is %W]\n", W, PW); diff --git a/services/inflections-module/Chapter 2/Name Clusters.w b/services/inflections-module/Chapter 3/Name Clusters.w similarity index 79% rename from services/inflections-module/Chapter 2/Name Clusters.w rename to services/inflections-module/Chapter 3/Name Clusters.w index d8d9ba94a..7d4ffe775 100644 --- a/services/inflections-module/Chapter 2/Name Clusters.w +++ b/services/inflections-module/Chapter 3/Name Clusters.w @@ -14,7 +14,7 @@ with lingistic roles. For example, the cluster of names for the common noun = typedef struct name_cluster { - struct individual_name *first_name; + struct linked_list *listed; /* of |individual_name| */ CLASS_DEFINITION } name_cluster; @@ -23,8 +23,7 @@ typedef struct individual_name { struct declension name; /* text of name */ int name_number; /* 1 for singular, 2 for plural */ int name_gender; /* 1 is neuter, 2 is masculine, 3 is feminine */ - NATURAL_LANGUAGE_WORDS_TYPE *name_language; /* always non-null */ - struct individual_name *next; /* within its cluster */ + NATURAL_LANGUAGE_WORDS_TYPE *name_language; CLASS_DEFINITION } individual_name; @@ -33,32 +32,34 @@ typedef struct individual_name { = name_cluster *Clusters::new(void) { name_cluster *names = CREATE(name_cluster); - names->first_name = NULL; + names->listed = NEW_LINKED_LIST(individual_name); return names; } @ The following can add either a single name, or a name and its plural(s): = -individual_name *Clusters::add(name_cluster *names, wording W, - NATURAL_LANGUAGE_WORDS_TYPE *nl, int gender, int number, int pluralise) { - if (nl == NULL) nl = English_language; +individual_name *Clusters::add_one(name_cluster *names, wording W, + NATURAL_LANGUAGE_WORDS_TYPE *nl, int gender, int number) { + nl = InflectionDefns::default_nl(nl); individual_name *in = CREATE(individual_name); in->principal_meaning = NULL_GENERAL_POINTER; in->name = Declensions::decline(W, nl, gender, number); in->name_language = nl; in->name_number = number; in->name_gender = gender; - in->next = NULL; - if (names->first_name == NULL) names->first_name = in; - else { - individual_name *in2; - for (in2 = names->first_name; ((in2) && (in2->next)); in2 = in2->next) ; - in2->next = in; - } + ADD_TO_LINKED_LIST(in, individual_name, names->listed); + return in; +} + +linked_list *Clusters::add(name_cluster *names, wording W, + NATURAL_LANGUAGE_WORDS_TYPE *nl, int gender, int number, int pluralise) { + linked_list *L = NEW_LINKED_LIST(individual_name); + individual_name *in = Clusters::add_one(names, W, nl, gender, number); + ADD_TO_LINKED_LIST(in, individual_name, L); if ((pluralise) && (number == 1)) @; - return in; + return L; } @ The following makes all possible plurals and registers those too. (Note @@ -75,9 +76,9 @@ so there may be any number of names registered: for instance, the kind wording PW = EMPTY_WORDING; pde = Pluralisation::make(W, &PW, pde, nl); if (Wordings::nonempty(PW)) { - LOGIF(CONSTRUCTED_PLURALS, "(%d) Reading plural of <%W> as <%W>\n", k, - W, PW); - Clusters::add(names, PW, nl, gender, 2, FALSE); + LOGIF(CONSTRUCTED_PLURALS, "(%d) Plural of <%W>: <%W>\n", k, W, PW); + individual_name *in = Clusters::add_one(names, PW, nl, gender, 2); + ADD_TO_LINKED_LIST(in, individual_name, L); } } while (pde); @@ -91,15 +92,14 @@ At run time, it's an integer from 0 to 11 which encodes all possible combinations. Here we only work through six, ignoring animation: = -void Clusters::add_with_agreements(name_cluster *cl, wording W, NATURAL_LANGUAGE_WORDS_TYPE *nl) { - if (nl == NULL) nl = English_language; - if (nl == English_language) { +void Clusters::add_with_agreements(name_cluster *cl, wording W, + NATURAL_LANGUAGE_WORDS_TYPE *nl) { + nl = InflectionDefns::default_nl(nl); + if (nl == InflectionDefns::default_nl(NULL)) Clusters::add(cl, W, nl, NEUTER_GENDER, 1, FALSE); - } else { - int gna; - for (gna = 0; gna < 6; gna++) + else + for (int gna = 0; gna < 6; gna++) @; - } } @ We use tries to modify the base text, which is taken to be the neuter @@ -134,10 +134,12 @@ through one or two tries. word_assemblage wa = WordAssemblages::from_wording(W); if (step1) wa = Inflections::apply_trie_to_wa(wa, - PreformUtilities::define_trie(step1, TRIE_END, Linguistics::default_nl(nl))); + PreformUtilities::define_trie(step1, TRIE_END, + InflectionDefns::default_nl(nl))); if (step2) wa = Inflections::apply_trie_to_wa(wa, - PreformUtilities::define_trie(step2, TRIE_END, Linguistics::default_nl(nl))); + PreformUtilities::define_trie(step2, TRIE_END, + InflectionDefns::default_nl(nl))); FW = WordAssemblages::to_wording(&wa); @h Plural fixing. @@ -148,9 +150,10 @@ only when the built-in kinds are being given plural names; some of these and wouldn't pass through the pluralising tries intact. = -void Clusters::set_plural_name(name_cluster *cl, wording W, NATURAL_LANGUAGE_WORDS_TYPE *nl) { +void Clusters::set_plural_name(name_cluster *cl, wording W, + NATURAL_LANGUAGE_WORDS_TYPE *nl) { individual_name *in; - for (in = cl->first_name; in; in = in->next) + LOOP_OVER_LINKED_LIST(in, individual_name, cl->listed) if (in->name_number == 2) { in->name = Declensions::decline(W, nl, NEUTER_GENDER, 2); return; @@ -170,7 +173,7 @@ wording Clusters::get_name(name_cluster *cl, int plural_flag) { int number_sought = 1; if (plural_flag) number_sought = 2; individual_name *in; - for (in = cl->first_name; in; in = in->next) + LOOP_OVER_LINKED_LIST(in, individual_name, cl->listed) if (in->name_number == number_sought) return Declensions::in_case(&(in->name), NOMINATIVE_CASE); return EMPTY_WORDING; @@ -180,11 +183,12 @@ wording Clusters::get_name(name_cluster *cl, int plural_flag) { falling back on English if there's none registered: = -wording Clusters::get_name_in_play(name_cluster *cl, int plural_flag, NATURAL_LANGUAGE_WORDS_TYPE *nl) { +wording Clusters::get_name_in_play(name_cluster *cl, int plural_flag, + NATURAL_LANGUAGE_WORDS_TYPE *nl) { int number_sought = 1; if (plural_flag) number_sought = 2; individual_name *in; - for (in = cl->first_name; in; in = in->next) + LOOP_OVER_LINKED_LIST(in, individual_name, cl->listed) if ((in->name_number == number_sought) && (in->name_language == nl)) return Declensions::in_case(&(in->name), NOMINATIVE_CASE); @@ -197,7 +201,7 @@ wording Clusters::get_name_in_play(name_cluster *cl, int plural_flag, NATURAL_LA wording Clusters::get_name_general(name_cluster *cl, NATURAL_LANGUAGE_WORDS_TYPE *nl, int number_sought, int gender_sought) { individual_name *in; - for (in = cl->first_name; in; in = in->next) + LOOP_OVER_LINKED_LIST(in, individual_name, cl->listed) if (((number_sought == -1) || (number_sought == in->name_number)) && ((gender_sought == -1) || (gender_sought == in->name_gender)) && (in->name_language == nl)) @@ -217,6 +221,8 @@ void Clusters::set_principal_meaning(individual_name *in, general_pointer meanin } general_pointer Clusters::get_principal_meaning(name_cluster *cl) { - if (cl->first_name == NULL) return NULL_GENERAL_POINTER; - return cl->first_name->principal_meaning; + individual_name *in; + LOOP_OVER_LINKED_LIST(in, individual_name, cl->listed) + return in->principal_meaning; + return NULL_GENERAL_POINTER; } diff --git a/services/inflections-module/Chapter 3/Past Participles.w b/services/inflections-module/Chapter 3/Past Participles.w index 25b31c958..68898fce6 100644 --- a/services/inflections-module/Chapter 3/Past Participles.w +++ b/services/inflections-module/Chapter 3/Past Participles.w @@ -38,6 +38,7 @@ above. It expects only a single word. = int PastParticiples::pasturise_text(OUTPUT_STREAM, text_stream *from) { match_avinue *past_trie = - PreformUtilities::define_trie(, TRIE_START, Linguistics::default_nl(NULL)); + PreformUtilities::define_trie(, TRIE_START, + InflectionDefns::default_nl(NULL)); return Inflections::suffix_inflection(OUT, past_trie, from); } diff --git a/services/inflections-module/Chapter 3/Pluralisation.w b/services/inflections-module/Chapter 3/Pluralisation.w index a299ef485..2e4fd7355 100644 --- a/services/inflections-module/Chapter 3/Pluralisation.w +++ b/services/inflections-module/Chapter 3/Pluralisation.w @@ -42,7 +42,7 @@ one not found in the dictionary). = plural_dictionary_entry *Pluralisation::make(wording W, wording *PW, plural_dictionary_entry *search_from, NATURAL_LANGUAGE_WORDS_TYPE *nl) { - if (nl == NULL) nl = English_language; + nl = InflectionDefns::default_nl(nl); plural_dictionary_entry *pde; @@ -95,8 +95,9 @@ has a plural, and modifies it to the plural form. = int Pluralisation::regular(OUTPUT_STREAM, text_stream *from, NATURAL_LANGUAGE_WORDS_TYPE *nl) { - if (nl == NULL) nl = English_language; + nl = InflectionDefns::default_nl(nl); match_avinue *plural_trie = - PreformUtilities::define_trie(, TRIE_END, Linguistics::default_nl(nl)); + PreformUtilities::define_trie(, TRIE_END, + InflectionDefns::default_nl(nl)); return Inflections::suffix_inflection(OUT, plural_trie, from); } diff --git a/services/inflections-module/Chapter 3/Verb Conjugation.w b/services/inflections-module/Chapter 3/Verb Conjugation.w index baac0f057..c2268a807 100644 --- a/services/inflections-module/Chapter 3/Verb Conjugation.w +++ b/services/inflections-module/Chapter 3/Verb Conjugation.w @@ -54,7 +54,7 @@ verb_conjugation *Conjugation::conjugate(word_assemblage base_text, verb_conjugation *Conjugation::conjugate_with_overrides(word_assemblage base_text, word_assemblage *overrides, int no_overrides, NATURAL_LANGUAGE_WORDS_TYPE *nl) { - if (nl == NULL) nl = English_language; + nl = InflectionDefns::default_nl(nl); if (WordAssemblages::nonempty(base_text) == FALSE) internal_error("No base text for verb conjugation"); @@ -378,7 +378,7 @@ example: verb_forms[n] = Inflections::apply_trie_to_wa( verb_forms[BASE_FORM_TYPE], - PreformUtilities::define_trie(content_token->nt_pt, TRIE_END, Linguistics::default_nl(nl))); + PreformUtilities::define_trie(content_token->nt_pt, TRIE_END, InflectionDefns::default_nl(nl))); else if (content_token->ptoken_category == FIXED_WORD_PTC) verb_forms[n] = Conjugation::expand_with_endings(content_token->ve_pt, verb_forms); @@ -804,7 +804,7 @@ from our dictionary of 14,000 or so present and past participles. = void Conjugation::test_participle(OUTPUT_STREAM, wording W) { verb_conjugation *vc = Conjugation::conjugate( - WordAssemblages::from_wording(W), English_language); + WordAssemblages::from_wording(W), InflectionDefns::default_nl(NULL)); if (vc == NULL) { WRITE("Failed test\n"); return; } Conjugation::write_participle(OUT, vc); DESTROY(vc, verb_conjugation); diff --git a/services/inflections-module/Chapter 4/English Inflections.w b/services/inflections-module/Chapter 4/English Inflections.w index b6c4503cd..7c0e5ac22 100644 --- a/services/inflections-module/Chapter 4/English Inflections.w +++ b/services/inflections-module/Chapter 4/English Inflections.w @@ -2,65 +2,6 @@ To define how English nouns and verbs are inflected. -@h Preface. -Inflections are modifications of words -- usually word endings or beginnings -- -for different circumstances. English is often called an uninflected language, -but this is an exaggeration. For example, we spell the word "tree" as -"trees" if it refers to more than one of them. Inform sometimes needs -to take text in one form and change it to another -- for example, to turn -a singular noun into a plural one -- and ordinary Preform parsing isn't good -enough to express this. - -Inform uses a data structure called a "trie" as an efficient way to match -prefix and/or suffix patterns in words, and then to modify them. These tries -are created using the same notation as for Preform grammar, which is -convenient in many ways, but also a little misleading -- they are parsed quite -differently. The rules are as follows: - -(a) A nonterminal in trie grammar can either be a list of other tries, or it -can be a list of inflection rules. Mixtures of the two are not allowed. For -example || is a list of other tries, while -|| contains actual rules. - -(b) In a list of tries, each production consists only of a single nonterminal -identifying the trie to make use of. One exception: writing |...| before the -trie's name makes it work on the end of a word instead of the beginning. -Inform attempts to find a match using each trie in turn, until a match is -found. - -(c) In a list of inflection rules, each production consists of two words. The -first word is what to match; the second gives instructions on what to turn -it into. An asterisk is used to mean "any string of 0 or more letters"; -a digit in the replacement text means "truncate by this many letters and -add...". (As a special case, the replacement text "0" means: make no -change.) Some examples: - -|lead gold| turns "lead" into "gold" - -|codex codices| turns "codex" to "codices" - -|*mouse 5mice| turns "mouse" to "mice", or "fieldmouse" to "fieldmice" - -Designing a trie is not quite as easy as it looks. It looks as if this is a -sequence of tests to perform in succession, but it's better to think of the -rules all being performed at once. In general, if you need one inflection -rule to take precedence over another, put it in an earlier trie, rather than -putting it earlier in the same trie. - -@ Tries are highly language specific and should not be translated as such: -instead, an appropriate version needs to be written for every language. - -Except at the very top level, translators are free to created new tries -and name them as they please. For example, the Spanish implementation of -= (text as InC) - -= -may look entirely unlike its English version, but at the top level it still -has to have that name. - -Lower-level tries used in the implementation should have names beginning -with a language code: hence the names "en-" used below. - @h Noun inflections. The following trie looks at the start of a word, which we assume to be a noun, and decides whether to use the indefinite article "a" or "an". diff --git a/services/inflections-module/Contents.w b/services/inflections-module/Contents.w index a166501bb..66fdf8b94 100644 --- a/services/inflections-module/Contents.w +++ b/services/inflections-module/Contents.w @@ -4,17 +4,21 @@ Purpose: A library for adapting words or short phrases for linguistic purposes. Language: InC Licence: Artistic License 2.0 +Preliminaries + What This Module Does + How To Include This Module + Chapter 1: Starting Up Inflections Module Chapter 2: Machinery Linguistic Definitions Tries and Inflections - Name Clusters Chapter 3: Grammatical Uses of Inflection Article Inflection Declensions + Name Clusters Pluralisation Grading Adjectives Past Participles diff --git a/services/inflections-module/Preliminaries/How To Include This Module.w b/services/inflections-module/Preliminaries/How To Include This Module.w new file mode 100644 index 000000000..53736a0ed --- /dev/null +++ b/services/inflections-module/Preliminaries/How To Include This Module.w @@ -0,0 +1,28 @@ +How To Include This Module. + +What to do to make use of the inflections module in a new command-line tool. + +@h Status. +The inflections module is provided as one of the "services" suite of modules, +which means that it was built with a view to potential incorporation in +multiple tools. It can be found, for example, in //inform7// and +//inflections-test//. + +By convention, the modules considered as "services" have no dependencies on +other modules except for //foundation// and other "services" modules. + +A tool can import //inflections// only if it also imports //foundation//, +//words// and //syntax//. + +@h Importing the module. +We'll use the term "parent" to mean the tool which is importing //inflections//, +that is, which will include its code and be able to use it. As with any +imported module, +(*) The contents page of the parent's web must identify and locate the +module: += (text as Inweb) +Import: somepath/inflections += +(*) The parent must call |InflectionsModule::start()| just after it starts up, and +|InflectionsModule::end()| just before it shuts down. (But just after, and just +before, the corresponding calls to //foundation//.) diff --git a/services/inflections-module/Preliminaries/What This Module Does.w b/services/inflections-module/Preliminaries/What This Module Does.w new file mode 100644 index 000000000..7036b1b3d --- /dev/null +++ b/services/inflections-module/Preliminaries/What This Module Does.w @@ -0,0 +1,113 @@ +What This Module Does. + +An overview of the inflections module's role and abilities. + +@h Prerequisites. +The inflections module is a part of the Inform compiler toolset. It is +presented as a literate program or "web". Before diving in: +(a) It helps to have some experience of reading webs: see //inweb// for more. +(b) The module is written in C, in fact ANSI C99, but this is disguised by the +fact that it uses some extension syntaxes provided by the //inweb// literate +programming tool, making it a dialect of C called InC. See //inweb// for +full details, but essentially: it's C without predeclarations or header files, +and where functions have names like |Tags::add_by_name| rather than |add_by_name|. +(c) This module uses other modules drawn from the //compiler//, and also +uses a module of utility functions called //foundation//. +For more, see //foundation: A Brief Guide to Foundation//. + +@h Inflections. +Inflections are modifications of words -- usually word endings or beginnings -- +for different circumstances. English is often called an uninflected language, +but this is an exaggeration. For example, we spell the word "tree" as +"trees" when we refer to more than one of them. Inform sometimes needs +to take text in one form and change it to another -- for example, to turn +a singular noun into a plural one -- and ordinary Preform parsing isn't good +enough to express this. + +Inform uses a data structure called a "trie" as an efficient way to match +prefix and/or suffix patterns in words, and then to modify them. + +Tries are provided as basic data structures by //foundation: Tries and Avinues//, +and the code for initialising them from Preform grammar is provided by +//words: Preform Utilities//. + +@ Though tries are, as just mentioned, created from Preform grammar, they're +parsed quite differently. The rules are as follows: + +(a) A nonterminal in trie grammar can either be a list of other tries, or it +can be a list of inflection rules. Mixtures of the two are not allowed. For +example is a list of other tries, +while contains actual rules. + +(b) In a list of tries, each production consists only of a single nonterminal +identifying the trie to make use of. One exception: writing |...| before the +trie's name makes it work on the end of a word instead of the beginning. +Inform attempts to find a match using each trie in turn, until a match is +found. For example: += (text as Preform) + ::= + | + ... | + ... += +means try first (on the whole word), then + (on the tail), and finally +(also on the tail). + +(c) In a list of inflection rules, each production consists of two words. The +first word is what to match; the second gives instructions on what to turn +it into. An asterisk is used to mean "any string of 0 or more letters"; +a digit in the replacement text means "truncate by this many letters and +add...". (As a special case, the replacement text "0" means: make no +change.) Some examples: += (text as Preform) + ::= + lead lead | + codex codices | + *mouse 5mice += +This would pluralise "lead" as "lead", "codex" as "codices", "mouse" as "mice", +and "fieldmouse" as "fieldmice". + +Designing a trie is not quite as easy as it looks. It looks as if this is a +sequence of tests to perform in succession, but it's better to think of the +rules all being performed at once. In general, if you need one inflection +rule to take precedence over another, put it in an earlier trie, rather than +putting it earlier in the same trie. + +For the implementation of these rules, see //Tries and Inflections//. + +@ Once we have that general inflection machinery, most of what we need to +do becomes a simple matter of writing wrapper functions for tries. + +(*) //ArticleInflection::preface_by_article// handles the variation of articles: +for example, mutating "a" to "an" when it comes before "orange", thus making +"an orange" rather than "a orange". + +(*) //Grading::make_comparative// turns "tall" into "taller". + +(*) //Grading::make_superlative// turns "tall" into "tallest". + +(*) //Grading::make_quiddity// turns "tall" into "tallness". + +(*) //PastParticiples::pasturise_wording// turns "looking away" to "looked away". + +(*) //Pluralisation::make// produces a series of allowable plurals for a +word, using a combination of a trie to handle regular pluralisation (for +English, we use Conway's algorithm) and a dictionary of user-supplied +exceptions. + +@ Tries are highly language specific and should not be translated as such: +instead, an appropriate version needs to be written for every language. +The tries for English are in //English Inflections//. + +Except at the very top level, translators are free to created new tries +and name them as they please. For example, the Spanish implementation of += (text as InC) + += +may look entirely unlike its English version, but at the top level it still +has to have that name. + +Lower-level tries used in the implementation should have names beginning +with a language code: hence the names "en-" used in //English Inflections//. diff --git a/services/inflections-test/Chapter 1/Unit Tests.w b/services/inflections-test/Chapter 1/Unit Tests.w index 2f41623a0..c4cb72250 100644 --- a/services/inflections-test/Chapter 1/Unit Tests.w +++ b/services/inflections-test/Chapter 1/Unit Tests.w @@ -14,9 +14,9 @@ void Unit::test_adjectives(text_stream *arg) { if (Lexer::word(i) == PARBREAK_V) continue; wording W = Wordings::one_word(i); PRINT("%W --> ", W); - PRINT("comparative: %W, ", Grading::make_comparative(W, English_language)); - PRINT("superlative: %W, ", Grading::make_superlative(W, English_language)); - PRINT("quiddity: %W\n", Grading::make_quiddity(W, English_language)); + PRINT("comparative: %W, ", Grading::make_comparative(W, InflectionDefns::default_nl(NULL))); + PRINT("superlative: %W, ", Grading::make_superlative(W, InflectionDefns::default_nl(NULL))); + PRINT("quiddity: %W\n", Grading::make_quiddity(W, InflectionDefns::default_nl(NULL))); } } } @@ -35,7 +35,7 @@ void Unit::test_articles(text_stream *arg) { TEMPORARY_TEXT(T); WRITE_TO(T, "%W", W); TEMPORARY_TEXT(AT); - ArticleInflection::preface_by_article(AT, T, English_language); + ArticleInflection::preface_by_article(AT, T, InflectionDefns::default_nl(NULL)); PRINT("%S --> %S\n", T, AT); DISCARD_TEXT(AT); DISCARD_TEXT(T); @@ -62,12 +62,12 @@ void Unit::test_declensions(text_stream *arg) { if (Lexer::word(i) == f_V) { gen = FEMININE_GENDER; continue; } if (Lexer::word(i) == n_V) { gen = NEUTER_GENDER; continue; } wording W = Wordings::one_word(i); - declension D = Declensions::decline(W, English_language, gen, 1); - declension AD = Declensions::decline_article(PW, English_language, gen, 1); + declension D = Declensions::decline(W, InflectionDefns::default_nl(NULL), gen, 1); + declension AD = Declensions::decline_article(PW, InflectionDefns::default_nl(NULL), gen, 1); PRINT("%W --> ", W); Declensions::writer(STDOUT, &D, &AD); - D = Declensions::decline(W, English_language, gen, 2); - AD = Declensions::decline_article(PW, English_language, gen, 2); + D = Declensions::decline(W, InflectionDefns::default_nl(NULL), gen, 2); + AD = Declensions::decline_article(PW, InflectionDefns::default_nl(NULL), gen, 2); PRINT("pl --> "); Declensions::writer(STDOUT, &D, &AD); PRINT("\n"); @@ -106,7 +106,7 @@ void Unit::test_plurals(text_stream *arg) { TEMPORARY_TEXT(G); WRITE_TO(G, "%W", W); TEMPORARY_TEXT(ASAGIG); - Pluralisation::regular(ASAGIG, G, English_language); + Pluralisation::regular(ASAGIG, G, InflectionDefns::default_nl(NULL)); PRINT("%S --> %S\n", G, ASAGIG); DISCARD_TEXT(ASAGIG); DISCARD_TEXT(G); @@ -129,7 +129,7 @@ void Unit::test_verbs(text_stream *arg) { if (c++ < 10) { PRINT("Verb %W -->\n", W); TEMPORARY_TEXT(T); - Conjugation::test(T, W, English_language); + Conjugation::test(T, W, InflectionDefns::default_nl(NULL)); Regexp::replace(T, L"%^", L"\n", REP_REPEATING); PRINT("%S\n", T); DISCARD_TEXT(T); diff --git a/services/linguistics-module/Chapter 3/Nouns.w b/services/linguistics-module/Chapter 3/Nouns.w index 75c882acb..290915c91 100644 --- a/services/linguistics-module/Chapter 3/Nouns.w +++ b/services/linguistics-module/Chapter 3/Nouns.w @@ -112,9 +112,10 @@ we add a new one. = individual_name *Nouns::add_to_noun_and_reg(noun *t, wording W, NATURAL_LANGUAGE_WORDS_TYPE *foreign_language, int gender, int number, int options) { - individual_name *in = Clusters::add(t->names, W, foreign_language, gender, number, + linked_list *L = Clusters::add(t->names, W, foreign_language, gender, number, (options & REGISTER_PLURAL_NTOPT)?TRUE:FALSE); - for (; in; in = in->next) + individual_name *in; + LOOP_OVER_LINKED_LIST(in, individual_name, L) if ((options & REGISTER_SINGULAR_NTOPT) && (t->registration_category != NOUN_HAS_NO_MC)) { excerpt_meaning *em = ExcerptMeanings::register( t->registration_category, diff --git a/services/linguistics-module/Chapter 4/Adverb Phrases of Occurrence.w b/services/linguistics-module/Chapter 4/Adverb Phrases of Occurrence.w index 549a52ad2..5b3ec91f5 100644 --- a/services/linguistics-module/Chapter 4/Adverb Phrases of Occurrence.w +++ b/services/linguistics-module/Chapter 4/Adverb Phrases of Occurrence.w @@ -70,7 +70,7 @@ void Occurrence::log(OUTPUT_STREAM, void *vtp) { default: WRITE(": "); break; } if (tp->tense != IS_TENSE) { - WRITE(": "); Linguistics::log_tense_number(OUT, tp->tense); + WRITE(": "); InflectionDefns::log_tense_number(OUT, tp->tense); } WRITE(">"); } diff --git a/services/linguistics-module/Chapter 4/Verb Usages.w b/services/linguistics-module/Chapter 4/Verb Usages.w index 359f20106..ce761feac 100644 --- a/services/linguistics-module/Chapter 4/Verb Usages.w +++ b/services/linguistics-module/Chapter 4/Verb Usages.w @@ -326,7 +326,7 @@ A usage is "foreign" if it belongs to a language other than English: int VerbUsages::is_foreign(verb_usage *vu) { if ((vu->verb_used) && (vu->verb_used->conjugation->defined_in) && - (vu->verb_used->conjugation->defined_in != English_language)) { + (vu->verb_used->conjugation->defined_in != InflectionDefns::default_nl(NULL))) { return TRUE; } return FALSE; diff --git a/services/linguistics-test/Chapter 1/Unit Tests.w b/services/linguistics-test/Chapter 1/Unit Tests.w index c50dcbb6c..f42bba73b 100644 --- a/services/linguistics-test/Chapter 1/Unit Tests.w +++ b/services/linguistics-test/Chapter 1/Unit Tests.w @@ -55,7 +55,7 @@ any text but then fail. @ = ::= - verb ... ==> R[1]; *XP = Conjugation::conjugate(WordAssemblages::from_wording(FW[1]), English_language); + verb ... ==> R[1]; *XP = Conjugation::conjugate(WordAssemblages::from_wording(FW[1]), InflectionDefns::default_nl(NULL)); @h Syntax tree.