@pubid/pubid 0.1.3 → 0.1.5

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 (185) hide show
  1. package/artifact/corpus.json.gz +0 -0
  2. package/dist/conformance/cli.js +5 -1
  3. package/dist/flavors/amca/grammar.d.ts +4 -0
  4. package/dist/flavors/amca/grammar.js +87 -0
  5. package/dist/flavors/amca/index.d.ts +4 -0
  6. package/dist/flavors/amca/index.js +76 -0
  7. package/dist/flavors/amca/model.d.ts +29 -0
  8. package/dist/flavors/amca/model.js +146 -0
  9. package/dist/flavors/ansi/index.d.ts +24 -0
  10. package/dist/flavors/ansi/index.js +147 -0
  11. package/dist/flavors/api/grammar.d.ts +4 -0
  12. package/dist/flavors/api/grammar.js +79 -0
  13. package/dist/flavors/api/index.d.ts +4 -0
  14. package/dist/flavors/api/index.js +71 -0
  15. package/dist/flavors/api/model.d.ts +27 -0
  16. package/dist/flavors/api/model.js +114 -0
  17. package/dist/flavors/ashrae/grammar.d.ts +2 -0
  18. package/dist/flavors/ashrae/grammar.js +667 -0
  19. package/dist/flavors/ashrae/index.d.ts +4 -0
  20. package/dist/flavors/ashrae/index.js +306 -0
  21. package/dist/flavors/ashrae/model.d.ts +87 -0
  22. package/dist/flavors/ashrae/model.js +335 -0
  23. package/dist/flavors/ashrae/preprocessor.d.ts +7 -0
  24. package/dist/flavors/ashrae/preprocessor.js +44 -0
  25. package/dist/flavors/asme/grammar.d.ts +2 -0
  26. package/dist/flavors/asme/grammar.js +200 -0
  27. package/dist/flavors/asme/index.d.ts +4 -0
  28. package/dist/flavors/asme/index.js +138 -0
  29. package/dist/flavors/asme/model.d.ts +34 -0
  30. package/dist/flavors/asme/model.js +123 -0
  31. package/dist/flavors/astm/grammar.d.ts +2 -0
  32. package/dist/flavors/astm/grammar.js +110 -0
  33. package/dist/flavors/astm/index.d.ts +2 -0
  34. package/dist/flavors/astm/index.js +127 -0
  35. package/dist/flavors/astm/model.d.ts +42 -0
  36. package/dist/flavors/astm/model.js +263 -0
  37. package/dist/flavors/bipm/index.d.ts +30 -0
  38. package/dist/flavors/bipm/index.js +434 -0
  39. package/dist/flavors/bsi/grammar.d.ts +4 -0
  40. package/dist/flavors/bsi/grammar.js +535 -0
  41. package/dist/flavors/bsi/index.d.ts +4 -0
  42. package/dist/flavors/bsi/index.js +941 -0
  43. package/dist/flavors/bsi/model.d.ts +127 -0
  44. package/dist/flavors/bsi/model.js +863 -0
  45. package/dist/flavors/calconnect/index.d.ts +21 -0
  46. package/dist/flavors/calconnect/index.js +113 -0
  47. package/dist/flavors/cen_cenelec/grammar.d.ts +4 -0
  48. package/dist/flavors/cen_cenelec/grammar.js +107 -0
  49. package/dist/flavors/cen_cenelec/index.d.ts +5 -0
  50. package/dist/flavors/cen_cenelec/index.js +263 -0
  51. package/dist/flavors/cen_cenelec/model.d.ts +45 -0
  52. package/dist/flavors/cen_cenelec/model.js +490 -0
  53. package/dist/flavors/cie/grammar.d.ts +5 -0
  54. package/dist/flavors/cie/grammar.js +127 -0
  55. package/dist/flavors/cie/index.d.ts +2 -0
  56. package/dist/flavors/cie/index.js +311 -0
  57. package/dist/flavors/cie/model.d.ts +122 -0
  58. package/dist/flavors/cie/model.js +464 -0
  59. package/dist/flavors/csa/grammar.d.ts +6 -0
  60. package/dist/flavors/csa/grammar.js +239 -0
  61. package/dist/flavors/csa/index.d.ts +2 -0
  62. package/dist/flavors/csa/index.js +634 -0
  63. package/dist/flavors/csa/model.d.ts +33 -0
  64. package/dist/flavors/csa/model.js +505 -0
  65. package/dist/flavors/doi/index.d.ts +13 -0
  66. package/dist/flavors/doi/index.js +65 -0
  67. package/dist/flavors/easc/index.d.ts +4 -0
  68. package/dist/flavors/easc/index.js +107 -0
  69. package/dist/flavors/ecma/index.d.ts +4 -0
  70. package/dist/flavors/ecma/index.js +117 -0
  71. package/dist/flavors/etsi/index.d.ts +14 -0
  72. package/dist/flavors/etsi/index.js +307 -0
  73. package/dist/flavors/evs/grammar.d.ts +2 -0
  74. package/dist/flavors/evs/grammar.js +22 -0
  75. package/dist/flavors/evs/index.d.ts +2 -0
  76. package/dist/flavors/evs/index.js +24 -0
  77. package/dist/flavors/evs/model.d.ts +19 -0
  78. package/dist/flavors/evs/model.js +36 -0
  79. package/dist/flavors/gb/index.d.ts +31 -0
  80. package/dist/flavors/gb/index.js +159 -0
  81. package/dist/flavors/gost/grammar.d.ts +2 -0
  82. package/dist/flavors/gost/grammar.js +46 -0
  83. package/dist/flavors/gost/index.d.ts +2 -0
  84. package/dist/flavors/gost/index.js +165 -0
  85. package/dist/flavors/gost/model.d.ts +61 -0
  86. package/dist/flavors/gost/model.js +147 -0
  87. package/dist/flavors/gost/prefix_routes.d.ts +15 -0
  88. package/dist/flavors/gost/prefix_routes.js +192 -0
  89. package/dist/flavors/iala/index.d.ts +32 -0
  90. package/dist/flavors/iala/index.js +300 -0
  91. package/dist/flavors/iana/index.d.ts +19 -0
  92. package/dist/flavors/iana/index.js +71 -0
  93. package/dist/flavors/idf/grammar.d.ts +2 -0
  94. package/dist/flavors/idf/grammar.js +71 -0
  95. package/dist/flavors/idf/index.d.ts +2 -0
  96. package/dist/flavors/idf/index.js +100 -0
  97. package/dist/flavors/idf/model.d.ts +54 -0
  98. package/dist/flavors/idf/model.js +359 -0
  99. package/dist/flavors/iec/grammar.d.ts +3 -0
  100. package/dist/flavors/iec/grammar.js +187 -0
  101. package/dist/flavors/iec/index.d.ts +4 -0
  102. package/dist/flavors/iec/index.js +507 -0
  103. package/dist/flavors/iec/model.d.ts +54 -0
  104. package/dist/flavors/iec/model.js +437 -0
  105. package/dist/flavors/ieee/grammar.d.ts +2 -0
  106. package/dist/flavors/ieee/grammar.js +697 -0
  107. package/dist/flavors/ieee/index.d.ts +3 -0
  108. package/dist/flavors/ieee/index.js +1258 -0
  109. package/dist/flavors/ieee/model.d.ts +144 -0
  110. package/dist/flavors/ieee/model.js +1237 -0
  111. package/dist/flavors/ieee/preprocessor.d.ts +8 -0
  112. package/dist/flavors/ieee/preprocessor.js +410 -0
  113. package/dist/flavors/ieee/update_codes.d.ts +8 -0
  114. package/dist/flavors/ieee/update_codes.js +197 -0
  115. package/dist/flavors/ietf/index.d.ts +30 -0
  116. package/dist/flavors/ietf/index.js +151 -0
  117. package/dist/flavors/iho/index.d.ts +4 -0
  118. package/dist/flavors/iho/index.js +126 -0
  119. package/dist/flavors/index.d.ts +9 -0
  120. package/dist/flavors/index.js +136 -0
  121. package/dist/flavors/isbn/index.d.ts +13 -0
  122. package/dist/flavors/isbn/index.js +97 -0
  123. package/dist/flavors/iso/grammar.d.ts +2 -0
  124. package/dist/flavors/iso/grammar.js +207 -0
  125. package/dist/flavors/iso/index.d.ts +2 -0
  126. package/dist/flavors/iso/index.js +343 -0
  127. package/dist/flavors/iso/model.d.ts +159 -0
  128. package/dist/flavors/iso/model.js +802 -0
  129. package/dist/flavors/iso/stages.generated.d.ts +13 -0
  130. package/dist/flavors/iso/stages.generated.js +391 -0
  131. package/dist/flavors/itu/grammar.d.ts +4 -0
  132. package/dist/flavors/itu/grammar.js +205 -0
  133. package/dist/flavors/itu/index.d.ts +2 -0
  134. package/dist/flavors/itu/index.js +224 -0
  135. package/dist/flavors/itu/model.d.ts +184 -0
  136. package/dist/flavors/itu/model.js +599 -0
  137. package/dist/flavors/jcgm/index.d.ts +7 -0
  138. package/dist/flavors/jcgm/index.js +300 -0
  139. package/dist/flavors/jis/index.d.ts +4 -0
  140. package/dist/flavors/jis/index.js +267 -0
  141. package/dist/flavors/nist/grammar.d.ts +2 -0
  142. package/dist/flavors/nist/grammar.js +287 -0
  143. package/dist/flavors/nist/index.d.ts +2 -0
  144. package/dist/flavors/nist/index.js +1244 -0
  145. package/dist/flavors/nist/model.d.ts +155 -0
  146. package/dist/flavors/nist/model.js +823 -0
  147. package/dist/flavors/nist/preprocessor.d.ts +11 -0
  148. package/dist/flavors/nist/preprocessor.js +281 -0
  149. package/dist/flavors/oasis/index.d.ts +23 -0
  150. package/dist/flavors/oasis/index.js +110 -0
  151. package/dist/flavors/ogc/index.d.ts +20 -0
  152. package/dist/flavors/ogc/index.js +75 -0
  153. package/dist/flavors/oiml/grammar.d.ts +2 -0
  154. package/dist/flavors/oiml/grammar.js +206 -0
  155. package/dist/flavors/oiml/implementation.d.ts +9 -0
  156. package/dist/flavors/oiml/implementation.js +45 -0
  157. package/dist/flavors/oiml/model.d.ts +23 -0
  158. package/dist/flavors/oiml/model.js +592 -0
  159. package/dist/flavors/omg/index.d.ts +14 -0
  160. package/dist/flavors/omg/index.js +73 -0
  161. package/dist/flavors/plateau/index.d.ts +4 -0
  162. package/dist/flavors/plateau/index.js +97 -0
  163. package/dist/flavors/tgpp/index.d.ts +4 -0
  164. package/dist/flavors/tgpp/index.js +122 -0
  165. package/dist/flavors/un/index.d.ts +13 -0
  166. package/dist/flavors/un/index.js +90 -0
  167. package/dist/flavors/w3c/index.d.ts +14 -0
  168. package/dist/flavors/w3c/index.js +148 -0
  169. package/dist/flavors/xsf/index.d.ts +18 -0
  170. package/dist/flavors/xsf/index.js +65 -0
  171. package/dist/grammar/engine.d.ts +78 -0
  172. package/dist/grammar/engine.js +351 -0
  173. package/dist/index.d.ts +1 -0
  174. package/dist/index.js +3 -0
  175. package/dist/model/attribute.d.ts +54 -0
  176. package/dist/model/attribute.js +53 -0
  177. package/dist/model/builder.d.ts +39 -0
  178. package/dist/model/builder.js +124 -0
  179. package/dist/model/component.d.ts +70 -0
  180. package/dist/model/component.js +170 -0
  181. package/dist/model/identifier.d.ts +84 -0
  182. package/dist/model/identifier.js +270 -0
  183. package/dist/model/urn-generator.d.ts +27 -0
  184. package/dist/model/urn-generator.js +91 -0
  185. package/package.json +1 -1
