@fpw/en-wiktionary-la-modules 0.0.16 → 0.1.3

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 (37) hide show
  1. package/dist/LaEngine.d.ts +7 -8
  2. package/dist/LaEngine.js +1 -1
  3. package/dist/LaEngine.js.map +1 -1
  4. package/dist/modules/conjugation/LaVerb.d.ts +5 -3
  5. package/dist/modules/conjugation/LaVerb.js +207 -31
  6. package/dist/modules/conjugation/LaVerb.js.map +1 -1
  7. package/dist/modules/conjugation/VerbType.d.ts +5 -1
  8. package/dist/modules/conjugation/VerbType.js +4 -0
  9. package/dist/modules/conjugation/VerbType.js.map +1 -1
  10. package/dist/modules/declination/LaAdjData.d.ts +1 -1
  11. package/dist/modules/declination/LaAdjData.js +45 -24
  12. package/dist/modules/declination/LaAdjData.js.map +1 -1
  13. package/dist/modules/declination/LaNominal.d.ts +6 -3
  14. package/dist/modules/declination/LaNominal.js +190 -168
  15. package/dist/modules/declination/LaNominal.js.map +1 -1
  16. package/dist/modules/declination/LaNounData.js +65 -64
  17. package/dist/modules/declination/LaNounData.js.map +1 -1
  18. package/dist/modules/declination/LaPersonalPronoun.d.ts +7 -29
  19. package/dist/modules/declination/LaPersonalPronoun.js +73 -56
  20. package/dist/modules/declination/LaPersonalPronoun.js.map +1 -1
  21. package/dist/modules/declination/NominalType.d.ts +116 -0
  22. package/dist/modules/declination/NominalType.js +142 -0
  23. package/dist/modules/declination/NominalType.js.map +1 -0
  24. package/dist/modules/headword/HeadWord.d.ts +3 -3
  25. package/dist/modules/headword/HeadwordParser.d.ts +2 -2
  26. package/dist/modules/headword/HeadwordParser.js.map +1 -1
  27. package/package.json +8 -9
  28. package/src/LaEngine.ts +8 -9
  29. package/src/modules/conjugation/LaVerb.ts +213 -36
  30. package/src/modules/conjugation/VerbType.ts +4 -0
  31. package/src/modules/declination/LaAdjData.ts +47 -24
  32. package/src/modules/declination/LaNominal.ts +216 -184
  33. package/src/modules/declination/LaNounData.ts +67 -66
  34. package/src/modules/declination/LaPersonalPronoun.ts +76 -63
  35. package/src/modules/declination/NominalType.ts +153 -0
  36. package/src/modules/headword/HeadWord.ts +3 -3
  37. package/src/modules/headword/HeadwordParser.ts +18 -18
@@ -3,7 +3,7 @@
3
3
  * It was converted from Lua to TypeScript by Folke Will <folko@solhost.org>.
4
4
  *
5
5
  * Original source: https://en.wiktionary.org/wiki/Module:la-nominal
6
- * Based on version: https://en.wiktionary.org/w/index.php?title=Module:la-nominal&oldid=62391877
6
+ * Based on version: https://en.wiktionary.org/w/index.php?title=Module:la-nominal&oldid=68705587
7
7
  *
8
8
  * Lua idioms, function and variable names kept as in the original in order to easily
9
9
  * backport later changes to this implementation.
