@fpw/en-wiktionary-la-modules 0.0.11 → 0.0.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/dist/LaEngine.js +6 -6
  2. package/dist/LaEngine.js.map +1 -1
  3. package/dist/index.js +5 -1
  4. package/dist/index.js.map +1 -1
  5. package/dist/modules/conjugation/LaVerb.js +375 -374
  6. package/dist/modules/conjugation/LaVerb.js.map +1 -1
  7. package/dist/modules/conjugation/VerbForm.js +2 -2
  8. package/dist/modules/conjugation/VerbForm.js.map +1 -1
  9. package/dist/modules/conjugation/VerbType.d.ts +1 -0
  10. package/dist/modules/conjugation/VerbType.js +3 -2
  11. package/dist/modules/conjugation/VerbType.js.map +1 -1
  12. package/dist/modules/declination/LaAdjData.js +424 -424
  13. package/dist/modules/declination/LaAdjData.js.map +1 -1
  14. package/dist/modules/declination/LaNominal.js +70 -70
  15. package/dist/modules/declination/LaNominal.js.map +1 -1
  16. package/dist/modules/declination/LaNounData.js +420 -420
  17. package/dist/modules/declination/LaNounData.js.map +1 -1
  18. package/dist/modules/declination/NominalForm.js +2 -2
  19. package/dist/modules/declination/NominalForm.js.map +1 -1
  20. package/dist/modules/headword/HeadwordParser.js +17 -17
  21. package/dist/modules/headword/HeadwordParser.js.map +1 -1
  22. package/package.json +6 -5
  23. package/src/LaEngine.ts +82 -0
  24. package/src/index.ts +16 -0
  25. package/src/modules/common.ts +164 -0
  26. package/src/modules/conjugation/LaVerb.ts +2490 -0
  27. package/src/modules/conjugation/VerbAffix.ts +18 -0
  28. package/src/modules/conjugation/VerbForm.ts +223 -0
  29. package/src/modules/conjugation/VerbType.ts +51 -0
  30. package/src/modules/declination/LaAdjData.ts +845 -0
  31. package/src/modules/declination/LaNominal.ts +1975 -0
  32. package/src/modules/declination/LaNounData.ts +859 -0
  33. package/src/modules/declination/LaPersonalPronoun.ts +77 -0
  34. package/src/modules/declination/NominalForm.ts +89 -0
  35. package/src/modules/headword/HeadWord.ts +132 -0
  36. package/src/modules/headword/HeadwordParser.ts +514 -0