@@ -0,0 +1,434 @@
1
+ import { match, str } from "../../grammar/engine.js";
2
+ import { ParseFailed, parseGrammar } from "../../grammar/engine.js";
3
+ import { BaseIdentifier, registerType } from "../../model/identifier.js";
4
+ import { extendAttributes, keyValue } from "../../model/attribute.js";
5
+ import { BaseUrnGenerator } from "../../model/urn-generator.js";
6
+ /**
7
+ * 1:1 port of lib/pubid/bipm/ — 90 corpus rows across six families:
8
+ * committee documents (REC/RES/DECN/ACT/DECL in short and long EN/FR
9
+ * forms), meetings (EN ordinals, FR <sup>e</sup> réunion), the
10
+ * Metrologia journal, the SI Brochure and its derived products, mises
11
+ * en pratique (incl. Rapport BIPM-YYYY/NN), and CC guides. Historic
12
+ * group names (CCDS) and two-letter language codes (EN/FR) normalize
13
+ * at parse time and never reach the hash.
14
+ */
15
+ const GROUPS = [
16
+ "CIPM", "CGPM", "JCRB", "CCTF", "CCQM", "CCT", "CCL", "CCAUV",
17
+ "CCU", "CCM", "CCEM", "CCPR", "CCRI",
18
+ ];
19
+ const GROUP_ALIASES = { CCDS: "CCTF" };
20
+ const PARSEABLE_GROUPS = [...GROUPS, ...Object.keys(GROUP_ALIASES)];
21
+ const TYPE_CODES = ["REC", "RES", "DECN", "ACT", "DECL"];
22
+ const TYPE_NAME_EN = {
23
+ REC: "Recommendation", RES: "Resolution", DECN: "Decision",
24
+ ACT: "Action", DECL: "Statement",
25
+ };
26
+ const TYPE_NAME_FR = {
27
+ REC: "Recommandation", RES: "Résolution", DECN: "Décision",
28
+ ACT: "Action", DECL: "Statement",
29
+ };
30
+ const TYPE_WORD_ALIASES = {
31
+ Declaration: "DECL", "Déclaration": "DECL",
32
+ };
33
+ const TYPE_WORD_TO_CODE = (() => {
34
+ const map = { ...TYPE_WORD_ALIASES };
35
+ for (const code of TYPE_CODES) {
36
+ map[code] = code;
37
+ map[TYPE_NAME_EN[code]] = code;
38
+ map[TYPE_NAME_FR[code]] = code;
39
+ }
40
+ return map;
41
+ })();
42
+ const LANGUAGE_ALIASES = { EN: "E", FR: "F" };
43
+ /** Longest-first literal alternation, so "CCTF" beats "CCT". */
44
+ function alternation(tokens) {
45
+ const sorted = [...tokens].sort((a, b) => b.length - a.length);
46
+ return sorted.map((t) => str(t)).reduce((a, b) => a.or(b));
47
+ }
48
+ function buildRules() {
49
+ const rules = {};
50
+ const rule = (name, build) => {
51
+ rules[name] = build();
52
+ };
53
+ const space = str(" ");
54
+ const digits = match("[0-9]").repeat(1, Infinity);
55
+ const alnum = match("[0-9A-Za-z]").repeat(1, Infinity);
56
+ rule("number", () => digits.then(str("-").then(digits).repeat(0, Infinity)).as("number"));
57
+ rule("year", () => match("[0-9]").repeat(4, 4).as("year"));
58
+ // Two-letter consumer codes first, so "EN" is never a bare "E".
59
+ const lang = () => alternation(["EN", "FR", "E", "F"]).as("language");
60
+ rule("year_paren", () => str("(").then(rules["year"], str(", ").then(lang()).maybe(), str(")")));
61
+ rule("year_paren_nolang", () => str("(").then(rules["year"], str(")")));
62
+ rule("group", () => alternation(PARSEABLE_GROUPS).as("group"));
63
+ rule("type_abbrev", () => alternation([...TYPE_CODES]).as("type_word"));
64
+ rule("type_name_en", () => alternation([...new Set([...Object.values(TYPE_NAME_EN), "Declaration"])]).as("type_word"));
65
+ rule("type_name_fr", () => alternation([...new Set([...Object.values(TYPE_NAME_FR), "Déclaration"])]).as("type_word"));
66
+ const connective = () => str("de la").or(str("du"));
67
+ const ordinal = () => str("st").or(str("nd"), str("rd"), str("th"));
68
+ const meetingWordFr = () => str("Réunion").or(str("réunion"));
69
+ // The trailing date is optional so "CCTF REC 2" parses date-less.
70
+ rule("committee_short", () => rules["group"]
71
+ .then(space, rules["type_abbrev"], space.then(rules["number"]).maybe(), space.then(rules["year_paren"]).maybe())
72
+ .as("committee_short"));
73
+ rule("committee_long_en", () => rules["group"]
74
+ .then(space, rules["type_name_en"], space.then(rules["number"]).maybe(), space.then(rules["year_paren_nolang"]).maybe())
75
+ .as("committee_long_en"));
76
+ rule("committee_long_fr", () => rules["type_name_fr"]
77
+ .then(space.then(rules["number"]).maybe(), space, connective(), space, rules["group"], space.then(rules["year_paren_nolang"]).maybe())
78
+ .as("committee_long_fr"));
79
+ // Loose consumer form: a French type name in group-leading order.
80
+ rule("committee_group_fr", () => rules["group"]
81
+ .then(space, rules["type_name_fr"], space.then(rules["number"]).maybe(), space.then(rules["year_paren_nolang"]).maybe())
82
+ .as("committee_long_fr"));
83
+ // Bare MRA form: group + number, no type word ("CIPM 2005-06").
84
+ rule("committee_bare", () => rules["group"]
85
+ .then(space, rules["number"], space.then(rules["year_paren"]).maybe())
86
+ .as("committee_bare"));
87
+ rule("meeting_en", () => rules["group"]
88
+ .then(space, rules["number"], ordinal(), space, str("Meeting"), space.then(rules["year_paren"]).maybe())
89
+ .or(rules["group"].then(space, str("Meeting"), space, rules["number"], space.then(rules["year_paren"]).maybe()))
90
+ .as("meeting_en"));
91
+ rule("meeting_fr", () => rules["group"]
92
+ .then(space, rules["number"], str("<sup>e</sup>"), space, str("réunion"), space.then(rules["year_paren"]).maybe())
93
+ .or(rules["group"].then(space, rules["number"], str("e"), space, meetingWordFr(), space.then(rules["year_paren"]).maybe()), rules["group"].then(space, meetingWordFr(), space, rules["number"], space.then(rules["year_paren"]).maybe()))
94
+ .as("meeting_fr"));
95
+ rule("metrologia", () => str("Metrologia")
96
+ .then(space
97
+ .then(digits.as("volume"), space
98
+ .then(alnum.as("issue"), space.then(alnum.as("article")).maybe())
99
+ .maybe())
100
+ .maybe())
101
+ .as("metrologia"));
102
+ rule("edition", () => digits.then(str("e")).as("edition"));
103
+ rule("version", () => str("v").then(match("[0-9.]").repeat(1, Infinity)).as("version"));
104
+ rule("years", () => digits.then(str("/").then(digits).maybe()).as("years"));
105
+ rule("si_brochure", () => str("BIPM SI Brochure")
106
+ .or(str("SI Brochure"))
107
+ .then(space, str("sur le SI").then(space).maybe(), rules["edition"], space, rules["version"], space, str("("), rules["years"], str(", "), lang(), str(")"))
108
+ .as("si_brochure"));
109
+ rule("brochure_variant", () => str("Appendix")
110
+ .then(space, digits)
111
+ .or(str("Concise"), str("FAQ"))
112
+ .as("variant"));
113
+ rule("si_brochure_variant", () => str("BIPM SI Brochure")
114
+ .or(str("SI Brochure"))
115
+ .then(space, rules["brochure_variant"])
116
+ .as("si_brochure_variant"));
117
+ rule("si_brochure_section", () => str("BIPM SI Brochure")
118
+ .or(str("SI Brochure"))
119
+ .then(space.then(str("Part"), space, digits.as("part")).maybe())
120
+ .as("si_brochure_section"));
121
+ // Shared "Appendix N [Annex N] Part N[.M]" tail of MEPs and guides.
122
+ rule("appendix_part", () => str("Appendix").then(space, digits.as("appendix"), space.then(str("Annex"), space, digits.as("annex")).maybe(), space, str("Part"), space, digits.then(str(".").then(digits).maybe()).as("part")));
123
+ rule("mep_code", () => match("[0-9A-Za-z]").repeat(1, Infinity).as("mep_code"));
124
+ rule("report_code", () => str("BIPM-").then(digits, str("/"), digits).as("report_code"));
125
+ const mepBody = () => str("SI MEP").then(space, rules["mep_code"]).or(str("Rapport").then(space, rules["report_code"]));
126
+ rule("mep", () => str("BIPM")
127
+ .then(space, mepBody(), space, rules["appendix_part"])
128
+ .or(mepBody())
129
+ .as("mep"));
130
+ rule("guide_kind", () => str("MeP").or(str("RSI")).as("guide_kind"));
131
+ const guideBody = () => rules["group"].then(str("-GD-"), rules["guide_kind"], str("-"), digits.as("number"));
132
+ rule("guide", () => str("BIPM")
133
+ .then(space, guideBody(), space, rules["appendix_part"])
134
+ .or(guideBody())
135
+ .as("guide"));
136
+ rule("group_leading", () => rules["meeting_en"].or(rules["meeting_fr"], rules["committee_short"], rules["committee_long_en"], rules["committee_group_fr"], rules["committee_bare"]));
137
+ rule("identifier", () => rules["metrologia"].or(rules["si_brochure"], rules["si_brochure_variant"], rules["si_brochure_section"], rules["mep"], rules["guide"], rules["committee_long_fr"], rules["group_leading"]));
138
+ rule("root", () => rules["identifier"]);
139
+ return rules;
140
+ }
141
+ export const bipmGrammar = { rules: buildRules(), root: "root" };
142
+ /** data/bipm/update_codes.yaml — full-line legacy spellings. */
143
+ const UPDATE_CODES = {
144
+ "CIPM/2005-06(REV)": "CIPM 2005-06",
145
+ "CIPM 2005-06(REV)": "CIPM 2005-06",
146
+ };
147
+ // ---------------------------------------------------------------------------
148
+ // Model
149
+ // ---------------------------------------------------------------------------
150
+ const BIPM_ATTRS = {
151
+ group: { type: "string" },
152
+ type_code: { type: "string" },
153
+ number: { type: "string" },
154
+ year: { type: "integer" },
155
+ language: { type: "string" },
156
+ form: { type: "string", default: "short" },
157
+ issue: { type: "string" },
158
+ article: { type: "string" },
159
+ edition: { type: "string" },
160
+ version: { type: "string" },
161
+ years: { type: "string" },
162
+ variant: { type: "string" },
163
+ mep_code: { type: "string" },
164
+ report_code: { type: "string" },
165
+ guide_kind: { type: "string" },
166
+ appendix: { type: "string" },
167
+ annex: { type: "string" },
168
+ part: { type: "string" },
169
+ };
170
+ const BIPM_MAPPINGS = keyValue({ wire: "group", to: "group" }, { wire: "type_code", to: "type_code" }, { wire: "number", to: "number" }, { wire: "year", to: "year" }, { wire: "language", to: "language" }, { wire: "form", to: "form" }, { wire: "issue", to: "issue" }, { wire: "article", to: "article" }, { wire: "edition", to: "edition" }, { wire: "version", to: "version" }, { wire: "years", to: "years" }, { wire: "variant", to: "variant" }, { wire: "mep_code", to: "mep_code" }, { wire: "report_code", to: "report_code" }, { wire: "guide_kind", to: "guide_kind" }, { wire: "appendix", to: "appendix" }, { wire: "annex", to: "annex" }, { wire: "part", to: "part" });
171
+ /** Naive source-data ordinals: 1→st, 2→nd, 3→rd, else→th (11→"11st"). */
172
+ function ordinalSuffix(number) {
173
+ const first = number.split("-")[0] ?? "";
174
+ const last = first.at(-1);
175
+ if (last === "1")
176
+ return "st";
177
+ if (last === "2")
178
+ return "nd";
179
+ if (last === "3")
180
+ return "rd";
181
+ return "th";
182
+ }
183
+ function frenchConnective(group) {
184
+ return group === "CGPM" ? "de la" : "du";
185
+ }
186
+ export class BipmIdentifier extends BaseIdentifier {
187
+ static attributes = extendAttributes(BaseIdentifier, BIPM_ATTRS);
188
+ static mappings = BIPM_MAPPINGS;
189
+ numberSegment() {
190
+ return this.number === undefined ? "" : ` ${this.number}`;
191
+ }
192
+ yearSegment(lang = "") {
193
+ return this.year === undefined ? "" : ` (${this.year}${lang})`;
194
+ }
195
+ fullContentWrap(body) {
196
+ if (this.part === undefined)
197
+ return body;
198
+ const annex = this.annex === undefined ? "" : ` Annex ${this.annex}`;
199
+ return `BIPM ${body} Appendix ${this.appendix}${annex} Part ${this.part}`;
200
+ }
201
+ }
202
+ class BipmUrnGenerator extends BaseUrnGenerator {
203
+ generate() {
204
+ const id = this.identifier;
205
+ if (id instanceof BipmCommitteeDocument) {
206
+ const parts = [
207
+ "urn", "bipm", id.group?.toLowerCase() ?? "",
208
+ id.type_code?.toLowerCase() ?? "", id.number ?? "",
209
+ ];
210
+ if (id.year !== undefined)
211
+ parts.push(String(id.year));
212
+ return parts.join(":");
213
+ }
214
+ if (id instanceof BipmMeeting) {
215
+ const parts = ["urn", "bipm", id.group?.toLowerCase() ?? "", "meeting", id.number ?? ""];
216
+ if (id.year !== undefined)
217
+ parts.push(String(id.year));
218
+ return parts.join(":");
219
+ }
220
+ if (id instanceof BipmMetrologiaArticle) {
221
+ const parts = ["urn", "bipm", "metrologia", String(id.volume())];
222
+ if (id.issue !== undefined)
223
+ parts.push(id.issue);
224
+ if (id.article !== undefined)
225
+ parts.push(id.article);
226
+ return parts.join(":");
227
+ }
228
+ if (id instanceof BipmSiBrochure) {
229
+ return [
230
+ "urn", "bipm", "si-brochure", id.language?.toLowerCase() ?? "",
231
+ id.edition ?? "", id.version ?? "", id.years ?? "",
232
+ ].join(":");
233
+ }
234
+ throw new ParseFailed(`Cannot build URN for BIPM identifier: ${id.constructor.polymorphicName}`, 0);
235
+ }
236
+ }
237
+ class BipmCommitteeDocument extends BipmIdentifier {
238
+ static polymorphicName = "pubid:bipm:committee-document";
239
+ static urnGenerator = BipmUrnGenerator;
240
+ render() {
241
+ if (this.form === "long") {
242
+ if (this.language === "F") {
243
+ const name = TYPE_NAME_FR[this.type_code ?? ""] ?? "";
244
+ return `${name}${this.numberSegment()} ${frenchConnective(this.group ?? "")} ${this.group}${this.yearSegment()}`;
245
+ }
246
+ const name = TYPE_NAME_EN[this.type_code ?? ""] ?? "";
247
+ return `${this.group ?? ""} ${name}${this.numberSegment()}${this.yearSegment()}`;
248
+ }
249
+ const lang = this.language === undefined ? "" : `, ${this.language}`;
250
+ const type = this.type_code === undefined ? "" : ` ${this.type_code}`;
251
+ return `${this.group ?? ""}${type}${this.numberSegment()}${this.yearSegment(lang)}`;
252
+ }
253
+ }
254
+ registerType(BipmCommitteeDocument);
255
+ class BipmMeeting extends BipmIdentifier {
256
+ static polymorphicName = "pubid:bipm:meeting";
257
+ static urnGenerator = BipmUrnGenerator;
258
+ render() {
259
+ if (this.language === "F") {
260
+ return `${this.group ?? ""} ${this.number ?? ""}<sup>e</sup> réunion${this.yearSegment()}`;
261
+ }
262
+ return `${this.group ?? ""} ${this.number ?? ""}${ordinalSuffix(this.number ?? "")} Meeting${this.yearSegment()}`;
263
+ }
264
+ }
265
+ registerType(BipmMeeting);
266
+ class BipmMetrologiaArticle extends BipmIdentifier {
267
+ static polymorphicName = "pubid:bipm:metrologia-article";
268
+ static urnGenerator = BipmUrnGenerator;
269
+ /** The volume IS the index key — derived from `number`, never stored. */
270
+ volume() {
271
+ return this.number === undefined ? undefined : Number(this.number);
272
+ }
273
+ render() {
274
+ let result = "Metrologia";
275
+ if (this.volume() !== undefined)
276
+ result += ` ${this.volume()}`;
277
+ if (this.issue !== undefined)
278
+ result += ` ${this.issue}`;
279
+ if (this.article !== undefined)
280
+ result += ` ${this.article}`;
281
+ return result;
282
+ }
283
+ }
284
+ registerType(BipmMetrologiaArticle);
285
+ class BipmSiBrochure extends BipmIdentifier {
286
+ static polymorphicName = "pubid:bipm:si-brochure";
287
+ static urnGenerator = BipmUrnGenerator;
288
+ render() {
289
+ if (this.variant !== undefined)
290
+ return `BIPM SI Brochure ${this.variant}`;
291
+ if (this.edition === undefined) {
292
+ const part = this.part === undefined ? "" : ` Part ${this.part}`;
293
+ return `BIPM SI Brochure${part}`;
294
+ }
295
+ const phrase = this.language === "F" ? "sur le SI " : "";
296
+ const lang = this.language === undefined ? "" : `, ${this.language}`;
297
+ return `BIPM SI Brochure ${phrase}${this.edition} ${this.version} (${this.years}${lang})`;
298
+ }
299
+ }
300
+ registerType(BipmSiBrochure);
301
+ class BipmMep extends BipmIdentifier {
302
+ static polymorphicName = "pubid:bipm:mep";
303
+ static urnGenerator = BipmUrnGenerator;
304
+ render() {
305
+ const body = this.report_code !== undefined
306
+ ? `Rapport ${this.report_code}`
307
+ : `SI MEP ${this.mep_code}`;
308
+ return this.fullContentWrap(body);
309
+ }
310
+ }
311
+ registerType(BipmMep);
312
+ class BipmGuide extends BipmIdentifier {
313
+ static polymorphicName = "pubid:bipm:guide";
314
+ static urnGenerator = BipmUrnGenerator;
315
+ render() {
316
+ return this.fullContentWrap(`${this.group}-GD-${this.guide_kind}-${this.number}`);
317
+ }
318
+ }
319
+ registerType(BipmGuide);
320
+ // ---------------------------------------------------------------------------
321
+ // Builder
322
+ // ---------------------------------------------------------------------------
323
+ const isObj = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
324
+ const s = (v) => v === undefined || v === null ? undefined : String(v);
325
+ function flatten(data) {
326
+ return Array.isArray(data) ? Object.assign({}, ...data) : data;
327
+ }
328
+ const normalizeGroup = (token) => GROUP_ALIASES[token] ?? token;
329
+ const normalizeLanguage = (token) => token === undefined ? undefined : LANGUAGE_ALIASES[token] ?? token;
330
+ class BipmBuilder {
331
+ build(data) {
332
+ const tree = flatten(data);
333
+ const node = (key) => {
334
+ const v = tree[key];
335
+ return isObj(v) ? flatten(v) : {};
336
+ };
337
+ if (tree["committee_short"] !== undefined)
338
+ return this.buildCommittee(node("committee_short"), "short");
339
+ if (tree["committee_long_en"] !== undefined)
340
+ return this.buildCommittee(node("committee_long_en"), "long", "E");
341
+ if (tree["committee_bare"] !== undefined)
342
+ return this.buildCommittee(node("committee_bare"), "short");
343
+ if (tree["committee_long_fr"] !== undefined)
344
+ return this.buildCommittee(node("committee_long_fr"), "long", "F");
345
+ if (tree["meeting_en"] !== undefined)
346
+ return this.buildMeeting(node("meeting_en"));
347
+ if (tree["meeting_fr"] !== undefined)
348
+ return this.buildMeeting(node("meeting_fr"), "F");
349
+ if (tree["metrologia"] !== undefined) {
350
+ const n = node("metrologia");
351
+ return new BipmMetrologiaArticle({
352
+ number: s(n["volume"]),
353
+ issue: s(n["issue"]),
354
+ article: s(n["article"]),
355
+ });
356
+ }
357
+ if (tree["si_brochure"] !== undefined) {
358
+ const n = node("si_brochure");
359
+ const edition = s(n["edition"]);
360
+ return new BipmSiBrochure({
361
+ number: edition,
362
+ edition,
363
+ version: s(n["version"]),
364
+ years: s(n["years"]),
365
+ language: normalizeLanguage(s(n["language"])),
366
+ });
367
+ }
368
+ if (tree["si_brochure_variant"] !== undefined) {
369
+ const variant = s(node("si_brochure_variant")["variant"]);
370
+ return new BipmSiBrochure({ number: variant, variant });
371
+ }
372
+ if (tree["si_brochure_section"] !== undefined) {
373
+ const n = node("si_brochure_section");
374
+ return new BipmSiBrochure({ part: s(n["part"]) });
375
+ }
376
+ if (tree["mep"] !== undefined) {
377
+ const n = node("mep");
378
+ const mepCode = s(n["mep_code"]);
379
+ const reportCode = s(n["report_code"]);
380
+ return new BipmMep({
381
+ number: mepCode ?? reportCode,
382
+ mep_code: mepCode,
383
+ report_code: reportCode,
384
+ appendix: s(n["appendix"]),
385
+ annex: s(n["annex"]),
386
+ part: s(n["part"]),
387
+ });
388
+ }
389
+ if (tree["guide"] !== undefined) {
390
+ const n = node("guide");
391
+ return new BipmGuide({
392
+ group: normalizeGroup(s(n["group"])),
393
+ guide_kind: s(n["guide_kind"]),
394
+ number: s(n["number"]),
395
+ appendix: s(n["appendix"]),
396
+ part: s(n["part"]),
397
+ });
398
+ }
399
+ throw new ParseFailed(`Unrecognized BIPM parse tree: ${JSON.stringify(tree)}`, 0);
400
+ }
401
+ buildCommittee(n, form, language) {
402
+ const year = s(n["year"]);
403
+ return new BipmCommitteeDocument({
404
+ group: normalizeGroup(s(n["group"])),
405
+ type_code: TYPE_WORD_TO_CODE[s(n["type_word"]) ?? ""],
406
+ number: s(n["number"]),
407
+ ...(year !== undefined ? { year: Number(year) } : {}),
408
+ language: normalizeLanguage(language ?? s(n["language"])),
409
+ form,
410
+ });
411
+ }
412
+ buildMeeting(n, language) {
413
+ const year = s(n["year"]);
414
+ return new BipmMeeting({
415
+ group: normalizeGroup(s(n["group"])),
416
+ number: s(n["number"]),
417
+ ...(year !== undefined ? { year: Number(year) } : {}),
418
+ language: normalizeLanguage(language ?? s(n["language"])),
419
+ });
420
+ }
421
+ }
422
+ export function bipmGrammarImplementation() {
423
+ const builder = new BipmBuilder();
424
+ return {
425
+ parse(input) {
426
+ const normalized = UPDATE_CODES[input] ?? input;
427
+ const tree = parseGrammar(bipmGrammar, normalized);
428
+ if (typeof tree !== "object" || tree === null) {
429
+ throw new ParseFailed("BIPM: unexpected parse tree", 0);
430
+ }
431
+ return builder.build(tree);
432
+ },
433
+ };
434
+ }
@@ -0,0 +1,4 @@
1
+ import { Grammar } from "../../grammar/engine.js";
2
+ export declare const bsiGrammar: Grammar;
3
+ /** Parser.parse normalization: "BSI " → "BS " except "BSI Flex". */
4
+ export declare function preprocessBsi(input: string): string;