@@ -16,6 +16,7 @@ import { ArgMap, array_equals, extract_base, FormMap, is_enum_value, read_list,
16
16
  import { m_adj_decl } from "./LaAdjData";
17
17
  import { m_noun_decl } from "./LaNounData";
18
18
  import { getNominalForm, NominalForm, setNominalForm } from "./NominalForm";
19
+ import { addNominalType, delNominalType, hasNominalType, NominalType } from "./NominalType";
19
20
 
20
21
  export interface DeclOptions {
21
22
  suppressOldGenitive?: boolean;
@@ -44,6 +45,7 @@ interface SegmentRun {
44
45
  gender?: Gender;
45
46
  is_adj?: boolean;
46
47
  propses: DeclProp[];
48
+ apparent_decl?: string;
47
49
  }
48
50
 
49
51
  interface Segment {
@@ -56,7 +58,7 @@ interface Segment {
56
58
  orig_lemma: string;
57
59
  stem2?: string;
58
60
  gender?: Gender;
59
- types: Set<string>;
61
+ types: Set<NominalType>;
60
62
  num?: NumberTantum;
61
63
  loc: boolean;
62
64
  args: string[];
@@ -78,7 +80,7 @@ interface Alternant {
78
80
  export interface DeclProp {
79
81
  decl: string;
80
82
  headword_decl: string;
81
- types: Set<string>;
83
+ types: Set<NominalType>;
82
84
  }
83
85
 
84
86
  interface Declensions {
@@ -90,6 +92,7 @@ interface Declensions {
90
92
  categories: string[];
91
93
  voc: boolean;
92
94
  noneut: boolean;
95
+ nomf: boolean;
93
96
  }
94
97
 
95
98
  export interface DeclensionData {
@@ -126,6 +129,7 @@ export interface AdjectiveData extends DeclensionData {
126
129
 
127
130
  voc: boolean;
128
131
  noneut: boolean;
132
+ nomf: boolean;
129
133
 
130
134
  // only in headwords
131
135
  comp: string[];
@@ -142,7 +146,7 @@ export interface SegmentData {
142
146
  loc?: boolean;
143
147
  pos: string;
144
148
  forms: FormMap<NominalForm>;
145
- types: Set<string>;
149
+ types: Set<NominalType>;
146
150
  categories: string[];
147
151
  notes: Map<string, string>;
148
152
 
@@ -150,12 +154,13 @@ export interface SegmentData {
150
154
  gender?: Gender;
151
155
  voc?: boolean;
152
156
  noneut?: boolean;
157
+ nomf?: boolean;
153
158
  }
154
159
 
155
160
  type EndingTable = [
156
161
  string | string[],
157
162
  string,
158
- string[],
163
+ NominalType[],
159
164
  ((base: string, stem2: string) => [string, string])?
160
165
  ][];
161
166
 
@@ -331,6 +336,7 @@ export class LaNominal {
331
336
  user_specified: new Set(),
332
337
  voc: declensions.voc,
333
338
  noneut: args.has("noneut") || declensions.noneut,
339
+ nomf: args.has("nomf") || declensions.nomf,
334
340
  pos: pos,
335
341
  num_type: args.get("type"),
336
342
 
@@ -378,10 +384,13 @@ export class LaNominal {
378
384
  if (parsed_run.loc) {
379
385
  post_text_parts.push(", with locative");
380
386
  }
381
- if (parsed_run.num == "sg") {
382
- post_text_parts.push(", singular only");
383
- } else if (parsed_run.num == "pl") {
384
- post_text_parts.push(", plural only");
387
+
388
+ if (parsed_run.apparent_decl == "indecl") {
389
+ if (parsed_run.num == "sg") {
390
+ post_text_parts.push(", singular only");
391
+ } else if (parsed_run.num == "pl") {
392
+ post_text_parts.push(", plural only");
393
+ }
385
394
  }
386
395
 
387
396
  const post_text = post_text_parts.join("");
@@ -441,6 +450,9 @@ export class LaNominal {
441
450
  if (data.noneut && slot.match(/_n/)) {
442
451
  setNominalForm(data.forms, slot, undefined);
443
452
  }
453
+ if (data.nomf && (slot.match(/_m/) || slot.match(/_f/))) {
454
+ setNominalForm(data.forms, slot, undefined);
455
+ }
444
456
  let val: string[] | undefined;
445
457
  const ovr = args.get(slot);
446
458
  if (ovr) {
@@ -619,7 +631,7 @@ export class LaNominal {
619
631
  num: num,
620
632
  gender: gender,
621
633
  is_adj: is_adj,
622
- propses: propses
634
+ propses: propses,
623
635
  };
624
636
  }
625
637
 
@@ -736,7 +748,7 @@ export class LaNominal {
736
748
  loc: loc,
737
749
  num: num,
738
750
  gender: gender,
739
- propses: propses
751
+ propses: propses,
740
752
  };
741
753
  }
742
754
 
@@ -754,7 +766,7 @@ export class LaNominal {
754
766
  const stems = stem_part.split("/");
755
767
  const specs = spec_part.split(".");
756
768
 
757
- const types = new Set<string>();
769
+ const types = new Set<NominalType>();
758
770
  let num: NumberTantum | undefined;
759
771
  let loc = false;
760
772
 
@@ -769,7 +781,9 @@ export class LaNominal {
769
781
  const begins_with_hypen = m2[1];
770
782
  spec = m2[2];
771
783
  spec = begins_with_hypen + spec.replace(/-/g, "_");
772
- types.add(spec);
784
+ if (spec) {
785
+ addNominalType(types, spec);
786
+ }
773
787
  }
774
788
  }
775
789
  }
@@ -790,7 +804,7 @@ export class LaNominal {
790
804
 
791
805
  let headword_decl;
792
806
  let base;
793
- let detected_subtypes;
807
+ let detected_subtypes: Set<NominalType>;
794
808
 
795
809
  if (decl.match(/\+/)) {
796
810
  decl = decl.replace(/\+/g, "");
@@ -805,8 +819,8 @@ export class LaNominal {
805
819
  }
806
820
 
807
821
  for (const subtype of detected_subtypes) {
808
- if (types.has("-" + subtype)) {
809
- types.delete("-" + subtype);
822
+ if (hasNominalType(types, "-" + subtype)) {
823
+ delNominalType(types, "-" + subtype);
810
824
  } else {
811
825
  types.add(subtype);
812
826
  }
@@ -822,42 +836,48 @@ export class LaNominal {
822
836
  }
823
837
 
824
838
  for (const subtype of detected_subtypes) {
825
- if (types.has("-" + subtype)) {
826
- types.delete("-" + subtype);
827
- } else if ((subtype == "M" || subtype == "F" || subtype == "N") && (types.has("M") || types.has("F") || types.has("N"))) {
839
+ if (hasNominalType(types, "-" + subtype)) {
840
+ delNominalType(types, "-" + subtype);
841
+ } else if (
842
+ (subtype == NominalType.Masculine || subtype == NominalType.Feminine || subtype == NominalType.Neuter) &&
843
+ (types.has(NominalType.Masculine) || types.has(NominalType.Feminine) || types.has(NominalType.Neuter))
844
+ ) {
828
845
  // don't create conflicting gender specs
829
- } else if ((subtype == "sg" || subtype == "pl" || subtype == "both") && (types.has("sg") || types.has("pl") || types.has("both"))) {
846
+ } else if (
847
+ (subtype == NominalType.Singular || subtype == NominalType.Plural || subtype == NominalType.Both) &&
848
+ (types.has(NominalType.Singular) || types.has(NominalType.Plural) || types.has(NominalType.Both))
849
+ ) {
830
850
  // don't create conflicting number restrictions
831
851
  } else {
832
852
  types.add(subtype);
833
853
  }
834
854
  }
835
855
 
836
- if (!types.has("pl") && !types.has("both") && lemma.match(/^[A-ZĀĒĪŌŪȲĂĔĬŎŬ]/)) {
837
- types.add("sg");
856
+ if (!types.has(NominalType.Plural) && !types.has(NominalType.Both) && lemma.match(/^[A-ZĀĒĪŌŪȲĂĔĬŎŬ]/)) {
857
+ types.add(NominalType.Singular);
838
858
  }
839
859
  }
840
860
 
841
- if (types.has("loc")) {
861
+ if (types.has(NominalType.Locative)) {
842
862
  loc = true;
843
- types.delete("loc");
863
+ types.delete(NominalType.Locative);
844
864
  }
845
865
 
846
866
  let gender: Gender | undefined;
847
- if (types.has("M")) {
867
+ if (types.has(NominalType.Masculine)) {
848
868
  gender = Gender.M;
849
- } else if (types.has("F")) {
869
+ } else if (types.has(NominalType.Feminine)) {
850
870
  gender = Gender.F;
851
- } else if (types.has("N")) {
871
+ } else if (types.has(NominalType.Neuter)) {
852
872
  gender = Gender.N;
853
873
  }
854
874
 
855
- if (types.has("pl")) {
875
+ if (types.has(NominalType.Plural)) {
856
876
  num = NumberTantum.Plural;
857
- types.delete("pl");
858
- } else if (types.has("sg")) {
877
+ types.delete(NominalType.Plural);
878
+ } else if (types.has(NominalType.Singular)) {
859
879
  num = NumberTantum.Singular;
860
- types.delete("sg");
880
+ types.delete(NominalType.Singular);
861
881
  }
862
882
 
863
883
  const args = [base, stem2];
@@ -878,10 +898,10 @@ export class LaNominal {
878
898
  };
879
899
  }
880
900
 
881
- private detect_adj_type_and_subtype(lemma: string, stem2: string, typ: string, subtypes: Set<string>): [any, any, any, any] {
882
- if (!typ.match(/^[0123]/) && !typ.match(/^irreg/)) {
883
- subtypes = new Set(subtypes);
884
- subtypes.add(typ);
901
+ private detect_adj_type_and_subtype(lemma: string, stem2: string, typ: string, subtypes: Set<NominalType>): [any, any, any, any] {
902
+ if (!typ.match(/^[0123]/) && !typ.match(/^irreg/) && typ) {
903
+ subtypes = new Set<NominalType>(subtypes);
904
+ addNominalType(subtypes, typ);
885
905
  typ = "";
886
906
  }
887
907
 
@@ -905,17 +925,17 @@ export class LaNominal {
905
925
  ["us", "1&2", []],
906
926
  ["a", "1&2", []],
907
927
  ["um", "1&2", []],
908
- ["ī", "1&2", ["pl"]],
909
- ["ae", "1&2", ["pl"]],
910
- ["a", "1&2", ["pl"]],
911
- ["os", "1&2", ["greekA", "-greekE"]],
912
- ["os", "1&2", ["greekE", "-greekA"]],
913
- ["ē", "1&2", ["greekE", "-greekA"]],
914
- ["on", "1&2", ["greekA", "-greekE"]],
915
- ["on", "1&2", ["greekE", "-greekA"]],
916
- ["^(.*er)$", "1&2", ["er"]],
917
- ["^(.*ur)$", "1&2", ["er"]],
918
- ["^(h)ic$", "1&2", ["ic"]],
928
+ ["ī", "1&2", [NominalType.Plural]],
929
+ ["ae", "1&2", [NominalType.Plural]],
930
+ ["a", "1&2", [NominalType.Plural]],
931
+ ["os", "1&2", [NominalType.GreekA, NominalType.NoGreekE]],
932
+ ["os", "1&2", [NominalType.GreekE, NominalType.NoGreekA]],
933
+ ["ē", "1&2", [NominalType.GreekE, NominalType.NoGreekA]],
934
+ ["on", "1&2", [NominalType.GreekA, NominalType.NoGreekE]],
935
+ ["on", "1&2", [NominalType.GreekE, NominalType.NoGreekA]],
936
+ ["^(.*er)$", "1&2", [NominalType.Er]],
937
+ ["^(.*ur)$", "1&2", [NominalType.Er]],
938
+ ["^(h)ic$", "1&2", [NominalType.Ic]],
919
939
  ];
920
940
 
921
941
  const decl3_entries: EndingTable = [
@@ -924,16 +944,16 @@ export class LaNominal {
924
944
  ["e", "3-2", []],
925
945
  ["^(.*[ij])or$", "3-C", []],
926
946
  ["^(min)or$", "3-C", []],
927
- ["^(.*ēs)$", "3-1", ["I"]],
928
- ["^(.*ēs)$", "3-1", ["par"]],
929
- ["^(.*[ij])ōrēs$", "3-C", ["pl"]],
930
- ["^(min)ōrēs$", "3-C", ["pl"]],
931
- ["ēs", "3-2", ["pl", "I"]],
932
- ["ēs", "3-1", ["pl", "par"], base_as_stem2],
933
- ["ia", "3-2", ["pl", "I"]],
934
- ["a", "3-1", ["pl", "par"], base_as_stem2],
935
- ["", "3-1", ["I"]],
936
- ["", "3-1", ["par"]],
947
+ ["^(.*ēs)$", "3-1", [NominalType.I]],
948
+ ["^(.*ēs)$", "3-1", [NominalType.Par]],
949
+ ["^(.*[ij])ōrēs$", "3-C", [NominalType.Plural]],
950
+ ["^(min)ōrēs$", "3-C", [NominalType.Plural]],
951
+ ["ēs", "3-2", [NominalType.Plural, NominalType.I]],
952
+ ["ēs", "3-1", [NominalType.Plural, NominalType.Par], base_as_stem2],
953
+ ["ia", "3-2", [NominalType.Plural, NominalType.I]],
954
+ ["a", "3-1", [NominalType.Plural, NominalType.Par], base_as_stem2],
955
+ ["", "3-1", [NominalType.I]],
956
+ ["", "3-1", [NominalType.Par]],
937
957
  ];
938
958
 
939
959
  if (!typ) {
@@ -952,77 +972,77 @@ export class LaNominal {
952
972
  } else if (typ == "1-1") {
953
973
  return this.get_adj_type_and_subtype_by_ending(lemma, stem2, typ, subtypes, [
954
974
  ["a", "1-1", []],
955
- ["ae", "1-1", ["pl"]]
975
+ ["ae", "1-1", [NominalType.Plural]]
956
976
  ]);
957
977
  } else if (typ == "2-2") {
958
978
  return this.get_adj_type_and_subtype_by_ending(lemma, stem2, typ, subtypes, [
959
979
  ["us", "2-2", []],
960
980
  ["um", "2-2", []],
961
- ["ī", "2-2", ["pl"]],
962
- ["a", "2-2", ["pl"]],
963
- ["os", "2-2", ["greek"]],
964
- ["on", "2-2", ["greek"]],
965
- ["oe", "2-2", ["greek", "pl"]],
981
+ ["ī", "2-2", [NominalType.Plural]],
982
+ ["a", "2-2", [NominalType.Plural]],
983
+ ["os", "2-2", [NominalType.greek]],
984
+ ["on", "2-2", [NominalType.greek]],
985
+ ["oe", "2-2", [NominalType.greek, NominalType.Plural]],
966
986
  ]);
967
987
  } else if (typ == "3-1") {
968
988
  return this.get_adj_type_and_subtype_by_ending(lemma, stem2, typ, subtypes, [
969
- ["^(.*ēs)$", "3-1", ["I"]],
970
- ["^(.*ēs)$", "3-1", ["par"]],
971
- ["ēs", "3-1", ["pl", "I"], base_as_stem2],
972
- ["ēs", "3-1", ["pl", "par"], base_as_stem2],
973
- ["ia", "3-1", ["pl", "I"], base_as_stem2],
974
- ["a", "3-1", ["pl", "par"], base_as_stem2],
975
- ["", "3-1", ["I"]],
976
- ["", "3-1", ["par"]],
989
+ ["^(.*ēs)$", "3-1", [NominalType.I]],
990
+ ["^(.*ēs)$", "3-1", [NominalType.Par]],
991
+ ["ēs", "3-1", [NominalType.Plural, NominalType.I], base_as_stem2],
992
+ ["ēs", "3-1", [NominalType.Plural, NominalType.Par], base_as_stem2],
993
+ ["ia", "3-1", [NominalType.Plural, NominalType.I], base_as_stem2],
994
+ ["a", "3-1", [NominalType.Plural, NominalType.Par], base_as_stem2],
995
+ ["", "3-1", [NominalType.I]],
996
+ ["", "3-1", [NominalType.Par]],
977
997
  ], decl3_stem2);
978
998
  } else if (typ == "3-2") {
979
999
  return this.get_adj_type_and_subtype_by_ending(lemma, stem2, typ, subtypes, [
980
1000
  ["is", "3-2", []],
981
1001
  ["e", "3-2", []],
982
1002
  ["ēs", "3-2", []],
983
- ["ēs", "3-2", ["pl"]],
984
- ["ia", "3-2", ["pl"]],
1003
+ ["ēs", "3-2", [NominalType.Plural]],
1004
+ ["ia", "3-2", [NominalType.Plural]],
985
1005
  ], decl3_stem2);
986
1006
  } else if (typ == "3-C") {
987
1007
  return this.get_adj_type_and_subtype_by_ending(lemma, stem2, typ, subtypes, [
988
1008
  ["^(.*[ij])or$", "3-C", []],
989
1009
  ["^(min)or$", "3-C", []],
990
- ["^(.*[ij])ōrēs$", "3-C", ["pl"]],
991
- ["^(min)ōrēs$", "3-C", ["pl"]],
1010
+ ["^(.*[ij])ōrēs$", "3-C", [NominalType.Plural]],
1011
+ ["^(min)ōrēs$", "3-C", [NominalType.Plural]],
992
1012
  ], decl3_stem2);
993
1013
  } else if (typ == "irreg") {
994
1014
  return this.get_adj_type_and_subtype_by_ending(lemma, stem2, typ, subtypes, [
995
- ["^(duo)$", typ, ["pl"]],
996
- ["^(ambō)$", typ, ["pl"]],
997
- ["^(mīll?ia)$", typ, ["N", "pl"], constant_base("mīlle")],
1015
+ ["^(duo)$", typ, [NominalType.Plural]],
1016
+ ["^(ambō)$", typ, [NominalType.Plural]],
1017
+ ["^(mīll?ia)$", typ, [NominalType.Neuter, NominalType.Plural], constant_base("mīlle")],
998
1018
  ["^(ea)$", typ, [], constant_base("is")],
999
1019
  ["^(id)$", typ, [], constant_base("is")],
1000
- ["^([ei]ī)$", typ, ["pl"], constant_base("is")],
1001
- ["^(eae?)$", typ, ["pl"], constant_base("is")],
1020
+ ["^([ei]ī)$", typ, [NominalType.Plural], constant_base("is")],
1021
+ ["^(eae?)$", typ, [NominalType.Plural], constant_base("is")],
1002
1022
  ["^(eadem)$", typ, [], constant_base("īdem")],
1003
1023
  ["^([īi]dem)$", typ, [], constant_base("īdem")],
1004
- ["^(īdem)$", typ, ["pl"]],
1005
- ["^(eae?dem)$", typ, ["pl"], constant_base("īdem")],
1024
+ ["^(īdem)$", typ, [NominalType.Plural]],
1025
+ ["^(eae?dem)$", typ, [NominalType.Plural], constant_base("īdem")],
1006
1026
  ["^(i[lps][lst])a$", typ, [], (base: string, s2: string) => [base + "e", ""]],
1007
1027
  ["^(i[ls][lt])ud$", typ, [], (base: string, s2: string) => [base + "e", ""]],
1008
1028
  ["^(ipsum)$", typ, [], constant_base("ipse")],
1009
- ["^(i[lps][lst])ī$", typ, ["pl"], (base: string, s2: string) => [base + "e", ""]],
1010
- ["^(i[lps][lst])ae?$", typ, ["pl"], (base: string, s2: string) => [base + "e", ""]],
1029
+ ["^(i[lps][lst])ī$", typ, [NominalType.Plural], (base: string, s2: string) => [base + "e", ""]],
1030
+ ["^(i[lps][lst])ae?$", typ, [NominalType.Plural], (base: string, s2: string) => [base + "e", ""]],
1011
1031
  ["^(quī)$", typ, []],
1012
- ["^(quī)$", typ, ["pl"]],
1032
+ ["^(quī)$", typ, [NominalType.Plural]],
1013
1033
  ["^(quae)$", typ, [], constant_base("quī")],
1014
- ["^(quae)$", typ, ["pl"], constant_base("quī")],
1034
+ ["^(quae)$", typ, [NominalType.Plural], constant_base("quī")],
1015
1035
  ["^(quid)$", typ, [], constant_base("quis")],
1016
1036
  ["^(quod)$", typ, [], constant_base("quī")],
1017
1037
  ["^(qui[cd]quid)$", typ, [], constant_base("quisquis")],
1018
- ["^(quīquī)$", typ, ["pl"], constant_base("quisquis")],
1019
- ["^(quaequae)$", typ, ["pl"], constant_base("quisquis")],
1038
+ ["^(quīquī)$", typ, [NominalType.Plural], constant_base("quisquis")],
1039
+ ["^(quaequae)$", typ, [NominalType.Plural], constant_base("quisquis")],
1020
1040
  ["", typ, []],
1021
1041
  ]);
1022
1042
  } else {
1023
1043
  return this.get_adj_type_and_subtype_by_ending(lemma, stem2, typ, subtypes, [
1024
- ["ēs", typ, ["pl"], base_as_stem2],
1025
- ["ia", typ, ["pl"], base_as_stem2],
1044
+ ["ēs", typ, [NominalType.Plural], base_as_stem2],
1045
+ ["ia", typ, [NominalType.Plural], base_as_stem2],
1026
1046
  ["", typ, []],
1027
1047
  ], decl3_stem2);
1028
1048
  }
@@ -1032,23 +1052,23 @@ export class LaNominal {
1032
1052
  lemma: string,
1033
1053
  stem2: string,
1034
1054
  decltype: string | undefined,
1035
- specified_subtypes: Set<string>,
1055
+ specified_subtypes: Set<NominalType>,
1036
1056
  endings_and_subtypes: EndingTable,
1037
1057
  process_stem2?: (base: string) => string):
1038
- [string, string, string, string[]]
1058
+ [string, string, string, NominalType[]]
1039
1059
  {
1040
1060
  for (const [ending, rettype, subtypes, process_retval] of endings_and_subtypes) {
1041
1061
  let not_this_subtype = false;
1042
- if (specified_subtypes.has("pl") && !subtypes.includes("pl")) {
1062
+ if (specified_subtypes.has(NominalType.Plural) && !subtypes.includes(NominalType.Plural)) {
1043
1063
  not_this_subtype = true;
1044
1064
  } else {
1045
1065
  for (const subtype of subtypes) {
1046
- if (specified_subtypes.has("-" + subtype)) {
1066
+ if (!subtype.startsWith("-") && hasNominalType(specified_subtypes, "-" + subtype)) {
1047
1067
  not_this_subtype = true;
1048
1068
  break;
1049
1069
  }
1050
1070
  const must_not_be_present = subtype.match(/^-(.*)$/);
1051
- if (must_not_be_present && specified_subtypes.has(must_not_be_present[1])) {
1071
+ if (must_not_be_present && hasNominalType(specified_subtypes, must_not_be_present[1])) {
1052
1072
  not_this_subtype = true;
1053
1073
  break;
1054
1074
  }
@@ -1093,50 +1113,50 @@ export class LaNominal {
1093
1113
  }
1094
1114
  }
1095
1115
 
1096
- private detect_noun_subtype(lemma: string, stem2: string, typ: string, subtypes: Set<string>): [string, string, Set<string>] {
1116
+ private detect_noun_subtype(lemma: string, stem2: string, typ: string, subtypes: Set<NominalType>): [string, string, Set<NominalType>] {
1097
1117
  if (typ == "1") {
1098
1118
  return this.get_noun_subtype_by_ending(lemma, stem2, typ, subtypes, [
1099
- ["ām", ["F", "am"]],
1100
- ["ās", ["M", "Greek", "Ma"]],
1101
- ["ēs", ["M", "Greek", "Me"]],
1102
- ["ē", ["F", "Greek"]],
1103
- ["ae", ["F", "pl"]],
1104
- ["a", ["F"]],
1119
+ ["ām", [NominalType.Feminine, NominalType.Am]],
1120
+ ["ās", [NominalType.Masculine, NominalType.Greek, NominalType.Ma]],
1121
+ ["ēs", [NominalType.Masculine, NominalType.Greek, NominalType.Me]],
1122
+ ["ē", [NominalType.Feminine, NominalType.Greek]],
1123
+ ["ae", [NominalType.Feminine, NominalType.Plural]],
1124
+ ["a", [NominalType.Feminine]],
1105
1125
  ]);
1106
1126
  } else if (typ == "2") {
1107
1127
  let detected_subtypes;
1108
1128
  [lemma, stem2, detected_subtypes] = this.get_noun_subtype_by_ending(lemma, stem2, typ, subtypes, [
1109
- ["^(.*r)$", ["M", "er"]],
1110
- ["^(.*v)os$", ["M", "vos"]],
1111
- ["^(.*v)om$", ["N", "vom"]],
1112
- ["os", ["M", "Greek"]],
1113
- ["os", ["N", "Greek", "us"]],
1114
- ["on", ["N", "Greek"]],
1115
- ["^([A-ZĀĒĪŌŪȲĂĔĬŎŬ].*)ius$", ["M", "ius", "voci", "sg"]],
1116
- ["ius", ["M", "ius"]],
1117
- ["ium", ["N", "ium"]],
1118
- ["us", ["M"]],
1119
- ["us", ["N", "us"]],
1120
- ["um", ["N"]],
1121
- ["iī", ["M", "ius", "pl"]],
1122
- ["ia", ["N", "ium", "pl"]],
1123
- ["ī", ["M", "pl"]],
1124
- ["ī", ["N", "us", "pl"]],
1125
- ["a", ["N", "pl"]],
1129
+ ["^(.*r)$", [NominalType.Masculine, NominalType.Er]],
1130
+ ["^(.*v)os$", [NominalType.Masculine, NominalType.Vos]],
1131
+ ["^(.*v)om$", [NominalType.Neuter, NominalType.Vom]],
1132
+ ["os", [NominalType.Masculine, NominalType.Greek]],
1133
+ ["os", [NominalType.Neuter, NominalType.Greek, NominalType.Us]],
1134
+ ["on", [NominalType.Neuter, NominalType.Greek]],
1135
+ ["^([A-ZĀĒĪŌŪȲĂĔĬŎŬ].*)ius$", [NominalType.Masculine, NominalType.Ius, NominalType.VocI, NominalType.Singular]],
1136
+ [NominalType.Ius, [NominalType.Masculine, NominalType.Ius]],
1137
+ [NominalType.Ium, [NominalType.Neuter, NominalType.Ium]],
1138
+ [NominalType.Us, [NominalType.Masculine]],
1139
+ [NominalType.Us, [NominalType.Neuter, NominalType.Us]],
1140
+ ["um", [NominalType.Neuter]],
1141
+ ["iī", [NominalType.Masculine, NominalType.Ius, NominalType.Plural]],
1142
+ ["ia", [NominalType.Neuter, NominalType.Ium, NominalType.Plural]],
1143
+ ["ī", [NominalType.Masculine, NominalType.Plural]],
1144
+ ["ī", [NominalType.Neuter, NominalType.Us, NominalType.Plural]],
1145
+ ["a", [NominalType.Neuter, NominalType.Plural]],
1126
1146
  ]);
1127
1147
  stem2 = stem2 || lemma;
1128
1148
  return [lemma, stem2, detected_subtypes];
1129
1149
  } else if (typ == "3") {
1130
1150
  let match;
1131
- if (subtypes.has("pl")) {
1132
- if (subtypes.has("Greek")) {
1151
+ if (subtypes.has(NominalType.Plural)) {
1152
+ if (subtypes.has(NominalType.Greek)) {
1133
1153
  match = lemma.match(/^(.*)erēs$/);
1134
1154
  if (match) {
1135
- return [match[1] + "ēr", match[1] + "er", new Set(["er"])];
1155
+ return [match[1] + "ēr", match[1] + "er", new Set([NominalType.Er])];
1136
1156
  }
1137
1157
  match = lemma.match(/^(.*)ontēs$/);
1138
1158
  if (match) {
1139
- return [match[1] + "ōn", match[1] + "ont", new Set(["on"])];
1159
+ return [match[1] + "ōn", match[1] + "ont", new Set([NominalType.On])];
1140
1160
  }
1141
1161
  match = lemma.match(/^(.*)es$/);
1142
1162
  if (match) {
@@ -1146,11 +1166,11 @@ export class LaNominal {
1146
1166
  }
1147
1167
  match = lemma.match(/^(.*)ia$/);
1148
1168
  if (match) {
1149
- return ["foo", stem2 || match[1], new Set(["N", "I", "pure"])];
1169
+ return ["foo", stem2 || match[1], new Set([NominalType.Neuter, NominalType.I, NominalType.Pure])];
1150
1170
  }
1151
1171
  match = lemma.match(/^(.*)a$/);
1152
1172
  if (match) {
1153
- return ["foo", stem2 || match[1], new Set(["N"])];
1173
+ return ["foo", stem2 || match[1], new Set([NominalType.Neuter])];
1154
1174
  }
1155
1175
  match = lemma.match(/^(.*)ēs$/);
1156
1176
  if (match) {
@@ -1163,32 +1183,32 @@ export class LaNominal {
1163
1183
  let detected_subtypes;
1164
1184
  let base;
1165
1185
  let tmp;
1166
- if (subtypes.has("Greek")) {
1186
+ if (subtypes.has(NominalType.Greek)) {
1167
1187
  [base, tmp, detected_subtypes] = this.get_noun_subtype_by_ending(lemma, stem2, "", subtypes, [
1168
- [["is", ""], ["I"]],
1169
- ["ēr", ["er"]],
1170
- ["ōn", ["on"]],
1188
+ [["is", ""], [NominalType.I]],
1189
+ ["ēr", [NominalType.Er]],
1190
+ ["ōn", [NominalType.On]],
1171
1191
  ]);
1172
1192
  if (base) {
1173
1193
  return [lemma, stem2, detected_subtypes];
1174
1194
  }
1175
1195
  return [lemma, stem2, new Set()];
1176
1196
  }
1177
- if (!subtypes.has("N")) {
1197
+ if (!subtypes.has(NominalType.Neuter)) {
1178
1198
  [base, tmp, detected_subtypes] = this.get_noun_subtype_by_ending(lemma, stem2, "", subtypes, [
1179
- [["^([A-ZĀĒĪŌŪȲĂĔĬŎŬ].*pol)is$", ""], ["F", "polis", "sg", "loc"]],
1180
- [["tūdō", "tūdin"], ["F"]],
1181
- [["tās", "tāt"], ["F"]],
1182
- [["tūs", "tūt"], ["F"]],
1183
- [["tiō", "tiōn"], ["F"]],
1184
- [["siō", "siōn"], ["F"]],
1185
- [["xiō", "xiōn"], ["F"]],
1186
- [["gō", "gin"], ["F"]],
1187
- [["or", "ōr"], ["M"]],
1188
- [["trīx", "trīc"], ["F"]],
1189
- [["trix", "trīc"], ["F"]],
1190
- [["is", ""], ["I"]],
1191
- [["^([a-zāēīōūȳăĕĭŏŭ].*)ēs$", ""], ["I"]],
1199
+ [["^([A-ZĀĒĪŌŪȲĂĔĬŎŬ].*pol)is$", ""], [NominalType.Feminine, NominalType.Polis, NominalType.Singular, NominalType.Locative]],
1200
+ [["tūdō", "tūdin"], [NominalType.Feminine]],
1201
+ [["tās", "tāt"], [NominalType.Feminine]],
1202
+ [["tūs", "tūt"], [NominalType.Feminine]],
1203
+ [["tiō", "tiōn"], [NominalType.Feminine]],
1204
+ [["siō", "siōn"], [NominalType.Feminine]],
1205
+ [["xiō", "xiōn"], [NominalType.Feminine]],
1206
+ [["gō", "gin"], [NominalType.Feminine]],
1207
+ [["or", "ōr"], [NominalType.Masculine]],
1208
+ [["trīx", "trīc"], [NominalType.Feminine]],
1209
+ [["trix", "trīc"], [NominalType.Feminine]],
1210
+ [["is", ""], [NominalType.I]],
1211
+ [["^([a-zāēīōūȳăĕĭŏŭ].*)ēs$", ""], [NominalType.I]],
1192
1212
  ]);
1193
1213
  if (base) {
1194
1214
  return [lemma, stem2, detected_subtypes];
@@ -1196,49 +1216,49 @@ export class LaNominal {
1196
1216
  }
1197
1217
 
1198
1218
  [base, tmp, detected_subtypes] = this.get_noun_subtype_by_ending(lemma, stem2, "", subtypes, [
1199
- [["us", "or"], ["N"]],
1200
- [["us", "er"], ["N"]],
1201
- [["ma", "mat"], ["N"]],
1202
- [["men", "min"], ["N"]],
1203
- [["^([A-ZĀĒĪŌŪȲĂĔĬŎŬ].*)e$", ""], ["N", "sg"]],
1204
- [["e", ""], ["N", "I", "pure"]],
1205
- [["al", "āl"], ["N", "I", "pure"]],
1206
- [["ar", "ār"], ["N", "I", "pure"]],
1219
+ [["us", "or"], [NominalType.Neuter]],
1220
+ [["us", "er"], [NominalType.Neuter]],
1221
+ [["ma", "mat"], [NominalType.Neuter]],
1222
+ [["men", "min"], [NominalType.Neuter]],
1223
+ [["^([A-ZĀĒĪŌŪȲĂĔĬŎŬ].*)e$", ""], [NominalType.Neuter, NominalType.Singular]],
1224
+ [["e", ""], [NominalType.Neuter, NominalType.I, NominalType.Pure]],
1225
+ [["al", "āl"], [NominalType.Neuter, NominalType.I, NominalType.Pure]],
1226
+ [["ar", "ār"], [NominalType.Neuter, NominalType.I, NominalType.Pure]],
1207
1227
  ]);
1208
1228
  if (base) {
1209
1229
  return [lemma, stem2, detected_subtypes];
1210
1230
  }
1211
1231
  return [lemma, stem2, new Set()];
1212
1232
  } else if (typ == "4") {
1213
- if (subtypes.has("echo") || subtypes.has("argo") || subtypes.has("Callisto")) {
1233
+ if (subtypes.has(NominalType.Echo) || subtypes.has(NominalType.argo) || subtypes.has(NominalType.Callisto)) {
1214
1234
  const match = lemma.match(/^(.*)ō$/);
1215
1235
  if (!match) {
1216
1236
  throw Error(`Declension-4 noun of subtype .echo, .argo or .Callisto should end in -ō: ${lemma}`);
1217
1237
  }
1218
1238
  const base = match[1];
1219
- if (subtypes.has("Callisto")) {
1220
- return [base, "", new Set(["F", "sg"])];
1239
+ if (subtypes.has(NominalType.Callisto)) {
1240
+ return [base, "", new Set([NominalType.Feminine, NominalType.Singular])];
1221
1241
  } else {
1222
- return [base, "", new Set(["F"])];
1242
+ return [base, "", new Set([NominalType.Feminine])];
1223
1243
  }
1224
1244
  }
1225
1245
  return this.get_noun_subtype_by_ending(lemma, stem2, typ, subtypes, [
1226
- ["us", ["M"]],
1227
- ["ū", ["N"]],
1228
- ["ūs", ["M", "pl"]],
1229
- ["ua", ["N", "pl"]],
1246
+ ["us", [NominalType.Masculine]],
1247
+ ["ū", [NominalType.Neuter]],
1248
+ ["ūs", [NominalType.Masculine, NominalType.Plural]],
1249
+ ["ua", [NominalType.Neuter, NominalType.Plural]],
1230
1250
  ]);
1231
1251
  } else if (typ == "5") {
1232
1252
  return this.get_noun_subtype_by_ending(lemma, stem2, typ, subtypes, [
1233
- ["iēs", ["F", "i"]],
1234
- ["iēs", ["F", "i", "pl"]],
1235
- ["ēs", ["F"]],
1236
- ["ēs", ["F", "pl"]],
1253
+ ["iēs", [NominalType.Feminine, NominalType.i]],
1254
+ ["iēs", [NominalType.Feminine, NominalType.i, NominalType.Plural]],
1255
+ ["ēs", [NominalType.Feminine]],
1256
+ ["ēs", [NominalType.Feminine, NominalType.Plural]],
1237
1257
  ]);
1238
1258
  } else if (typ == "irreg" && lemma == "domus") {
1239
- return [lemma, "", new Set(["loc"])];
1259
+ return [lemma, "", new Set([NominalType.Locative])];
1240
1260
  } else if (typ == "indecl" || (typ == "irreg" && (lemma == "Deus" || lemma == "Iēsus" || lemma == "Jēsus" || lemma == "Athōs" || lemma == "vēnum"))) {
1241
- return [lemma, "", new Set(["sg"])];
1261
+ return [lemma, "", new Set([NominalType.Singular])];
1242
1262
  } else {
1243
1263
  return [lemma, "", new Set()];
1244
1264
  }
@@ -1284,23 +1304,23 @@ export class LaNominal {
1284
1304
  lemma: string,
1285
1305
  stem2: string,
1286
1306
  decltype: string,
1287
- specified_subtypes: Set<string>,
1288
- endings_and_subtypes: [(string | string[]), string[]][]):
1289
- [string, string, Set<string>]
1307
+ specified_subtypes: Set<NominalType>,
1308
+ endings_and_subtypes: [(string | string[]), NominalType[]][]):
1309
+ [string, string, Set<NominalType>]
1290
1310
  {
1291
1311
  for (const ending_and_subtype of endings_and_subtypes) {
1292
1312
  const ending = ending_and_subtype[0];
1293
1313
  const subtypes = ending_and_subtype[1];
1294
1314
  let not_this_subtype = false;
1295
- if (specified_subtypes.has("pl") && !subtypes.includes("pl")) {
1315
+ if (specified_subtypes.has(NominalType.Plural) && !subtypes.includes(NominalType.Plural)) {
1296
1316
  not_this_subtype = true;
1297
1317
  } else {
1298
1318
  for (const subtype of subtypes) {
1299
- if (specified_subtypes.has("-" + subtype) ||
1300
- (subtype == "N" && (specified_subtypes.has("M") || specified_subtypes.has("F"))) ||
1301
- ((subtype == "M" || subtype == "F") && specified_subtypes.has("N")) ||
1302
- (subtype == "sg" && specified_subtypes.has("pl")) ||
1303
- (subtype == "pl" && specified_subtypes.has("sg"))) {
1319
+ if (hasNominalType(specified_subtypes, "-" + subtype) ||
1320
+ (subtype == NominalType.Neuter && (specified_subtypes.has(NominalType.Masculine) || specified_subtypes.has(NominalType.Feminine))) ||
1321
+ ((subtype == NominalType.Masculine || subtype == NominalType.Feminine) && specified_subtypes.has(NominalType.Neuter)) ||
1322
+ (subtype == NominalType.Singular && specified_subtypes.has(NominalType.Plural)) ||
1323
+ (subtype == NominalType.Plural && specified_subtypes.has(NominalType.Singular))) {
1304
1324
  not_this_subtype = true;
1305
1325
  break;
1306
1326
  }
@@ -1339,6 +1359,7 @@ export class LaNominal {
1339
1359
  categories: [],
1340
1360
  voc: true,
1341
1361
  noneut: false,
1362
+ nomf: false,
1342
1363
  };
1343
1364
 
1344
1365
  for (const slot of this.iter_slots(is_adj)) {
@@ -1367,8 +1388,10 @@ export class LaNominal {
1367
1388
  footnote: "",
1368
1389
  num: seg.num,
1369
1390
  gender: seg.gender,
1391
+ loc: seg.loc,
1370
1392
  voc: true,
1371
1393
  noneut: false,
1394
+ nomf: false,
1372
1395
  pos: is_adj ? pos : "adjectives",
1373
1396
  forms: new Map(),
1374
1397
  types: seg.types,
@@ -1383,10 +1406,13 @@ export class LaNominal {
1383
1406
  if (data.noneut) {
1384
1407
  declensions.noneut = true;
1385
1408
  }
1409
+ if (data.nomf) {
1410
+ declensions.nomf = true;
1411
+ }
1386
1412
 
1387
- if (data.types.has("sufn")) {
1413
+ if (data.types.has(NominalType.SuffixN)) {
1388
1414
  data.subtitles.push(["with", " 'm' optionally → 'n' in compounds"]);
1389
- } else if (data.types.has("not_sufn")) {
1415
+ } else if (data.types.has(NominalType.NotSuffixN)) {
1390
1416
  data.subtitles.push(["without", " 'm' optionally → 'n' in compounds"]);
1391
1417
  }
1392
1418
 
@@ -1449,11 +1475,12 @@ export class LaNominal {
1449
1475
  } else {
1450
1476
  throw Error(`Internal error! Don't recognize noun declension ${apparent_decl}`);
1451
1477
  }
1478
+ parsed_run.apparent_decl = apparent_decl;
1452
1479
  data.title = data.title + " noun";
1453
1480
  }
1454
- if (data.types.has("sufn")) {
1481
+ if (data.types.has(NominalType.SuffixN)) {
1455
1482
  data.subtitles.push(["with", " 'm' optionally → 'n' in compounds"]);
1456
- } else if (data.types.has("not_sufn")) {
1483
+ } else if (data.types.has(NominalType.NotSuffixN)) {
1457
1484
  data.subtitles.push(["without", " 'm' optionally → 'n' in compounds"]);
1458
1485
  }
1459
1486
  declensions.orig_titles.push(data.title);
@@ -1489,11 +1516,11 @@ export class LaNominal {
1489
1516
  }
1490
1517
  }
1491
1518
 
1492
- if (seg.types.has("lig")) {
1519
+ if (seg.types.has(NominalType.Ligature)) {
1493
1520
  this.apply_ligatures(data.forms, is_adj);
1494
1521
  }
1495
1522
 
1496
- if (seg.types.has("sufn")) {
1523
+ if (seg.types.has(NominalType.SuffixN)) {
1497
1524
  this.apply_sufn(data.forms, is_adj);
1498
1525
  }
1499
1526
 
@@ -1536,7 +1563,7 @@ export class LaNominal {
1536
1563
  declensions.notes.set(slot, notes);
1537
1564
  }
1538
1565
 
1539
- if (!seg.types.has("nocat") && (is_adj || !seg.is_adj)) {
1566
+ if (!seg.types.has(NominalType.NoCategories) && (is_adj || !seg.is_adj)) {
1540
1567
  for (const cat of data.categories) {
1541
1568
  this.insert_if_not(declensions.categories, cat);
1542
1569
  }
@@ -1579,7 +1606,7 @@ export class LaNominal {
1579
1606
  }
1580
1607
  }
1581
1608
  if (!title_the_hard_way) {
1582
- const subtypeses: Set<string> = new Set();
1609
+ const subtypeses = new Set<NominalType>();
1583
1610
  for (const this_parsed_run of seg.alternants) {
1584
1611
  for (const segment of this_parsed_run.segments) {
1585
1612
  if (segment.type == "Segment" && segment.decl) {
@@ -1593,7 +1620,7 @@ export class LaNominal {
1593
1620
  if (segment.type == "Segment" && segment.decl) {
1594
1621
  const neg_subtypes = this.set_difference(subtypeses, segment.types);
1595
1622
  for (const neg_subtype of neg_subtypes) {
1596
- segment.types.add("not_" + neg_subtype);
1623
+ addNominalType(segment.types, "not_" + neg_subtype);
1597
1624
  }
1598
1625
  }
1599
1626
  }
@@ -1614,6 +1641,10 @@ export class LaNominal {
1614
1641
  declensions.noneut = true;
1615
1642
  }
1616
1643
 
1644
+ if (this_declensions.nomf) {
1645
+ declensions.nomf = true;
1646
+ }
1647
+
1617
1648
  if (this_parsed_run.num == "sg" || this_parsed_run.num == "pl") {
1618
1649
  for (const slot of (this.iter_slots(is_adj))) {
1619
1650
  if ((this_parsed_run.num == "sg" && slot.includes("pl")) ||
@@ -1862,8 +1893,8 @@ export class LaNominal {
1862
1893
  return sentences_to_join.join(joiner);
1863
1894
  }
1864
1895
 
1865
- private set_difference(a: Set<string>, b: Set<string>): Set<string> {
1866
- const res = new Set<string>();
1896
+ private set_difference<T>(a: Set<T>, b: Set<T>): Set<T> {
1897
+ const res = new Set<T>();
1867
1898
  for (const key of a.keys()) {
1868
1899
  if (!b.has(key)) {
1869
1900
  res.add(key);
@@ -1963,6 +1994,7 @@ export class LaNominal {
1963
1994
  }
1964
1995
  newval.push(form);
1965
1996
  }
1997
+ setNominalForm(forms, slot, newval);
1966
1998
  }
1967
1999
  }
1968
2000
  }