@@ -0,0 +1,859 @@
1
+ /**
2
+ * This is a complete re-implementation of Wiktionary's Module:la-adj/data, developed by Benwing2.
3
+ * It was converted from Lua to TypeScript by Folke Will <folko@solhost.org>.
4
+ *
5
+ * Original source: https://en.wiktionary.org/wiki/Module:la-noun/data
6
+ * Based on version: https://en.wiktionary.org/w/index.php?title=Module:la-noun/data&oldid=63744261
7
+ *
8
+ * Lua idioms, function and variable names kept as in the original in order to easily
9
+ * backport later changes to this implementation.
10
+ *
11
+ * For that reason, it's suggested to add a type-aware wrapper around this class and leave
12
+ * this code unchanged instead of improving the types and use of idioms in this class.
13
+ *
14
+ */
15
+ import { strip_macrons } from "../common";
16
+ import { NumberTantum, SegmentData } from "./LaNominal";
17
+ import { getNominalForm, setNominalForm } from "./NominalForm";
18
+
19
+ export const m_noun_decl: Map<string, ((data: SegmentData, args: string[]) => void)> = new Map([
20
+ ["1", (data, args) => {
21
+ const stem = args[0];
22
+
23
+ setNominalForm(data.forms, "nom_sg", [stem + "a"]);
24
+ setNominalForm(data.forms, "gen_sg", [stem + "ae"]);
25
+ setNominalForm(data.forms, "dat_sg", [stem + "ae"]);
26
+ setNominalForm(data.forms, "acc_sg", [stem + "am"]);
27
+ setNominalForm(data.forms, "abl_sg", [stem + "ā"]);
28
+ setNominalForm(data.forms, "voc_sg", [stem + "a"]);
29
+
30
+ setNominalForm(data.forms, "nom_pl", [stem + "ae"]);
31
+ setNominalForm(data.forms, "gen_pl", [stem + "ārum"]);
32
+ setNominalForm(data.forms, "dat_pl", [stem + "īs"]);
33
+ setNominalForm(data.forms, "acc_pl", [stem + "ās"]);
34
+ setNominalForm(data.forms, "abl_pl", [stem + "īs"]);
35
+ setNominalForm(data.forms, "voc_pl", [stem + "ae"]);
36
+
37
+ if (data.types.has("abus")) {
38
+ data.subtitles.push(["dative/ablative plural in ", "'-ābus'"]);
39
+ setNominalForm(data.forms, "dat_pl", [stem + "ābus"]);
40
+ setNominalForm(data.forms, "abl_pl", [stem + "ābus"]);
41
+ } else if (data.types.has("not_abus")) {
42
+ data.subtitles.push(["dative/ablative plural in ", "'-īs'"]);
43
+ }
44
+
45
+ if (data.types.has("am")) {
46
+ data.subtitles.push(["nominative/vocative singular in ", "'-ām'"]);
47
+ setNominalForm(data.forms, "nom_sg", [stem + "ām"]);
48
+ setNominalForm(data.forms, "acc_sg", [stem + "ām"]);
49
+ setNominalForm(data.forms, "voc_sg", [stem + "ām"]);
50
+ setNominalForm(data.forms, "abl_sg", [stem + "ām", stem + "ā"]);
51
+ } else if (data.types.has("Greek")) {
52
+ if (data.types.has("Ma")) {
53
+ data.subtitles.push("masculine Greek-type with nominative singular in '-ās'");
54
+ setNominalForm(data.forms, "nom_sg", [stem + "ās"]);
55
+ setNominalForm(data.forms, "acc_sg", [stem + "ān"]);
56
+ setNominalForm(data.forms, "voc_sg", [stem + "ā"]);
57
+ } else if (data.types.has("Me")) {
58
+ data.subtitles.push("masculine Greek-type with nominative singular in '-ēs'");
59
+ setNominalForm(data.forms, "nom_sg", [stem + "ēs"]);
60
+ setNominalForm(data.forms, "acc_sg", [stem + "ēn"]);
61
+ setNominalForm(data.forms, "abl_sg", [stem + "ē"]);
62
+ setNominalForm(data.forms, "voc_sg", [stem + "ē"]);
63
+ } else {
64
+ data.subtitles.push("Greek-type");
65
+ setNominalForm(data.forms, "nom_sg", [stem + "ē"]);
66
+ setNominalForm(data.forms, "gen_sg", [stem + "ēs"]);
67
+ setNominalForm(data.forms, "acc_sg", [stem + "ēn"]);
68
+ setNominalForm(data.forms, "abl_sg", [stem + "ē"]);
69
+ setNominalForm(data.forms, "voc_sg", [stem + "ē"]);
70
+ }
71
+ } else if (data.types.has("not_Greek")) {
72
+ data.subtitles.push("non-Greek-type");
73
+ } else if (data.types.has("not_am")) {
74
+ data.subtitles.push(["nominative/vocative singular in ", "'-a'"]);
75
+ }
76
+
77
+ if (data.loc) {
78
+ setNominalForm(data.forms, "loc_sg", [stem + "ae"]);
79
+ setNominalForm(data.forms, "loc_pl", [stem + "īs"]);
80
+ }
81
+ }],
82
+ ["2", (data, args) => {
83
+ const stem1 = args[0];
84
+ const stem2 = args[1];
85
+
86
+ setNominalForm(data.forms, "nom_sg", [stem1 + "us"]);
87
+ setNominalForm(data.forms, "gen_sg", [stem1 + "ī"]);
88
+ setNominalForm(data.forms, "dat_sg", [stem1 + "ō"]);
89
+ setNominalForm(data.forms, "acc_sg", [stem1 + "um"]);
90
+ setNominalForm(data.forms, "abl_sg", [stem1 + "ō"]);
91
+ setNominalForm(data.forms, "voc_sg", [stem1 + "e"]);
92
+
93
+ setNominalForm(data.forms, "nom_pl", [stem1 + "ī"]);
94
+ setNominalForm(data.forms, "gen_pl", [stem1 + "ōrum"]);
95
+ setNominalForm(data.forms, "dat_pl", [stem1 + "īs"]);
96
+ setNominalForm(data.forms, "acc_pl", [stem1 + "ōs"]);
97
+ setNominalForm(data.forms, "abl_pl", [stem1 + "īs"]);
98
+ setNominalForm(data.forms, "voc_pl", [stem1 + "ī"]);
99
+
100
+ if (data.types.has("N")) {
101
+ data.subtitles.push("neuter");
102
+ setNominalForm(data.forms, "nom_sg", [stem1 + "um"]);
103
+ setNominalForm(data.forms, "voc_sg", [stem1 + "um"]);
104
+
105
+ setNominalForm(data.forms, "nom_pl", [stem1 + "a"]);
106
+ setNominalForm(data.forms, "acc_pl", [stem1 + "a"]);
107
+ setNominalForm(data.forms, "voc_pl", [stem1 + "a"]);
108
+
109
+ if (data.types.has("ium")) {
110
+ setNominalForm(data.forms, "nom_sg", [stem1 + "ium"]);
111
+ setNominalForm(data.forms, "gen_sg", [stem1 + "iī", stem1 + "ī"]);
112
+ setNominalForm(data.forms, "dat_sg", [stem1 + "iō"]);
113
+ setNominalForm(data.forms, "acc_sg", [stem1 + "ium"]);
114
+ setNominalForm(data.forms, "abl_sg", [stem1 + "iō"]);
115
+ setNominalForm(data.forms, "voc_sg", [stem1 + "ium"]);
116
+
117
+ setNominalForm(data.forms, "nom_pl", [stem1 + "ia"]);
118
+ setNominalForm(data.forms, "gen_pl", [stem1 + "iōrum"]);
119
+ setNominalForm(data.forms, "dat_pl", [stem1 + "iīs"]);
120
+ setNominalForm(data.forms, "acc_pl", [stem1 + "ia"]);
121
+ setNominalForm(data.forms, "abl_pl", [stem1 + "iīs"]);
122
+ setNominalForm(data.forms, "voc_pl", [stem1 + "ia"]);
123
+
124
+ data.notes.set("gen_sg2", "Found in older Latin (until the Augustan Age).");
125
+ } else if (data.types.has("a")) {
126
+ data.subtitles.push("nominative/accusative/vocative plural in '-a'");
127
+
128
+ setNominalForm(data.forms, "nom_sg", [stem1 + "us"]);
129
+ setNominalForm(data.forms, "acc_sg", [stem1 + "us"]);
130
+ setNominalForm(data.forms, "voc_sg", [stem1 + "us"]);
131
+
132
+ setNominalForm(data.forms, "nom_pl", [stem1 + "a"]);
133
+ setNominalForm(data.forms, "acc_pl", [stem1 + "a"]);
134
+ setNominalForm(data.forms, "voc_pl", [stem1 + "a"]);
135
+ } else if (data.types.has("vom")) {
136
+ data.subtitles.push("nominative singular in '-om' after 'v'");
137
+ setNominalForm(data.forms, "nom_sg", [stem1 + "om"]);
138
+ setNominalForm(data.forms, "acc_sg", [stem1 + "om"]);
139
+ setNominalForm(data.forms, "voc_sg", [stem1 + "om"]);
140
+ } else if (data.types.has("Greek") && data.types.has("us")) {
141
+ data.subtitles.push("Greek-type");
142
+ data.subtitles.push("nominative/accusative/vocative in '-os'");
143
+
144
+ setNominalForm(data.forms, "nom_sg", [stem1 + "os"]);
145
+ setNominalForm(data.forms, "acc_sg", [stem1 + "os"]);
146
+ setNominalForm(data.forms, "voc_sg", [stem1 + "os"]);
147
+
148
+ setNominalForm(data.forms, "nom_pl", [stem1 + "ē"]);
149
+ setNominalForm(data.forms, "gen_pl", [stem1 + "ōn"]);
150
+ setNominalForm(data.forms, "acc_pl", [stem1 + "ē"]);
151
+ setNominalForm(data.forms, "voc_pl", [stem1 + "ē"]);
152
+ } else if (data.types.has("Greek")) {
153
+ data.subtitles.push("Greek-type");
154
+ setNominalForm(data.forms, "nom_sg", [stem1 + "on"]);
155
+ setNominalForm(data.forms, "acc_sg", [stem1 + "on"]);
156
+ setNominalForm(data.forms, "voc_sg", [stem1 + "on"]);
157
+ } else if (data.types.has("us")) {
158
+ data.subtitles.push("nominative/accusative/vocative in '-us'");
159
+ setNominalForm(data.forms, "nom_sg", [stem1 + "us"]);
160
+ setNominalForm(data.forms, "acc_sg", [stem1 + "us"]);
161
+ setNominalForm(data.forms, "voc_sg", [stem1 + "us"]);
162
+
163
+ setNominalForm(data.forms, "nom_pl", [stem1 + "ī"]);
164
+ setNominalForm(data.forms, "acc_pl", [stem1 + "ōs"]);
165
+ setNominalForm(data.forms, "voc_pl", [stem1 + "ī"]);
166
+ } else if (data.types.has("not_Greek") || data.types.has("not_us")) {
167
+ data.subtitles.push("nominative/accusative/vocative in '-um'");
168
+ }
169
+ } else if (data.types.has("er")) {
170
+ if (stem1.match(/[aiouy]r$/)) {
171
+ data.subtitles.push("nominative singular in '-r'");
172
+ } else {
173
+ data.subtitles.push("nominative singular in '-er'");
174
+ }
175
+
176
+ setNominalForm(data.forms, "nom_sg", [stem1]);
177
+ setNominalForm(data.forms, "gen_sg", [stem2 + "ī"]);
178
+ setNominalForm(data.forms, "dat_sg", [stem2 + "ō"]);
179
+ setNominalForm(data.forms, "acc_sg", [stem2 + "um"]);
180
+ setNominalForm(data.forms, "abl_sg", [stem2 + "ō"]);
181
+ setNominalForm(data.forms, "voc_sg", [stem1]);
182
+
183
+ setNominalForm(data.forms, "nom_pl", [stem2 + "ī"]);
184
+ setNominalForm(data.forms, "gen_pl", [stem2 + "ōrum"]);
185
+ setNominalForm(data.forms, "dat_pl", [stem2 + "īs"]);
186
+ setNominalForm(data.forms, "acc_pl", [stem2 + "ōs"]);
187
+ setNominalForm(data.forms, "abl_pl", [stem2 + "īs"]);
188
+ setNominalForm(data.forms, "voc_pl", [stem2 + "ī"]);
189
+ } else if (data.types.has("ius")) {
190
+ setNominalForm(data.forms, "nom_sg", [stem1 + "ius"]);
191
+ setNominalForm(data.forms, "gen_sg", [stem1 + "iī", stem1 + "ī"]);
192
+ setNominalForm(data.forms, "dat_sg", [stem1 + "iō"]);
193
+ setNominalForm(data.forms, "acc_sg", [stem1 + "ium"]);
194
+ setNominalForm(data.forms, "abl_sg", [stem1 + "iō"]);
195
+
196
+ if (data.types.has("voci")) {
197
+ setNominalForm(data.forms, "voc_sg", [stem1 + "ī"]);
198
+ } else {
199
+ setNominalForm(data.forms, "voc_sg", [stem1 + "ie"]);
200
+ }
201
+
202
+ setNominalForm(data.forms, "nom_pl", [stem1 + "iī"]);
203
+ setNominalForm(data.forms, "gen_pl", [stem1 + "iōrum"]);
204
+ setNominalForm(data.forms, "dat_pl", [stem1 + "iīs"]);
205
+ setNominalForm(data.forms, "acc_pl", [stem1 + "iōs"]);
206
+ setNominalForm(data.forms, "abl_pl", [stem1 + "iīs"]);
207
+ setNominalForm(data.forms, "voc_pl", [stem1 + "iī"]);
208
+
209
+ data.notes.set("gen_sg2", "Found in older Latin (until the Augustan Age).");
210
+ } else if (data.types.has("vos")) {
211
+ data.subtitles.push("nominative singular in '-os' after 'v'");
212
+ setNominalForm(data.forms, "nom_sg", [stem1 + "os"]);
213
+ setNominalForm(data.forms, "acc_sg", [stem1 + "om"]);
214
+ } else if (data.types.has("Greek")) {
215
+ data.subtitles.push("Greek-type");
216
+ setNominalForm(data.forms, "nom_sg", [stem1 + "os"]);
217
+ setNominalForm(data.forms, "acc_sg", [stem1 + "on"]);
218
+ } else if (data.types.has("not_Greek")) {
219
+ data.subtitles.push("non-Greek-type");
220
+ }
221
+
222
+ if (data.types.has("genplum")) {
223
+ data.subtitles.push(["contracted", " genitive plural"]);
224
+ data.notes.set("gen_pl2", "Contraction found in poetry.");
225
+ if (data.types.has("ius") || data.types.has("ium")) {
226
+ setNominalForm(data.forms, "gen_pl", [stem2 + "iōrum", stem2 + "ium"]);
227
+ } else {
228
+ setNominalForm(data.forms, "gen_pl", [stem2 + "ōrum", stem2 + "um"]);
229
+ }
230
+ } else if (data.types.has("not_genplum")) {
231
+ data.subtitles.push(["normal", " genitive plural"]);
232
+ }
233
+
234
+ if (data.loc) {
235
+ if (data.types.has("ius") || data.types.has("ium")) {
236
+ setNominalForm(data.forms, "loc_sg", [stem2 + "iī"]);
237
+ setNominalForm(data.forms, "loc_pl", [stem2 + "iīs"]);
238
+ } else {
239
+ setNominalForm(data.forms, "loc_sg", [stem2 + "ī"]);
240
+ setNominalForm(data.forms, "loc_pl", [stem2 + "īs"]);
241
+ }
242
+ }
243
+ }],
244
+ ["3", (data, args) => {
245
+ let stem1 = args[0];
246
+ const stem2 = args[1];
247
+
248
+ function parisyllabic_type(): string {
249
+ const stem1_vowels = strip_macrons(stem1).replace(/[^AEIOUYaeiouy]/g, "");
250
+ const stem2_vowels = strip_macrons(stem2).replace(/[^AEIOUYaeiouy]/g, "");
251
+ return stem1_vowels.length > stem2_vowels.length ? "parisyllabic" : "imparisyllabic";
252
+ }
253
+
254
+ function non_i_stem_type() {
255
+ return parisyllabic_type() + " non-i-stem";
256
+ }
257
+
258
+ setNominalForm(data.forms, "nom_sg", [stem1]);
259
+ setNominalForm(data.forms, "gen_sg", [stem2 + "is"]);
260
+ setNominalForm(data.forms, "dat_sg", [stem2 + "ī"]);
261
+ setNominalForm(data.forms, "acc_sg", [stem2 + "em"]);
262
+ setNominalForm(data.forms, "abl_sg", [stem2 + "e"]);
263
+ setNominalForm(data.forms, "voc_sg", [stem1]);
264
+
265
+ setNominalForm(data.forms, "nom_pl", [stem2 + "ēs"]);
266
+ setNominalForm(data.forms, "gen_pl", [stem2 + "um"]);
267
+ setNominalForm(data.forms, "dat_pl", [stem2 + "ibus"]);
268
+ setNominalForm(data.forms, "acc_pl", [stem2 + "ēs"]);
269
+ setNominalForm(data.forms, "abl_pl", [stem2 + "ibus"]);
270
+ setNominalForm(data.forms, "voc_pl", [stem2 + "ēs"]);
271
+
272
+ let acc_sg_i_stem_subtype = false;
273
+ let not_acc_sg_i_stem_subtype = false;
274
+
275
+ for (const subtype of data.types.keys()) {
276
+ if (acc_sg_i_stem_subtypes.has(subtype)) {
277
+ acc_sg_i_stem_subtype = true;
278
+ break;
279
+ }
280
+ }
281
+
282
+ for (const [acc_sg_subtype, [endings, title]] of acc_sg_i_stem_subtypes) {
283
+ if (data.types.has("not_" + acc_sg_subtype)) {
284
+ not_acc_sg_i_stem_subtype = true;
285
+ break;
286
+ }
287
+ }
288
+
289
+ let abl_sg_i_stem_subtype = false;
290
+ let not_abl_sg_i_stem_subtype = false;
291
+ for (const subtype of data.types.keys()) {
292
+ if (abl_sg_i_stem_subtypes.has(subtype)) {
293
+ abl_sg_i_stem_subtype = true;
294
+ break;
295
+ }
296
+ }
297
+
298
+ for (const [abl_sg_subtype, [endings, title]] of abl_sg_i_stem_subtypes) {
299
+ if (data.types.has("not_" + abl_sg_subtype)) {
300
+ not_abl_sg_i_stem_subtype = true;
301
+ break;
302
+ }
303
+ }
304
+
305
+
306
+ if (data.types.has("Greek")) {
307
+ data.subtitles.push("Greek-type");
308
+
309
+ if (data.types.has("er")) {
310
+ data.subtitles.push("variant with nominative singular in '-ēr'");
311
+ stem1 = extract_stem(stem1, "ēr");
312
+
313
+ setNominalForm(data.forms, "nom_sg", [stem1 + "ēr"]);
314
+ setNominalForm(data.forms, "gen_sg", [stem1 + "eris"]);
315
+ setNominalForm(data.forms, "dat_sg", [stem1 + "erī"]);
316
+ setNominalForm(data.forms, "acc_sg", [stem1 + "era", stem1 + "erem"]);
317
+ setNominalForm(data.forms, "abl_sg", [stem1 + "ere"]);
318
+ setNominalForm(data.forms, "voc_sg", [stem1 + "ēr"]);
319
+
320
+ setNominalForm(data.forms, "nom_pl", [stem1 + "erēs"]);
321
+ setNominalForm(data.forms, "gen_pl", [stem1 + "erum"]);
322
+ setNominalForm(data.forms, "dat_pl", [stem1 + "eribus"]);
323
+ setNominalForm(data.forms, "acc_pl", [stem1 + "erēs"]);
324
+ setNominalForm(data.forms, "abl_pl", [stem1 + "eribus"]);
325
+ setNominalForm(data.forms, "voc_pl", [stem1 + "erēs"]);
326
+ } else if (data.types.has("on")) {
327
+ data.subtitles.push("variant with nominative singular in '-ōn'");
328
+ stem1 = extract_stem(stem1, "ōn");
329
+
330
+ setNominalForm(data.forms, "nom_sg", [stem1 + "ōn"]);
331
+ setNominalForm(data.forms, "gen_sg", [stem1 + "ontis", stem1 + "ontos"]);
332
+ setNominalForm(data.forms, "dat_sg", [stem1 + "ontī"]);
333
+ setNominalForm(data.forms, "acc_sg", [stem1 + "onta"]);
334
+ setNominalForm(data.forms, "abl_sg", [stem1 + "onte"]);
335
+ setNominalForm(data.forms, "voc_sg", [stem1 + "ōn"]);
336
+
337
+ setNominalForm(data.forms, "nom_pl", [stem1 + "ontēs"]);
338
+ setNominalForm(data.forms, "gen_pl", [stem1 + "ontum", stem1 + "ontium"]);
339
+ setNominalForm(data.forms, "dat_pl", [stem1 + "ontibus"]);
340
+ setNominalForm(data.forms, "acc_pl", [stem1 + "ontēs", stem1 + "ontās"]);
341
+ setNominalForm(data.forms, "abl_pl", [stem1 + "ontibus"]);
342
+ setNominalForm(data.forms, "voc_pl", [stem1 + "ontēs"]);
343
+ } else if (data.types.has("I")) {
344
+ data.subtitles.push("i-stem");
345
+ setNominalForm(data.forms, "gen_sg", [stem2 + "is", stem2 + "eōs", stem2 + "ios"]);
346
+ setNominalForm(data.forms, "acc_sg", [stem2 + "im", stem2 + "in", stem2 + "em"]);
347
+ setNominalForm(data.forms, "abl_sg", [stem2 + "ī", stem2 + "e"]);
348
+ setNominalForm(data.forms, "voc_sg", [stem2 + "is", stem2 + "i"]);
349
+
350
+ data.notes.set("acc_sg3", "Found sometimes in Medieval and New Latin.");
351
+ data.notes.set("abl_sg2", "Found sometimes in Medieval and New Latin.");
352
+
353
+ setNominalForm(data.forms, "nom_pl", [stem2 + "ēs", stem2 + "eis"]);
354
+ setNominalForm(data.forms, "gen_pl", [stem2 + "ium", stem2 + "eōn"]);
355
+ setNominalForm(data.forms, "acc_pl", [stem2 + "ēs", stem2 + "eis"]);
356
+ setNominalForm(data.forms, "voc_pl", [stem2 + "ēs", stem2 + "eis"]);
357
+
358
+ if (data.types.has("poetic_esi")) {
359
+ setNominalForm(data.forms, "dat_pl", [stem2 + "ibus", stem2 + "esi"]);
360
+ setNominalForm(data.forms, "abl_pl", [stem2 + "ibus", stem2 + "esi"]);
361
+ data.notes.set("dat_pl2", "Primarily in poetry.");
362
+ data.notes.set("abl_pl2", "Primarily in poetry.");
363
+ }
364
+ } else {
365
+ data.subtitles.push("normal variant");
366
+
367
+ setNominalForm(data.forms, "gen_sg", [stem2 + "os"]);
368
+ if (stem2.match(/y$/)) {
369
+ setNominalForm(data.forms, "acc_sg", [stem2 + "n"]);
370
+ } else {
371
+ setNominalForm(data.forms, "acc_sg", [stem2 + "a"]);
372
+ }
373
+ setNominalForm(data.forms, "nom_pl", [stem2 + "es"]);
374
+ setNominalForm(data.forms, "acc_pl", [stem2 + "as"]);
375
+ setNominalForm(data.forms, "voc_pl", [stem2 + "es"]);
376
+
377
+ if (stem1.match(/[iyï]s$/)) {
378
+ setNominalForm(data.forms, "voc_sg", [stem1, stem1.replace(/s/g, "")]);
379
+ data.notes.set("voc_sg2", "In poetry.");
380
+ }
381
+ }
382
+ } else if (data.types.has("not_Greek")) {
383
+ data.subtitles.push("non-Greek-type");
384
+ }
385
+
386
+ if (data.types.has("polis")) {
387
+ stem1 = extract_stem(stem1, "polis");
388
+ data.subtitles.push("i-stem, partially Greek-type");
389
+ setNominalForm(data.forms, "nom_sg", [stem1 + "polis"]);
390
+ setNominalForm(data.forms, "gen_sg", [stem1 + "polis"]);
391
+ setNominalForm(data.forms, "dat_sg", [stem1 + "polī"]);
392
+ setNominalForm(data.forms, "acc_sg", [stem1 + "polim", stem1 + "polin"]);
393
+ setNominalForm(data.forms, "abl_sg", [stem1 + "polī"]);
394
+ setNominalForm(data.forms, "voc_sg", [stem1 + "polis", stem1 + "polī"]);
395
+ } else if (data.types.has("not_polis")) {
396
+ data.subtitles.push(non_i_stem_type());
397
+ }
398
+
399
+ if (data.types.has("N")) {
400
+ data.subtitles.push("neuter");
401
+
402
+ setNominalForm(data.forms, "acc_sg", [stem1]);
403
+
404
+ if (data.types.has("I")) {
405
+ if (data.types.has("pure")) {
406
+ data.subtitles.push("“pure” i-stem");
407
+
408
+ setNominalForm(data.forms, "abl_sg", [stem2 + "ī"]);
409
+
410
+ setNominalForm(data.forms, "nom_pl", [stem2 + "ia"]);
411
+ setNominalForm(data.forms, "gen_pl", [stem2 + "ium"]);
412
+ setNominalForm(data.forms, "acc_pl", [stem2 + "ia"]);
413
+ setNominalForm(data.forms, "voc_pl", [stem2 + "ia"]);
414
+ } else {
415
+ data.subtitles.push("i-stem");
416
+ setNominalForm(data.forms, "nom_pl", [stem2 + "a"]);
417
+ setNominalForm(data.forms, "gen_pl", [stem2 + "ium", stem2 + "um"]);
418
+ setNominalForm(data.forms, "acc_pl", [stem2 + "a"]);
419
+ setNominalForm(data.forms, "voc_pl", [stem2 + "a"]);
420
+ }
421
+ } else {
422
+ data.subtitles.push(non_i_stem_type());
423
+ setNominalForm(data.forms, "nom_pl", [stem2 + "a"]);
424
+ setNominalForm(data.forms, "acc_pl", [stem2 + "a"]);
425
+ setNominalForm(data.forms, "voc_pl", [stem2 + "a"]);
426
+ }
427
+ } else if (data.types.has("I") || acc_sg_i_stem_subtype || abl_sg_i_stem_subtype) {
428
+ if (data.types.has("not_N")) {
429
+ data.subtitles.push("non-neuter i-stem");
430
+ } else {
431
+ data.subtitles.push("i-stem");
432
+ }
433
+
434
+ setNominalForm(data.forms, "gen_pl", [stem2 + "ium"]);
435
+ setNominalForm(data.forms, "acc_pl", [stem2 + "ēs", stem2 + "īs"]);
436
+
437
+ for (const subtype of data.types) {
438
+ const acc_sg_i_stem_props = acc_sg_i_stem_subtypes.get(subtype);
439
+ if (acc_sg_i_stem_props) {
440
+ setNominalForm(data.forms, "acc_sg", []);
441
+ for (const ending of acc_sg_i_stem_props[0]) {
442
+ setNominalForm(data.forms, "acc_sg", (getNominalForm(data.forms, "acc_sg") || []).concat([stem2 + ending]));
443
+ }
444
+ if (data.num != "pl") {
445
+ data.subtitles.push(acc_sg_i_stem_props[1]);
446
+ }
447
+ break;
448
+ }
449
+ }
450
+
451
+ for (const subtype of data.types) {
452
+ const abl_sg_i_stem_props = abl_sg_i_stem_subtypes.get(subtype);
453
+ if (abl_sg_i_stem_props) {
454
+ setNominalForm(data.forms, "abl_sg", []);
455
+ for (const ending of abl_sg_i_stem_props[0]) {
456
+ setNominalForm(data.forms, "abl_sg", (getNominalForm(data.forms, "abl_sg") || []).concat([stem2 + ending]));
457
+ }
458
+ if (data.num != "pl") {
459
+ data.subtitles.push(abl_sg_i_stem_props[1]);
460
+ }
461
+ break;
462
+ }
463
+ }
464
+ } else if (data.types.has("not_N") && data.types.has("not_I")) {
465
+ data.subtitles.push("non-neuter " + non_i_stem_type());
466
+ } else if (data.types.has("not_N")) {
467
+ data.subtitles.push("non-neuter");
468
+ } else if (data.types.has("not_I")) {
469
+ data.subtitles.push(non_i_stem_type());
470
+ }
471
+
472
+ if (data.loc) {
473
+ const loc_sg = Array.from(getNominalForm(data.forms, "dat_sg") || []);
474
+ const abl_sg = getNominalForm(data.forms, "abl_sg") || [];
475
+ for (const form of abl_sg) {
476
+ insert_if_not(loc_sg, form);
477
+ }
478
+ setNominalForm(data.forms, "loc_sg", loc_sg);
479
+ setNominalForm(data.forms, "loc_pl", getNominalForm(data.forms, "abl_pl") || []);
480
+ }
481
+ }],
482
+ ["4", (data, args) => {
483
+ const stem = args[0];
484
+
485
+ setNominalForm(data.forms, "nom_sg", [stem + "us"]);
486
+ setNominalForm(data.forms, "gen_sg", [stem + "ūs"]);
487
+ setNominalForm(data.forms, "dat_sg", [stem + "uī"]);
488
+ setNominalForm(data.forms, "acc_sg", [stem + "um"]);
489
+ setNominalForm(data.forms, "abl_sg", [stem + "ū"]);
490
+ setNominalForm(data.forms, "voc_sg", [stem + "us"]);
491
+
492
+ setNominalForm(data.forms, "nom_pl", [stem + "ūs"]);
493
+ setNominalForm(data.forms, "gen_pl", [stem + "uum"]);
494
+ setNominalForm(data.forms, "dat_pl", [stem + "ibus"]);
495
+ setNominalForm(data.forms, "acc_pl", [stem + "ūs"]);
496
+ setNominalForm(data.forms, "abl_pl", [stem + "ibus"]);
497
+ setNominalForm(data.forms, "voc_pl", [stem + "ūs"]);
498
+
499
+ if (data.types.has("echo")) {
500
+ data.subtitles.push("nominative/vocative singular in '-ō'");
501
+ setNominalForm(data.forms, "nom_sg", [stem + "ō"]);
502
+ setNominalForm(data.forms, "voc_sg", [stem + "ō"]);
503
+ } else if (data.types.has("argo")) {
504
+ data.subtitles.push("nominative/accusative/vocative singular in '-ō', ablative singular in '-uī'");
505
+ setNominalForm(data.forms, "nom_sg", [stem + "ō"]);
506
+ setNominalForm(data.forms, "acc_sg", [stem + "ō"]);
507
+ setNominalForm(data.forms, "abl_sg", [stem + "uī"]);
508
+ setNominalForm(data.forms, "voc_sg", [stem + "ō"]);
509
+ } else if (data.types.has("Callisto")) {
510
+ data.subtitles.push("all cases except the genitive singular in '-ō'");
511
+ setNominalForm(data.forms, "nom_sg", [stem + "ō"]);
512
+ setNominalForm(data.forms, "dat_sg", [stem + "ō"]);
513
+ setNominalForm(data.forms, "acc_sg", [stem + "ō"]);
514
+ setNominalForm(data.forms, "abl_sg", [stem + "ō"]);
515
+ setNominalForm(data.forms, "voc_sg", [stem + "ō"]);
516
+ }
517
+
518
+ if (data.types.has("N")) {
519
+ data.subtitles.push("neuter");
520
+
521
+ setNominalForm(data.forms, "nom_sg", [stem + "ū"]);
522
+ setNominalForm(data.forms, "dat_sg", [stem + "ū"]);
523
+ setNominalForm(data.forms, "acc_sg", [stem + "ū"]);
524
+ setNominalForm(data.forms, "voc_sg", [stem + "ū"]);
525
+
526
+ setNominalForm(data.forms, "nom_pl", [stem + "ua"]);
527
+ setNominalForm(data.forms, "acc_pl", [stem + "ua"]);
528
+ setNominalForm(data.forms, "voc_pl", [stem + "ua"]);
529
+ }
530
+
531
+ if (data.types.has("ubus")) {
532
+ data.subtitles.push("dative/ablative plural in '-ubus'");
533
+
534
+ setNominalForm(data.forms, "dat_pl", [stem + "ubus"]);
535
+ setNominalForm(data.forms, "abl_pl", [stem + "ubus"]);
536
+ } else if (data.types.has("not_ubus")) {
537
+ data.subtitles.push("'-ibus'");
538
+ }
539
+
540
+ if (data.loc) {
541
+ setNominalForm(data.forms, "loc_sg", getNominalForm(data.forms, "abl_sg") || []);
542
+ setNominalForm(data.forms, "loc_pl", getNominalForm(data.forms, "abl_pl") || []);
543
+ }
544
+
545
+ }],
546
+ ["5", (data, args) => {
547
+ let stem = args[0];
548
+
549
+ if (data.types.has("i")) {
550
+ stem = stem + "i";
551
+ }
552
+
553
+ setNominalForm(data.forms, "nom_sg", [stem + "ēs"]);
554
+ setNominalForm(data.forms, "gen_sg", [stem + "eī"]);
555
+ setNominalForm(data.forms, "dat_sg", [stem + "eī"]);
556
+ setNominalForm(data.forms, "acc_sg", [stem + "em"]);
557
+ setNominalForm(data.forms, "abl_sg", [stem + "ē"]);
558
+ setNominalForm(data.forms, "voc_sg", [stem + "ēs"]);
559
+
560
+ setNominalForm(data.forms, "nom_pl", [stem + "ēs"]);
561
+ setNominalForm(data.forms, "gen_pl", [stem + "ērum"]);
562
+ setNominalForm(data.forms, "dat_pl", [stem + "ēbus"]);
563
+ setNominalForm(data.forms, "acc_pl", [stem + "ēs"]);
564
+ setNominalForm(data.forms, "abl_pl", [stem + "ēbus"]);
565
+ setNominalForm(data.forms, "voc_pl", [stem + "ēs"]);
566
+
567
+ if (data.types.has("i")) {
568
+ setNominalForm(data.forms, "gen_sg", [stem + "ēī"]);
569
+ setNominalForm(data.forms, "dat_sg", [stem + "ēī"]);
570
+ }
571
+
572
+ if (data.loc) {
573
+ setNominalForm(data.forms, "loc_sg", [stem + "ē"]);
574
+ setNominalForm(data.forms, "loc_pl", [stem + "ēbus"]);
575
+ }
576
+ }],
577
+ ["0", (data, args) => {
578
+ const stem = args[0];
579
+
580
+ setNominalForm(data.forms, "nom_sg", [stem]);
581
+ setNominalForm(data.forms, "gen_sg", [stem]);
582
+ setNominalForm(data.forms, "dat_sg", [stem]);
583
+ setNominalForm(data.forms, "acc_sg", [stem]);
584
+ setNominalForm(data.forms, "abl_sg", [stem]);
585
+ setNominalForm(data.forms, "voc_sg", [stem]);
586
+
587
+ setNominalForm(data.forms, "nom_pl", [stem]);
588
+ setNominalForm(data.forms, "gen_pl", [stem]);
589
+ setNominalForm(data.forms, "dat_pl", [stem]);
590
+ setNominalForm(data.forms, "acc_pl", [stem]);
591
+ setNominalForm(data.forms, "abl_pl", [stem]);
592
+ setNominalForm(data.forms, "voc_pl", [stem]);
593
+
594
+ if (data.loc) {
595
+ setNominalForm(data.forms, "loc_sg", [stem]);
596
+ setNominalForm(data.forms, "loc_pl", [stem]);
597
+ }
598
+ }],
599
+ ["indecl", (data, args) => {
600
+ data.title = "Not declined; used only in the nominative and accusative singular.";
601
+
602
+ const stem = args[0];
603
+
604
+ setNominalForm(data.forms, "nom_sg", ["-"]);
605
+ setNominalForm(data.forms, "gen_sg", ["-"]);
606
+ setNominalForm(data.forms, "dat_sg", ["-"]);
607
+ setNominalForm(data.forms, "acc_sg", ["-"]);
608
+ setNominalForm(data.forms, "abl_sg", ["-"]);
609
+ setNominalForm(data.forms, "voc_sg", ["-"]);
610
+
611
+ setNominalForm(data.forms, "nom_pl", ["-"]);
612
+ setNominalForm(data.forms, "gen_pl", ["-"]);
613
+ setNominalForm(data.forms, "dat_pl", ["-"]);
614
+ setNominalForm(data.forms, "acc_pl", ["-"]);
615
+ setNominalForm(data.forms, "abl_pl", ["-"]);
616
+ setNominalForm(data.forms, "voc_pl", ["-"]);
617
+
618
+ setNominalForm(data.forms, "nom_sg", [stem]);
619
+ setNominalForm(data.forms, "acc_sg", [stem]);
620
+ data.num = NumberTantum.Singular;
621
+ }],
622
+ ["irreg", (data, args) => {
623
+ const stem = args[0];
624
+ setNominalForm(data.forms, "nom_sg", ["-"]);
625
+ setNominalForm(data.forms, "gen_sg", ["-"]);
626
+ setNominalForm(data.forms, "dat_sg", ["-"]);
627
+ setNominalForm(data.forms, "acc_sg", ["-"]);
628
+ setNominalForm(data.forms, "abl_sg", ["-"]);
629
+ setNominalForm(data.forms, "voc_sg", ["-"]);
630
+
631
+ setNominalForm(data.forms, "nom_pl", ["-"]);
632
+ setNominalForm(data.forms, "gen_pl", ["-"]);
633
+ setNominalForm(data.forms, "dat_pl", ["-"]);
634
+ setNominalForm(data.forms, "acc_pl", ["-"]);
635
+ setNominalForm(data.forms, "abl_pl", ["-"]);
636
+ setNominalForm(data.forms, "voc_pl", ["-"]);
637
+
638
+ if (stem == "bōs") {
639
+ setNominalForm(data.forms, "nom_sg", ["bōs"]);
640
+ setNominalForm(data.forms, "gen_sg", ["bovis"]);
641
+ setNominalForm(data.forms, "dat_sg", ["bovī"]);
642
+ setNominalForm(data.forms, "acc_sg", ["bovem"]);
643
+ setNominalForm(data.forms, "abl_sg", ["bove"]);
644
+ setNominalForm(data.forms, "voc_sg", ["bōs"]);
645
+
646
+ setNominalForm(data.forms, "nom_pl", ["bovēs"]);
647
+ setNominalForm(data.forms, "gen_pl", ["boum"]);
648
+ setNominalForm(data.forms, "dat_pl", ["bōbus", "būbus"]);
649
+ setNominalForm(data.forms, "acc_pl", ["bovēs"]);
650
+ setNominalForm(data.forms, "abl_pl", ["bōbus", "būbus"]);
651
+ setNominalForm(data.forms, "voc_pl", ["bovēs"]);
652
+ } else if (stem == "cherub") {
653
+ data.title = "mostly indeclinable";
654
+ data.subtitles.push("with a distinct plural");
655
+
656
+ setNominalForm(data.forms, "nom_sg", ["cherub"]);
657
+ setNominalForm(data.forms, "gen_sg", ["cherub"]);
658
+ setNominalForm(data.forms, "dat_sg", ["cherub"]);
659
+ setNominalForm(data.forms, "acc_sg", ["cherub"]);
660
+ setNominalForm(data.forms, "abl_sg", ["cherub"]);
661
+ setNominalForm(data.forms, "voc_sg", ["cherub"]);
662
+
663
+ setNominalForm(data.forms, "nom_pl", ["cherubim", "cherubin"]);
664
+ setNominalForm(data.forms, "gen_pl", ["cherubim", "cherubin"]);
665
+ setNominalForm(data.forms, "dat_pl", ["cherubim", "cherubin"]);
666
+ setNominalForm(data.forms, "acc_pl", ["cherubim", "cherubin"]);
667
+ setNominalForm(data.forms, "abl_pl", ["cherubim", "cherubin"]);
668
+ setNominalForm(data.forms, "voc_pl", ["cherubim", "cherubin"]);
669
+ } else if (stem == "deus") {
670
+ setNominalForm(data.forms, "nom_sg", ["deus"]);
671
+ setNominalForm(data.forms, "gen_sg", ["deī"]);
672
+ setNominalForm(data.forms, "dat_sg", ["deō"]);
673
+ setNominalForm(data.forms, "acc_sg", ["deum"]);
674
+ setNominalForm(data.forms, "abl_sg", ["deō"]);
675
+ setNominalForm(data.forms, "voc_sg", ["deus"]);
676
+
677
+ setNominalForm(data.forms, "nom_pl", ["dī", "diī", "deī"]);
678
+ setNominalForm(data.forms, "gen_pl", ["deōrum", "deûm", "divom"]);
679
+ setNominalForm(data.forms, "dat_pl", ["dīs", "diīs", "deīs"]);
680
+ setNominalForm(data.forms, "acc_pl", ["deōs"]);
681
+ setNominalForm(data.forms, "abl_pl", ["dīs", "diīs", "deīs"]);
682
+ setNominalForm(data.forms, "voc_pl", ["dī", "diī", "deī"]);
683
+ } else if (stem == "Deus") {
684
+ setNominalForm(data.forms, "nom_sg", ["Deus"]);
685
+ setNominalForm(data.forms, "gen_sg", ["Deī"]);
686
+ setNominalForm(data.forms, "dat_sg", ["Deō"]);
687
+ setNominalForm(data.forms, "acc_sg", ["Deum"]);
688
+ setNominalForm(data.forms, "abl_sg", ["Deō"]);
689
+ setNominalForm(data.forms, "voc_sg", ["Deus"]);
690
+ data.num = NumberTantum.Singular;
691
+ } else if (stem == "domus") {
692
+ data.title = "fourth/second-declension noun";
693
+
694
+ setNominalForm(data.forms, "nom_sg", ["domus"]);
695
+ setNominalForm(data.forms, "gen_sg", ["domūs", "domī"]);
696
+ setNominalForm(data.forms, "dat_sg", ["domuī", "domō", "domū"]);
697
+ setNominalForm(data.forms, "acc_sg", ["domum"]);
698
+ setNominalForm(data.forms, "abl_sg", ["domū", "domō"]);
699
+ setNominalForm(data.forms, "voc_sg", ["domus"]);
700
+ setNominalForm(data.forms, "loc_sg", ["domī"]);
701
+
702
+ setNominalForm(data.forms, "nom_pl", ["domūs"]);
703
+ setNominalForm(data.forms, "gen_pl", ["domuum", "domōrum"]);
704
+ setNominalForm(data.forms, "dat_pl", ["domibus"]);
705
+ setNominalForm(data.forms, "acc_pl", ["domūs", "domōs"]);
706
+ setNominalForm(data.forms, "abl_pl", ["domibus"]);
707
+ setNominalForm(data.forms, "voc_pl", ["domūs"]);
708
+ setNominalForm(data.forms, "loc_pl", ["domibus"]);
709
+
710
+ data.loc = true;
711
+ } else if (stem == "Iēsus" || stem == "Iēsūs") {
712
+ data.subtitles.push("highly irregular");
713
+ const ij = stem[0];
714
+ setNominalForm(data.forms, "nom_sg", [stem]);
715
+ setNominalForm(data.forms, "gen_sg", [ij + "ēsū"]);
716
+ setNominalForm(data.forms, "dat_sg", [ij + "ēsū"]);
717
+ setNominalForm(data.forms, "acc_sg", [ij + "ēsum"]);
718
+ setNominalForm(data.forms, "abl_sg", [ij + "ēsū"]);
719
+ setNominalForm(data.forms, "voc_sg", [ij + "ēsū"]);
720
+ data.num = NumberTantum.Singular;
721
+ } else if (stem == "Jesus") {
722
+ data.subtitles.push("highly irregular");
723
+ const ij = stem[0];
724
+ setNominalForm(data.forms, "nom_sg", [stem]);
725
+ setNominalForm(data.forms, "gen_sg", [ij + "esu"]);
726
+ setNominalForm(data.forms, "dat_sg", [ij + "esu"]);
727
+ setNominalForm(data.forms, "acc_sg", [ij + "esum"]);
728
+ setNominalForm(data.forms, "abl_sg", [ij + "esu"]);
729
+ setNominalForm(data.forms, "voc_sg", [ij + "esu"]);
730
+ data.num = NumberTantum.Singular;
731
+ } else if (stem == "iūgerum" || stem == "jūgerum") {
732
+ const ij = stem[0];
733
+ data.title = "second–third-declension hybrid noun";
734
+ data.subtitles.push("neuter");
735
+
736
+ setNominalForm(data.forms, "nom_sg", [ij + "ūgerum"]);
737
+ setNominalForm(data.forms, "gen_sg", [ij + "ūgerī"]);
738
+ setNominalForm(data.forms, "dat_sg", [ij + "ūgerō"]);
739
+ setNominalForm(data.forms, "acc_sg", [ij + "ūgerum"]);
740
+ setNominalForm(data.forms, "abl_sg", [ij + "ūgerō"]);
741
+ setNominalForm(data.forms, "voc_sg", [ij + "ūgerum"]);
742
+ setNominalForm(data.forms, "nom_pl", [ij + "ūgera"]);
743
+ setNominalForm(data.forms, "gen_pl", [ij + "ūgerum"]);
744
+ setNominalForm(data.forms, "dat_pl", [ij + "ūgeribus"]);
745
+ setNominalForm(data.forms, "acc_pl", [ij + "ūgera"]);
746
+ setNominalForm(data.forms, "abl_pl", [ij + "ūgeribus", ij + "ūgerīs"]);
747
+ setNominalForm(data.forms, "voc_pl", [ij + "ūgera"]);
748
+
749
+ data.notes.set("abl_pl2", "Once only, in:<br/>M. Terentius Varro, 'Res Rusticae', bk I, ch. x");
750
+ } else if (stem == "sūs") {
751
+ setNominalForm(data.forms, "nom_sg", ["sūs"]);
752
+ setNominalForm(data.forms, "gen_sg", ["suis"]);
753
+ setNominalForm(data.forms, "dat_sg", ["suī"]);
754
+ setNominalForm(data.forms, "acc_sg", ["suem"]);
755
+ setNominalForm(data.forms, "abl_sg", ["sue"]);
756
+ setNominalForm(data.forms, "voc_sg", ["sūs"]);
757
+
758
+ setNominalForm(data.forms, "nom_pl", ["suēs"]);
759
+ setNominalForm(data.forms, "gen_pl", ["suum"]);
760
+ setNominalForm(data.forms, "dat_pl", ["suibus", "sūbus", "subus"]);
761
+ setNominalForm(data.forms, "acc_pl", ["suēs"]);
762
+ setNominalForm(data.forms, "abl_pl", ["suibus", "sūbus", "subus"]);
763
+ setNominalForm(data.forms, "voc_pl", ["suēs"]);
764
+ } else if (stem == "ēthos") {
765
+ data.subtitles.push("irregular");
766
+ data.subtitles.push("Greek-type");
767
+
768
+ setNominalForm(data.forms, "nom_sg", ["ēthos"]);
769
+ setNominalForm(data.forms, "gen_sg", ["ētheos"]);
770
+ setNominalForm(data.forms, "acc_sg", ["ēthos"]);
771
+ setNominalForm(data.forms, "voc_sg", ["ēthos"]);
772
+
773
+ setNominalForm(data.forms, "nom_pl", ["ēthea", "ēthē"]);
774
+ setNominalForm(data.forms, "dat_pl", ["ēthesi", "ēthesin"]);
775
+ setNominalForm(data.forms, "acc_pl", ["ēthea", "ēthē"]);
776
+ setNominalForm(data.forms, "abl_pl", ["ēthesi", "ēthesin"]);
777
+ setNominalForm(data.forms, "voc_pl", ["ēthea", "ēthē"]);
778
+ } else if (stem == "lexis") {
779
+ data.subtitles.push("irregular");
780
+ data.subtitles.push("Greek-type");
781
+
782
+ setNominalForm(data.forms, "nom_sg", ["lexis"]);
783
+ setNominalForm(data.forms, "gen_sg", ["lexeōs"]);
784
+ setNominalForm(data.forms, "acc_pl", ["lexeis"]);
785
+ } else if (stem == "Athōs") {
786
+ data.subtitles.push("highly irregular");
787
+ data.subtitles.push("Greek-type");
788
+
789
+ setNominalForm(data.forms, "nom_sg", ["Athōs"]);
790
+ setNominalForm(data.forms, "gen_sg", ["Athō"]);
791
+ setNominalForm(data.forms, "dat_sg", ["Athō"]);
792
+ setNominalForm(data.forms, "acc_sg", ["Athō", "Athōn"]);
793
+ setNominalForm(data.forms, "abl_sg", ["Athō"]);
794
+ setNominalForm(data.forms, "voc_sg", ["Athōs"]);
795
+ data.num = NumberTantum.Singular;
796
+ } else if (stem == "vēnum") {
797
+ data.title = "fourth/second-declension noun";
798
+ data.subtitles.push("defective");
799
+
800
+ setNominalForm(data.forms, "dat_sg", ["vēnuī", "vēnō"]);
801
+ setNominalForm(data.forms, "acc_sg", ["vēnum"]);
802
+ data.num = NumberTantum.Singular;
803
+ } else if (stem == "vīs") {
804
+ data.subtitles.push("irregular");
805
+ data.subtitles.push("defective");
806
+
807
+ setNominalForm(data.forms, "nom_sg", ["vīs"]);
808
+ setNominalForm(data.forms, "gen_sg", ["*vīs"]);
809
+ setNominalForm(data.forms, "dat_sg", ["*vī"]);
810
+ setNominalForm(data.forms, "acc_sg", ["vim"]);
811
+ setNominalForm(data.forms, "abl_sg", ["vī"]);
812
+ setNominalForm(data.forms, "voc_sg", ["vīs"]);
813
+
814
+ setNominalForm(data.forms, "nom_pl", ["vīrēs"]);
815
+ setNominalForm(data.forms, "gen_pl", ["vīrium"]);
816
+ setNominalForm(data.forms, "dat_pl", ["vīribus"]);
817
+ setNominalForm(data.forms, "acc_pl", ["vīrēs", "vīrīs"]);
818
+ setNominalForm(data.forms, "abl_pl", ["vīribus"]);
819
+ setNominalForm(data.forms, "voc_pl", ["vīrēs"]);
820
+ } else {
821
+ throw Error(`Stem ${stem} not recognized.`);
822
+ }
823
+ }],
824
+ ]);
825
+
826
+ const acc_sg_i_stem_subtypes = new Map<string, [string[], string]>([
827
+ ["acc_im", [["im"], "accusative singular in '-im'"]],
828
+ ["acc_im_in", [["im", "in"], "accusative singular in '-im' or '-in'"]],
829
+ ["acc_im_in_em", [["im", "in", "em"], "accusative singular in '-im', '-in' or '-em'"]],
830
+ ["acc_im_em", [["im", "em"], "accusative singular in '-im' or '-em'"]],
831
+ ["acc_im_occ_em", [["im", "em"], "accusative singular in '-im' or occasionally '-em'"]],
832
+ ["acc_em_im", [["em", "im"], "accusative singular in '-em' or '-im'"]],
833
+ ]);
834
+
835
+ const abl_sg_i_stem_subtypes = new Map<string, [string[], string]>([
836
+ ["abl_i", [["ī"], "ablative singular in '-ī'"]],
837
+ ["abl_i_e", [["ī", "e"], "ablative singular in '-ī' or '-e'"]],
838
+ ["abl_e_i", [["e", "ī"], "ablative singular in '-e' or '-ī'"]],
839
+ ["abl_e_occ_i", [["e", "ī"], "ablative singular in '-e' or occasionally '-ī'"]],
840
+ ]);
841
+
842
+ function extract_stem(form: string, ending: string): string {
843
+ const base = form.match(new RegExp(`^(.*)${ending}$`));
844
+ if (!base) {
845
+ throw Error(`Form ${form} should end in -${ending}`);
846
+ }
847
+ return base[1];
848
+ }
849
+
850
+ function insert_if_not(data: string[], entry: string, pos = 0) {
851
+ if (data.includes(entry)) {
852
+ return;
853
+ }
854
+ if (pos == 0) {
855
+ data.push(entry);
856
+ } else {
857
+ data.splice(pos - 1, 0, entry);
858
+ }
859
+ }