@pubid/pubid 0.1.3 → 0.1.4
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.
- package/artifact/corpus.json.gz +0 -0
- package/dist/conformance/cli.js +5 -1
- package/dist/flavors/amca/grammar.d.ts +4 -0
- package/dist/flavors/amca/grammar.js +87 -0
- package/dist/flavors/amca/index.d.ts +4 -0
- package/dist/flavors/amca/index.js +76 -0
- package/dist/flavors/amca/model.d.ts +29 -0
- package/dist/flavors/amca/model.js +146 -0
- package/dist/flavors/ansi/index.d.ts +24 -0
- package/dist/flavors/ansi/index.js +147 -0
- package/dist/flavors/api/grammar.d.ts +4 -0
- package/dist/flavors/api/grammar.js +79 -0
- package/dist/flavors/api/index.d.ts +4 -0
- package/dist/flavors/api/index.js +71 -0
- package/dist/flavors/api/model.d.ts +27 -0
- package/dist/flavors/api/model.js +114 -0
- package/dist/flavors/ashrae/grammar.d.ts +2 -0
- package/dist/flavors/ashrae/grammar.js +667 -0
- package/dist/flavors/ashrae/index.d.ts +4 -0
- package/dist/flavors/ashrae/index.js +306 -0
- package/dist/flavors/ashrae/model.d.ts +87 -0
- package/dist/flavors/ashrae/model.js +335 -0
- package/dist/flavors/ashrae/preprocessor.d.ts +7 -0
- package/dist/flavors/ashrae/preprocessor.js +44 -0
- package/dist/flavors/asme/grammar.d.ts +2 -0
- package/dist/flavors/asme/grammar.js +200 -0
- package/dist/flavors/asme/index.d.ts +4 -0
- package/dist/flavors/asme/index.js +138 -0
- package/dist/flavors/asme/model.d.ts +34 -0
- package/dist/flavors/asme/model.js +123 -0
- package/dist/flavors/astm/grammar.d.ts +2 -0
- package/dist/flavors/astm/grammar.js +110 -0
- package/dist/flavors/astm/index.d.ts +2 -0
- package/dist/flavors/astm/index.js +127 -0
- package/dist/flavors/astm/model.d.ts +42 -0
- package/dist/flavors/astm/model.js +263 -0
- package/dist/flavors/bipm/index.d.ts +30 -0
- package/dist/flavors/bipm/index.js +434 -0
- package/dist/flavors/bsi/grammar.d.ts +4 -0
- package/dist/flavors/bsi/grammar.js +535 -0
- package/dist/flavors/bsi/index.d.ts +4 -0
- package/dist/flavors/bsi/index.js +941 -0
- package/dist/flavors/bsi/model.d.ts +127 -0
- package/dist/flavors/bsi/model.js +863 -0
- package/dist/flavors/calconnect/index.d.ts +21 -0
- package/dist/flavors/calconnect/index.js +113 -0
- package/dist/flavors/cen_cenelec/grammar.d.ts +4 -0
- package/dist/flavors/cen_cenelec/grammar.js +107 -0
- package/dist/flavors/cen_cenelec/index.d.ts +5 -0
- package/dist/flavors/cen_cenelec/index.js +263 -0
- package/dist/flavors/cen_cenelec/model.d.ts +45 -0
- package/dist/flavors/cen_cenelec/model.js +490 -0
- package/dist/flavors/cie/grammar.d.ts +5 -0
- package/dist/flavors/cie/grammar.js +127 -0
- package/dist/flavors/cie/index.d.ts +2 -0
- package/dist/flavors/cie/index.js +311 -0
- package/dist/flavors/cie/model.d.ts +122 -0
- package/dist/flavors/cie/model.js +464 -0
- package/dist/flavors/csa/grammar.d.ts +6 -0
- package/dist/flavors/csa/grammar.js +239 -0
- package/dist/flavors/csa/index.d.ts +2 -0
- package/dist/flavors/csa/index.js +634 -0
- package/dist/flavors/csa/model.d.ts +33 -0
- package/dist/flavors/csa/model.js +505 -0
- package/dist/flavors/doi/index.d.ts +13 -0
- package/dist/flavors/doi/index.js +65 -0
- package/dist/flavors/easc/index.d.ts +4 -0
- package/dist/flavors/easc/index.js +107 -0
- package/dist/flavors/ecma/index.d.ts +4 -0
- package/dist/flavors/ecma/index.js +117 -0
- package/dist/flavors/etsi/index.d.ts +14 -0
- package/dist/flavors/etsi/index.js +307 -0
- package/dist/flavors/evs/grammar.d.ts +2 -0
- package/dist/flavors/evs/grammar.js +22 -0
- package/dist/flavors/evs/index.d.ts +2 -0
- package/dist/flavors/evs/index.js +24 -0
- package/dist/flavors/evs/model.d.ts +19 -0
- package/dist/flavors/evs/model.js +36 -0
- package/dist/flavors/gb/index.d.ts +24 -0
- package/dist/flavors/gb/index.js +111 -0
- package/dist/flavors/gost/grammar.d.ts +2 -0
- package/dist/flavors/gost/grammar.js +46 -0
- package/dist/flavors/gost/index.d.ts +2 -0
- package/dist/flavors/gost/index.js +165 -0
- package/dist/flavors/gost/model.d.ts +61 -0
- package/dist/flavors/gost/model.js +147 -0
- package/dist/flavors/gost/prefix_routes.d.ts +15 -0
- package/dist/flavors/gost/prefix_routes.js +192 -0
- package/dist/flavors/iala/index.d.ts +32 -0
- package/dist/flavors/iala/index.js +300 -0
- package/dist/flavors/iana/index.d.ts +19 -0
- package/dist/flavors/iana/index.js +71 -0
- package/dist/flavors/idf/grammar.d.ts +2 -0
- package/dist/flavors/idf/grammar.js +71 -0
- package/dist/flavors/idf/index.d.ts +2 -0
- package/dist/flavors/idf/index.js +100 -0
- package/dist/flavors/idf/model.d.ts +54 -0
- package/dist/flavors/idf/model.js +359 -0
- package/dist/flavors/iec/grammar.d.ts +3 -0
- package/dist/flavors/iec/grammar.js +187 -0
- package/dist/flavors/iec/index.d.ts +4 -0
- package/dist/flavors/iec/index.js +507 -0
- package/dist/flavors/iec/model.d.ts +54 -0
- package/dist/flavors/iec/model.js +437 -0
- package/dist/flavors/ieee/grammar.d.ts +2 -0
- package/dist/flavors/ieee/grammar.js +626 -0
- package/dist/flavors/ieee/index.d.ts +3 -0
- package/dist/flavors/ieee/index.js +1186 -0
- package/dist/flavors/ieee/model.d.ts +142 -0
- package/dist/flavors/ieee/model.js +1148 -0
- package/dist/flavors/ieee/preprocessor.d.ts +8 -0
- package/dist/flavors/ieee/preprocessor.js +410 -0
- package/dist/flavors/ieee/update_codes.d.ts +8 -0
- package/dist/flavors/ieee/update_codes.js +191 -0
- package/dist/flavors/ietf/index.d.ts +30 -0
- package/dist/flavors/ietf/index.js +151 -0
- package/dist/flavors/iho/index.d.ts +4 -0
- package/dist/flavors/iho/index.js +126 -0
- package/dist/flavors/index.d.ts +9 -0
- package/dist/flavors/index.js +136 -0
- package/dist/flavors/isbn/index.d.ts +13 -0
- package/dist/flavors/isbn/index.js +97 -0
- package/dist/flavors/iso/grammar.d.ts +2 -0
- package/dist/flavors/iso/grammar.js +207 -0
- package/dist/flavors/iso/index.d.ts +2 -0
- package/dist/flavors/iso/index.js +343 -0
- package/dist/flavors/iso/model.d.ts +159 -0
- package/dist/flavors/iso/model.js +802 -0
- package/dist/flavors/iso/stages.generated.d.ts +13 -0
- package/dist/flavors/iso/stages.generated.js +391 -0
- package/dist/flavors/itu/grammar.d.ts +4 -0
- package/dist/flavors/itu/grammar.js +205 -0
- package/dist/flavors/itu/index.d.ts +2 -0
- package/dist/flavors/itu/index.js +224 -0
- package/dist/flavors/itu/model.d.ts +184 -0
- package/dist/flavors/itu/model.js +599 -0
- package/dist/flavors/jcgm/index.d.ts +7 -0
- package/dist/flavors/jcgm/index.js +300 -0
- package/dist/flavors/jis/index.d.ts +4 -0
- package/dist/flavors/jis/index.js +267 -0
- package/dist/flavors/nist/grammar.d.ts +2 -0
- package/dist/flavors/nist/grammar.js +287 -0
- package/dist/flavors/nist/index.d.ts +2 -0
- package/dist/flavors/nist/index.js +1244 -0
- package/dist/flavors/nist/model.d.ts +155 -0
- package/dist/flavors/nist/model.js +823 -0
- package/dist/flavors/nist/preprocessor.d.ts +11 -0
- package/dist/flavors/nist/preprocessor.js +281 -0
- package/dist/flavors/oasis/index.d.ts +23 -0
- package/dist/flavors/oasis/index.js +110 -0
- package/dist/flavors/ogc/index.d.ts +20 -0
- package/dist/flavors/ogc/index.js +75 -0
- package/dist/flavors/oiml/grammar.d.ts +2 -0
- package/dist/flavors/oiml/grammar.js +180 -0
- package/dist/flavors/oiml/implementation.d.ts +9 -0
- package/dist/flavors/oiml/implementation.js +16 -0
- package/dist/flavors/oiml/model.d.ts +4 -0
- package/dist/flavors/oiml/model.js +462 -0
- package/dist/flavors/omg/index.d.ts +14 -0
- package/dist/flavors/omg/index.js +73 -0
- package/dist/flavors/plateau/index.d.ts +4 -0
- package/dist/flavors/plateau/index.js +97 -0
- package/dist/flavors/tgpp/index.d.ts +4 -0
- package/dist/flavors/tgpp/index.js +122 -0
- package/dist/flavors/un/index.d.ts +13 -0
- package/dist/flavors/un/index.js +90 -0
- package/dist/flavors/w3c/index.d.ts +14 -0
- package/dist/flavors/w3c/index.js +148 -0
- package/dist/flavors/xsf/index.d.ts +18 -0
- package/dist/flavors/xsf/index.js +65 -0
- package/dist/grammar/engine.d.ts +78 -0
- package/dist/grammar/engine.js +351 -0
- package/dist/model/attribute.d.ts +54 -0
- package/dist/model/attribute.js +53 -0
- package/dist/model/builder.d.ts +39 -0
- package/dist/model/builder.js +124 -0
- package/dist/model/component.d.ts +70 -0
- package/dist/model/component.js +170 -0
- package/dist/model/identifier.d.ts +83 -0
- package/dist/model/identifier.js +270 -0
- package/dist/model/urn-generator.d.ts +27 -0
- package/dist/model/urn-generator.js +91 -0
- package/package.json +1 -1
|
@@ -0,0 +1,1186 @@
|
|
|
1
|
+
import { ParseFailed, parseGrammar } from "../../grammar/engine.js";
|
|
2
|
+
import { grammarImplementation } from "../index.js";
|
|
3
|
+
import { ieeeGrammar } from "./grammar.js";
|
|
4
|
+
import { preParse, preprocessIeee } from "./preprocessor.js";
|
|
5
|
+
import { applyUpdateCodes } from "./update_codes.js";
|
|
6
|
+
import { AdoptedStandardClass, AieeClass, AmendmentClass, ConformanceClass, CorrigendumClass, CsaDualPublishedClass, DualPublishedClass, IecIeeeCopublishedClass, IeeeCode, IeeeDraft, IeeeRelationship, IeeeTypedStage, InterpretationClass, IreClass, JointDevelopmentClass, MultiNumberedClass, NescDraftClass, NescEditionClass, NescHandbookClass, NescRedlineClass, NescStandardClass, ProjectDraftIdentifierClass, SiStandardClass, StandardClass, locateStage, } from "./model.js";
|
|
7
|
+
/**
|
|
8
|
+
* Port of lib/pubid/ieee/{builder}.rb + Identifier.parse orchestration
|
|
9
|
+
* (pre-parser dispatch, adopted/dual constructors, sub-builders).
|
|
10
|
+
*/
|
|
11
|
+
const isObj = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
12
|
+
const extractValue = (value) => {
|
|
13
|
+
if (value === undefined || value === null)
|
|
14
|
+
return undefined;
|
|
15
|
+
if (Array.isArray(value)) {
|
|
16
|
+
if (value.length === 0)
|
|
17
|
+
return undefined;
|
|
18
|
+
const joined = value.join("");
|
|
19
|
+
return joined.length > 0 ? joined : undefined;
|
|
20
|
+
}
|
|
21
|
+
const strValue = String(value).trim();
|
|
22
|
+
return strValue.length > 0 ? strValue : undefined;
|
|
23
|
+
};
|
|
24
|
+
function mergeParsedArray(parsedArray) {
|
|
25
|
+
return Object.assign({}, ...parsedArray);
|
|
26
|
+
}
|
|
27
|
+
const asHash = (v) => (Array.isArray(v) ? mergeParsedArray(v) : v);
|
|
28
|
+
const SI_STAGES = [
|
|
29
|
+
{ abbr: ["SI"], stage_code: "published", type_code: "SI" },
|
|
30
|
+
{ abbr: ["PSI"], stage_code: "draft", type_code: "SI" },
|
|
31
|
+
];
|
|
32
|
+
// --- Builder -----------------------------------------------------------------
|
|
33
|
+
class IeeeBuilder {
|
|
34
|
+
originalInput = "";
|
|
35
|
+
build(parsed) {
|
|
36
|
+
const d = Array.isArray(parsed) ? mergeParsedArray(parsed) : parsed;
|
|
37
|
+
if (d["ieee_portion"] !== undefined && d["csa_portion"] !== undefined) {
|
|
38
|
+
return this.buildCsaDualPublished(d);
|
|
39
|
+
}
|
|
40
|
+
if (d["s_number"] !== undefined)
|
|
41
|
+
return this.buildSDesignation(d);
|
|
42
|
+
if (d["first_aiee"] !== undefined && d["second_aiee"] !== undefined) {
|
|
43
|
+
return this.buildCombinedAiee(d);
|
|
44
|
+
}
|
|
45
|
+
if (d["content"] !== undefined)
|
|
46
|
+
return this.buildIecIeeCopublished(d);
|
|
47
|
+
if (d["nesc"] !== undefined)
|
|
48
|
+
return this.buildNesc(asHash(d["nesc"]));
|
|
49
|
+
if (d["aiee"] !== undefined)
|
|
50
|
+
return this.buildAiee(asHash(d["aiee"]));
|
|
51
|
+
if (d["ire"] !== undefined)
|
|
52
|
+
return this.buildIre(asHash(d["ire"]));
|
|
53
|
+
if (d["si_type"] !== undefined)
|
|
54
|
+
return this.buildSiPsi(d);
|
|
55
|
+
return this.buildSingleIdentifier(d, false);
|
|
56
|
+
}
|
|
57
|
+
// --- single identifier -----------------------------------------------------
|
|
58
|
+
buildSingleIdentifier(parsed, buildingSecondary) {
|
|
59
|
+
const parsedHash = asHash(parsed);
|
|
60
|
+
if (!buildingSecondary && parsedHash["primary_identifier"] !== undefined &&
|
|
61
|
+
(parsedHash["secondary_crossref"] !== undefined || parsedHash["secondary_joint"] !== undefined)) {
|
|
62
|
+
return this.buildMultiNumbered(parsedHash);
|
|
63
|
+
}
|
|
64
|
+
if (parsedHash["base"] !== undefined && parsedHash["cor_number"] !== undefined) {
|
|
65
|
+
return this.buildCorrigendumSupplement(parsedHash);
|
|
66
|
+
}
|
|
67
|
+
// A corrigendum capture that is a bare STRING matched the marker
|
|
68
|
+
// without its ordinal - never a valid complete parse (the reference
|
|
69
|
+
// rejects "…Corrigendum/D1").
|
|
70
|
+
if (typeof parsedHash["corrigendum"] === "string") {
|
|
71
|
+
throw new ParseFailed("corrigendum marker without ordinal", 0);
|
|
72
|
+
}
|
|
73
|
+
if (isObj(parsedHash["corrigendum"]) && parsedHash["base"] === undefined) {
|
|
74
|
+
// A corrigendum marker without its ordinal is not a marker - the
|
|
75
|
+
// reference never completes such a parse ("…Corrigendum/D1").
|
|
76
|
+
const cor = asHash(parsedHash["corrigendum"]);
|
|
77
|
+
if (cor["cor_number"] === undefined && cor["cor_year"] === undefined) {
|
|
78
|
+
throw new ParseFailed("corrigendum marker without ordinal", 0);
|
|
79
|
+
}
|
|
80
|
+
return this.buildFlatCorrigendum(parsedHash);
|
|
81
|
+
}
|
|
82
|
+
if (parsedHash["base"] !== undefined && parsedHash["amd_number"] !== undefined) {
|
|
83
|
+
return this.buildAmendmentSupplement(parsedHash);
|
|
84
|
+
}
|
|
85
|
+
if (isObj(parsedHash["amendment"]) && parsedHash["base"] === undefined) {
|
|
86
|
+
return this.buildFlatAmendment(parsedHash);
|
|
87
|
+
}
|
|
88
|
+
if (parsedHash["base"] !== undefined &&
|
|
89
|
+
(parsedHash["int_year"] !== undefined || parsedHash["interpretation"] !== undefined)) {
|
|
90
|
+
return this.buildInterpretationSupplement(parsedHash);
|
|
91
|
+
}
|
|
92
|
+
if (parsedHash["interpretation"] !== undefined && parsedHash["base"] === undefined) {
|
|
93
|
+
return this.buildFlatInterpretation(parsedHash);
|
|
94
|
+
}
|
|
95
|
+
if (parsedHash["base"] !== undefined && parsedHash["conf_number"] !== undefined) {
|
|
96
|
+
return this.buildConformanceSupplement(parsedHash);
|
|
97
|
+
}
|
|
98
|
+
if (parsedHash["joint_publishers"] !== undefined || parsedHash["iso_stage"] !== undefined) {
|
|
99
|
+
return this.buildJointDevelopment(parsedHash);
|
|
100
|
+
}
|
|
101
|
+
const attributes = this.extractAttributes(parsedHash);
|
|
102
|
+
if (parsedHash["relationship_type"] !== undefined || parsedHash["relationship_clause"] !== undefined) {
|
|
103
|
+
attributes["relationships"] = this.buildRelationships(parsedHash);
|
|
104
|
+
}
|
|
105
|
+
const klass = this.determineIdentifierClass(attributes);
|
|
106
|
+
// ProjectDraftIdentifier#initialize strips the leading P off the code
|
|
107
|
+
// string (the project marker lives in the stage, not the columns).
|
|
108
|
+
if (klass === ProjectDraftIdentifierClass) {
|
|
109
|
+
// The strip happens on the CODE STRING before Code.parse (Ruby
|
|
110
|
+
// ProjectDraftIdentifier#initialize), so "PIEEP62" -> prefix I.
|
|
111
|
+
const codeStr = attributes["__code"];
|
|
112
|
+
if (codeStr !== undefined && codeStr.startsWith("P")) {
|
|
113
|
+
const codeObj = IeeeCode.parse(codeStr.slice(1));
|
|
114
|
+
delete attributes["prefix"];
|
|
115
|
+
delete attributes["parts"];
|
|
116
|
+
delete attributes["separator"];
|
|
117
|
+
attributes["number"] = codeObj?.number;
|
|
118
|
+
if (codeObj?.prefix !== undefined)
|
|
119
|
+
attributes["prefix"] = codeObj.prefix;
|
|
120
|
+
if (codeObj !== undefined && codeObj.parts.length > 0)
|
|
121
|
+
attributes["parts"] = codeObj.parts;
|
|
122
|
+
if (codeObj?.originalSeparator !== undefined)
|
|
123
|
+
attributes["separator"] = codeObj.originalSeparator;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
delete attributes["__code"];
|
|
127
|
+
this.renameSupplementKeys(attributes);
|
|
128
|
+
return new klass(attributes);
|
|
129
|
+
}
|
|
130
|
+
renameSupplementKeys(attributes) {
|
|
131
|
+
const ordinal = attributes["cor_number"] ?? attributes["amd_number"] ?? attributes["conf_number"];
|
|
132
|
+
delete attributes["cor_number"];
|
|
133
|
+
delete attributes["amd_number"];
|
|
134
|
+
delete attributes["conf_number"];
|
|
135
|
+
if (ordinal !== undefined)
|
|
136
|
+
attributes["number"] = ordinal;
|
|
137
|
+
const year = attributes["cor_year"] ?? attributes["amd_year"] ?? attributes["conf_year"] ?? attributes["int_year"];
|
|
138
|
+
delete attributes["cor_year"];
|
|
139
|
+
delete attributes["amd_year"];
|
|
140
|
+
delete attributes["conf_year"];
|
|
141
|
+
delete attributes["int_year"];
|
|
142
|
+
if (year !== undefined)
|
|
143
|
+
attributes["year"] = year;
|
|
144
|
+
}
|
|
145
|
+
determineIdentifierClass(attributes) {
|
|
146
|
+
if (attributes["publisher"] === "AIEE")
|
|
147
|
+
return AieeClass;
|
|
148
|
+
const typeCode = attributes["type"];
|
|
149
|
+
if (typeCode === "P")
|
|
150
|
+
return ProjectDraftIdentifierClass;
|
|
151
|
+
if (typeCode === "SI" || typeCode === "PSI")
|
|
152
|
+
return SiStandardClass;
|
|
153
|
+
if (attributes["interpretation"] === true || attributes["int_year"] !== undefined) {
|
|
154
|
+
return InterpretationClass;
|
|
155
|
+
}
|
|
156
|
+
if (attributes["conf_number"] !== undefined)
|
|
157
|
+
return ConformanceClass;
|
|
158
|
+
if (attributes["cor_number"] !== undefined)
|
|
159
|
+
return CorrigendumClass;
|
|
160
|
+
if (attributes["amd_number"] !== undefined)
|
|
161
|
+
return AmendmentClass;
|
|
162
|
+
if (attributes["adoption"] !== undefined)
|
|
163
|
+
return AdoptedStandardClass;
|
|
164
|
+
return StandardClass;
|
|
165
|
+
}
|
|
166
|
+
// --- extract_attributes ----------------------------------------------------
|
|
167
|
+
extractAttributes(parsed) {
|
|
168
|
+
const attributes = {};
|
|
169
|
+
if (parsed["publishers"] !== undefined) {
|
|
170
|
+
const pubData = asHash(parsed["publishers"]);
|
|
171
|
+
attributes["publisher"] = extractValue(pubData["publisher"]);
|
|
172
|
+
if (pubData["copublishers"] !== undefined) {
|
|
173
|
+
const copubs = Array.isArray(pubData["copublishers"])
|
|
174
|
+
? pubData["copublishers"]
|
|
175
|
+
: [pubData["copublishers"]];
|
|
176
|
+
attributes["copublisher"] = copubs
|
|
177
|
+
.map((cp) => extractValue(asHash(cp)["copublisher"]))
|
|
178
|
+
.filter((cp) => cp !== undefined);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
else if (parsed["publisher"] !== undefined) {
|
|
182
|
+
attributes["publisher"] = extractValue(parsed["publisher"]);
|
|
183
|
+
}
|
|
184
|
+
const codeParts = [];
|
|
185
|
+
if (parsed["part"] !== undefined)
|
|
186
|
+
codeParts.push(extractValue(parsed["part"]) ?? "");
|
|
187
|
+
if (parsed["subpart"] !== undefined) {
|
|
188
|
+
const subparts = Array.isArray(parsed["subpart"]) ? parsed["subpart"] : [parsed["subpart"]];
|
|
189
|
+
for (const sp of subparts) {
|
|
190
|
+
const v = extractValue(sp);
|
|
191
|
+
if (v !== undefined)
|
|
192
|
+
codeParts.push(v);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
let codeStr = extractValue(parsed["number"]);
|
|
196
|
+
let typeValue = extractValue(parsed["type"]);
|
|
197
|
+
const draftStatusValue = extractValue(parsed["draft_status"]);
|
|
198
|
+
if (typeValue === undefined && this.originalInput !== "" && /IEEE\s+P/.test(this.originalInput)) {
|
|
199
|
+
typeValue = "P";
|
|
200
|
+
}
|
|
201
|
+
if (typeValue === undefined && this.originalInput !== "" && /ANSI\s+P/.test(this.originalInput)) {
|
|
202
|
+
typeValue = "P";
|
|
203
|
+
}
|
|
204
|
+
if (codeStr !== undefined && codeStr.startsWith("P") && this.originalInput.includes("/CSA")) {
|
|
205
|
+
const pubData = parsed["publishers"] !== undefined ? asHash(parsed["publishers"]) : undefined;
|
|
206
|
+
const hasCsaCopub = pubData?.["copublishers"] !== undefined
|
|
207
|
+
? (Array.isArray(pubData["copublishers"]) ? pubData["copublishers"] : [pubData["copublishers"]])
|
|
208
|
+
.some((cp) => (extractValue(asHash(cp)["copublisher"]) ?? "").includes("CSA"))
|
|
209
|
+
: this.originalInput.includes("/CSA");
|
|
210
|
+
if (hasCsaCopub)
|
|
211
|
+
codeStr = codeStr.replace(/^P/, "");
|
|
212
|
+
}
|
|
213
|
+
if (codeStr !== undefined && codeParts.length > 0) {
|
|
214
|
+
codeStr += `.${codeParts.join(".")}`;
|
|
215
|
+
}
|
|
216
|
+
if (codeStr !== undefined && parsed["year"] === undefined && codeParts.length === 0) {
|
|
217
|
+
const m = /^(.+)-(\d{4})$/.exec(codeStr);
|
|
218
|
+
if (m !== null) {
|
|
219
|
+
const potentialYear = Number.parseInt(m[2], 10);
|
|
220
|
+
if (potentialYear >= 1884 && potentialYear <= 2099) {
|
|
221
|
+
codeStr = m[1];
|
|
222
|
+
parsed["year"] = m[2];
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
const codeObj = codeStr !== undefined ? IeeeCode.parse(codeStr) : undefined;
|
|
227
|
+
if (codeStr !== undefined)
|
|
228
|
+
attributes["__code"] = codeStr;
|
|
229
|
+
if (codeObj !== undefined) {
|
|
230
|
+
attributes["number"] = codeObj.number;
|
|
231
|
+
if (codeObj.prefix !== undefined)
|
|
232
|
+
attributes["prefix"] = codeObj.prefix;
|
|
233
|
+
if (codeObj.parts.length > 0)
|
|
234
|
+
attributes["parts"] = codeObj.parts;
|
|
235
|
+
if (codeObj.originalSeparator !== undefined)
|
|
236
|
+
attributes["separator"] = codeObj.originalSeparator;
|
|
237
|
+
}
|
|
238
|
+
if (parsed["year"] !== undefined) {
|
|
239
|
+
attributes["year"] = extractValue(parsed["year"]);
|
|
240
|
+
}
|
|
241
|
+
else if (parsed["edition_year"] !== undefined) {
|
|
242
|
+
attributes["year"] = extractValue(parsed["edition_year"]);
|
|
243
|
+
}
|
|
244
|
+
else if (parsed["trailing_year"] !== undefined) {
|
|
245
|
+
attributes["year"] = extractValue(parsed["trailing_year"]);
|
|
246
|
+
if (parsed["trailing_month"] !== undefined) {
|
|
247
|
+
attributes["month"] = extractValue(parsed["trailing_month"]);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
if (parsed["edition_month"] !== undefined) {
|
|
251
|
+
attributes["edition_month"] = extractValue(parsed["edition_month"]);
|
|
252
|
+
}
|
|
253
|
+
// The historical "No"-prefixed spellings ("IEEE No148, April 1959")
|
|
254
|
+
// are plain standards - No normalizes to Std so the render prints
|
|
255
|
+
// "IEEE Std 148" and the stage lookup resolves. AIEE keeps its No.
|
|
256
|
+
if (typeValue !== undefined && /^No\.?$/.test(typeValue) &&
|
|
257
|
+
/^IEEE\s/.test(this.originalInput)) {
|
|
258
|
+
typeValue = "Std";
|
|
259
|
+
}
|
|
260
|
+
if (typeValue !== undefined)
|
|
261
|
+
attributes["type"] = typeValue;
|
|
262
|
+
const typedStageAbbr = this.determineStageAbbr(typeValue, parsed);
|
|
263
|
+
if (typedStageAbbr !== undefined) {
|
|
264
|
+
const record = locateStage(typedStageAbbr);
|
|
265
|
+
if (record !== undefined)
|
|
266
|
+
attributes["typed_stage"] = new IeeeTypedStage(record);
|
|
267
|
+
}
|
|
268
|
+
attributes["draft_status"] = draftStatusValue;
|
|
269
|
+
for (const key of ["edition", "revision"]) {
|
|
270
|
+
const value = extractValue(parsed[key]);
|
|
271
|
+
if (value !== undefined)
|
|
272
|
+
attributes[key] = value;
|
|
273
|
+
}
|
|
274
|
+
if (attributes["edition_month"] === undefined) {
|
|
275
|
+
const month = extractValue(parsed["month"]);
|
|
276
|
+
if (month !== undefined)
|
|
277
|
+
attributes["month"] = month;
|
|
278
|
+
}
|
|
279
|
+
const day = extractValue(parsed["day"]);
|
|
280
|
+
if (day !== undefined)
|
|
281
|
+
attributes["day"] = day;
|
|
282
|
+
this.handleDraft(parsed, attributes);
|
|
283
|
+
this.applyDefaultDraftVersion(attributes, typeValue);
|
|
284
|
+
this.handleKeyedHash(parsed, "corrigendum", attributes, "cor_number", "cor_year");
|
|
285
|
+
this.handleKeyedHash(parsed, "amendment", attributes, "amd_number", "amd_year");
|
|
286
|
+
this.handleKeyedHash(parsed, "conformance", attributes, "conf_number", "conf_year");
|
|
287
|
+
this.handleAshraeCopub(parsed, attributes);
|
|
288
|
+
this.handleIeeeCrossref(parsed, attributes);
|
|
289
|
+
this.handleReaffirmed(parsed, attributes);
|
|
290
|
+
this.handleParameters(parsed, attributes);
|
|
291
|
+
if (parsed["nickname"] !== undefined) {
|
|
292
|
+
attributes["nickname"] = extractValue(parsed["nickname"]);
|
|
293
|
+
}
|
|
294
|
+
if (parsed["interpretation"] !== undefined)
|
|
295
|
+
attributes["interpretation"] = true;
|
|
296
|
+
if (parsed["redline"] !== undefined)
|
|
297
|
+
attributes["redline"] = true;
|
|
298
|
+
return attributes;
|
|
299
|
+
}
|
|
300
|
+
determineStageAbbr(typeValue, parsed) {
|
|
301
|
+
if (parsed["draft"] !== undefined) {
|
|
302
|
+
let draftData = parsed["draft"];
|
|
303
|
+
if (Array.isArray(draftData)) {
|
|
304
|
+
draftData = mergeParsedArray(draftData);
|
|
305
|
+
}
|
|
306
|
+
if (isObj(draftData) && draftData["draft_version"] !== undefined) {
|
|
307
|
+
const dv = draftData["draft_version"];
|
|
308
|
+
const version = Array.isArray(dv) ? dv.map((v) => extractValue(v) ?? "").join("") : extractValue(dv);
|
|
309
|
+
if (version !== undefined) {
|
|
310
|
+
const draftAbbr = `D${version}`;
|
|
311
|
+
const stage = locateStage(draftAbbr);
|
|
312
|
+
if (stage !== undefined && stage.abbr.includes(draftAbbr))
|
|
313
|
+
return draftAbbr;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
if (typeValue !== undefined) {
|
|
318
|
+
if (typeValue.startsWith("P"))
|
|
319
|
+
return "P";
|
|
320
|
+
if (typeValue === "Std")
|
|
321
|
+
return "Std";
|
|
322
|
+
if (typeValue === "Draft Std" && parsed["draft"] === undefined && parsed["digit_draft"] === undefined) {
|
|
323
|
+
return "D1";
|
|
324
|
+
}
|
|
325
|
+
if (/^No\.?$/.test(typeValue))
|
|
326
|
+
return typeValue;
|
|
327
|
+
}
|
|
328
|
+
return "Std";
|
|
329
|
+
}
|
|
330
|
+
handleDraft(parsed, attributes) {
|
|
331
|
+
let draftData = parsed["draft"] ?? parsed["digit_draft"];
|
|
332
|
+
if (draftData === undefined)
|
|
333
|
+
return;
|
|
334
|
+
if (Array.isArray(draftData)) {
|
|
335
|
+
const hashes = draftData.filter((e) => isObj(e));
|
|
336
|
+
const versions = hashes
|
|
337
|
+
.map((e) => e["draft_version"])
|
|
338
|
+
.filter((v) => v !== undefined);
|
|
339
|
+
const merged = Object.assign({}, ...hashes);
|
|
340
|
+
if (versions.length > 0)
|
|
341
|
+
merged["draft_version"] = versions;
|
|
342
|
+
draftData = merged;
|
|
343
|
+
}
|
|
344
|
+
let version;
|
|
345
|
+
let revision;
|
|
346
|
+
let month;
|
|
347
|
+
let year;
|
|
348
|
+
let day;
|
|
349
|
+
let commaBeforeMonth = false;
|
|
350
|
+
if (isObj(draftData)) {
|
|
351
|
+
if (draftData["draft_version"] !== undefined) {
|
|
352
|
+
const dv = draftData["draft_version"];
|
|
353
|
+
version = Array.isArray(dv) ? dv.map((v) => extractValue(v) ?? "").join("") : extractValue(dv);
|
|
354
|
+
if (version !== undefined)
|
|
355
|
+
version = version.replace(/^-/, "");
|
|
356
|
+
}
|
|
357
|
+
revision = extractValue(draftData["revision"]);
|
|
358
|
+
month = extractValue(draftData["month"]);
|
|
359
|
+
year = extractValue(draftData["year"]);
|
|
360
|
+
day = extractValue(draftData["day"]);
|
|
361
|
+
if (this.originalInput !== "" && month !== undefined) {
|
|
362
|
+
commaBeforeMonth = new RegExp(`,\\s+${month.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}`, "i")
|
|
363
|
+
.test(this.originalInput);
|
|
364
|
+
}
|
|
365
|
+
if (version !== undefined && this.originalInput !== "" &&
|
|
366
|
+
new RegExp(`\\s+/D${version.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}`, "i").test(this.originalInput)) {
|
|
367
|
+
attributes["space_before_draft"] = true;
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
else {
|
|
371
|
+
version = extractValue(draftData);
|
|
372
|
+
}
|
|
373
|
+
if (version !== undefined) {
|
|
374
|
+
const draftObj = new IeeeDraft({
|
|
375
|
+
version,
|
|
376
|
+
revision,
|
|
377
|
+
month,
|
|
378
|
+
year,
|
|
379
|
+
day,
|
|
380
|
+
comma_before_month: commaBeforeMonth,
|
|
381
|
+
});
|
|
382
|
+
attributes["draft"] = draftObj.render();
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
applyDefaultDraftVersion(attributes, typeValue) {
|
|
386
|
+
if (attributes["draft"] !== undefined)
|
|
387
|
+
return;
|
|
388
|
+
if (typeValue !== "Draft Std")
|
|
389
|
+
return;
|
|
390
|
+
attributes["draft"] = new IeeeDraft({ version: "1", year: attributes["year"] }).render();
|
|
391
|
+
}
|
|
392
|
+
handleKeyedHash(parsed, key, attributes, numberKey, yearKey) {
|
|
393
|
+
if (isObj(parsed[key])) {
|
|
394
|
+
const data = parsed[key];
|
|
395
|
+
attributes[numberKey] = extractValue(data[numberKey]);
|
|
396
|
+
if (data[yearKey] !== undefined)
|
|
397
|
+
attributes[yearKey] = extractValue(data[yearKey]);
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
handleAshraeCopub(parsed, attributes) {
|
|
401
|
+
if (isObj(parsed["ashrae_copub"])) {
|
|
402
|
+
const data = parsed["ashrae_copub"];
|
|
403
|
+
attributes["ashrae_number"] = extractValue(data["ashrae_number"]);
|
|
404
|
+
if (data["ashrae_year"] !== undefined) {
|
|
405
|
+
attributes["ashrae_year"] = extractValue(data["ashrae_year"]);
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
handleIeeeCrossref(parsed, attributes) {
|
|
410
|
+
if (parsed["ieee_crossref"] !== undefined) {
|
|
411
|
+
const raw = extractValue(parsed["ieee_crossref"]) ?? "";
|
|
412
|
+
attributes["crossref"] = `/C${raw.replace(/^\//, "")}`;
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
handleReaffirmed(parsed, attributes) {
|
|
416
|
+
if (isObj(parsed["reaffirmed"])) {
|
|
417
|
+
attributes["reaffirmed"] = extractValue(parsed["reaffirmed"]["year"]);
|
|
418
|
+
}
|
|
419
|
+
else if (parsed["reaffirmed"] !== undefined) {
|
|
420
|
+
attributes["reaffirmed"] = extractValue(parsed["reaffirmed"]);
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
handleParameters(parsed, attributes) {
|
|
424
|
+
if (!isObj(parsed["parameters"]))
|
|
425
|
+
return;
|
|
426
|
+
const paramData = parsed["parameters"];
|
|
427
|
+
for (const key of ["parenthetical_content", "revision_of", "amendment_to", "adoption", "note"]) {
|
|
428
|
+
const value = extractValue(paramData[key]);
|
|
429
|
+
if (value !== undefined)
|
|
430
|
+
attributes[key] = value;
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
parseIdentifierList(listData) {
|
|
434
|
+
if (listData === undefined || listData === null)
|
|
435
|
+
return [];
|
|
436
|
+
const entries = Array.isArray(listData) ? listData : [listData];
|
|
437
|
+
const idStrings = [];
|
|
438
|
+
for (const entry of entries) {
|
|
439
|
+
if (isObj(entry) && entry["id"] !== undefined) {
|
|
440
|
+
idStrings.push(String(entry["id"]).trim());
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
return idStrings.map((idStr) => {
|
|
444
|
+
try {
|
|
445
|
+
return ieeeParse(idStr);
|
|
446
|
+
}
|
|
447
|
+
catch {
|
|
448
|
+
return new StandardClass({ parenthetical_content: idStr });
|
|
449
|
+
}
|
|
450
|
+
});
|
|
451
|
+
}
|
|
452
|
+
relationshipFrom(relData) {
|
|
453
|
+
if (!isObj(relData["relationship_type"]))
|
|
454
|
+
return undefined;
|
|
455
|
+
const firstKey = Object.keys(relData["relationship_type"])[0];
|
|
456
|
+
if (firstKey === undefined)
|
|
457
|
+
return undefined;
|
|
458
|
+
let amendments = [];
|
|
459
|
+
if (relData["amendments"] !== undefined && !isObj(relData["amendments"])) {
|
|
460
|
+
amendments = this.parseIdentifierList(relData["amendments"]);
|
|
461
|
+
}
|
|
462
|
+
return new IeeeRelationship(firstKey, this.parseIdentifierList(relData["related_ids"]), amendments, isObj(relData["amendments"]) && relData["amendments"]["approved_amendments"] !== undefined);
|
|
463
|
+
}
|
|
464
|
+
buildRelationships(parsedHash) {
|
|
465
|
+
const relationships = [];
|
|
466
|
+
if (parsedHash["relationship_type"] !== undefined || parsedHash["relationship_clause"] !== undefined) {
|
|
467
|
+
const rel = this.relationshipFrom(parsedHash);
|
|
468
|
+
if (rel !== undefined)
|
|
469
|
+
relationships.push(rel);
|
|
470
|
+
}
|
|
471
|
+
if (parsedHash["additional_rels"] !== undefined) {
|
|
472
|
+
const additional = Array.isArray(parsedHash["additional_rels"])
|
|
473
|
+
? parsedHash["additional_rels"]
|
|
474
|
+
: [parsedHash["additional_rels"]];
|
|
475
|
+
for (const relData of additional) {
|
|
476
|
+
if (isObj(relData)) {
|
|
477
|
+
const rel = this.relationshipFrom(relData);
|
|
478
|
+
if (rel !== undefined)
|
|
479
|
+
relationships.push(rel);
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
return relationships;
|
|
484
|
+
}
|
|
485
|
+
// --- supplements and wrappers ----------------------------------------------
|
|
486
|
+
reconstructBaseString(baseData) {
|
|
487
|
+
const baseParts = [];
|
|
488
|
+
if (baseData["publishers"] !== undefined) {
|
|
489
|
+
const pubData = asHash(baseData["publishers"]);
|
|
490
|
+
let publisherStr = extractValue(pubData["publisher"]) ?? "";
|
|
491
|
+
if (pubData["copublishers"] !== undefined && pubData["copublishers"] !== "") {
|
|
492
|
+
const copubs = Array.isArray(pubData["copublishers"])
|
|
493
|
+
? pubData["copublishers"]
|
|
494
|
+
: [pubData["copublishers"]];
|
|
495
|
+
const copubStrs = copubs
|
|
496
|
+
.map((cp) => extractValue(asHash(cp)["copublisher"]))
|
|
497
|
+
.filter((cp) => cp !== undefined);
|
|
498
|
+
if (copubStrs.length > 0)
|
|
499
|
+
publisherStr += `/${copubStrs.join("/")}`;
|
|
500
|
+
}
|
|
501
|
+
baseParts.push(publisherStr);
|
|
502
|
+
}
|
|
503
|
+
if (baseData["type"] !== undefined) {
|
|
504
|
+
baseParts.push(extractValue(baseData["type"]) ?? "");
|
|
505
|
+
}
|
|
506
|
+
let numberStr = extractValue(baseData["number"]) ?? "";
|
|
507
|
+
if (baseData["part"] !== undefined) {
|
|
508
|
+
numberStr += `.${extractValue(baseData["part"]) ?? ""}`;
|
|
509
|
+
}
|
|
510
|
+
if (baseData["subpart"] !== undefined) {
|
|
511
|
+
const subparts = Array.isArray(baseData["subpart"]) ? baseData["subpart"] : [baseData["subpart"]];
|
|
512
|
+
for (const sp of subparts) {
|
|
513
|
+
const v = extractValue(sp);
|
|
514
|
+
if (v !== undefined)
|
|
515
|
+
numberStr += `.${v}`;
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
if (baseData["year"] !== undefined) {
|
|
519
|
+
numberStr += `-${extractValue(baseData["year"]) ?? ""}`;
|
|
520
|
+
}
|
|
521
|
+
baseParts.push(numberStr);
|
|
522
|
+
return baseParts.join(" ");
|
|
523
|
+
}
|
|
524
|
+
buildCorrigendumSupplement(parsedHash) {
|
|
525
|
+
const base = ieeeParseSingle(this.reconstructBaseString(asHash(parsedHash["base"])));
|
|
526
|
+
const corNumber = extractValue(parsedHash["cor_number"]);
|
|
527
|
+
const corYear = extractValue(parsedHash["cor_year"]);
|
|
528
|
+
return new CorrigendumClass({
|
|
529
|
+
base, number: corNumber, year: corYear,
|
|
530
|
+
});
|
|
531
|
+
}
|
|
532
|
+
buildFlatCorrigendum(parsedHash) {
|
|
533
|
+
const corData = parsedHash["corrigendum"];
|
|
534
|
+
const corNumber = extractValue(corData["cor_number"]);
|
|
535
|
+
const corYear = corData["cor_year"] !== undefined ? extractValue(corData["cor_year"]) : undefined;
|
|
536
|
+
const baseHash = { ...parsedHash };
|
|
537
|
+
delete baseHash["corrigendum"];
|
|
538
|
+
const base = this.buildSingleIdentifier(baseHash, false);
|
|
539
|
+
return new CorrigendumClass({
|
|
540
|
+
base, number: corNumber, year: corYear,
|
|
541
|
+
});
|
|
542
|
+
}
|
|
543
|
+
buildFlatAmendment(parsedHash) {
|
|
544
|
+
const amdData = parsedHash["amendment"];
|
|
545
|
+
const amdNumber = extractValue(amdData["amd_number"]);
|
|
546
|
+
const amdYear = amdData["amd_year"] !== undefined ? extractValue(amdData["amd_year"]) : undefined;
|
|
547
|
+
const baseHash = { ...parsedHash };
|
|
548
|
+
delete baseHash["amendment"];
|
|
549
|
+
const base = this.buildSingleIdentifier(baseHash, false);
|
|
550
|
+
return new AmendmentClass({
|
|
551
|
+
base, number: amdNumber, year: amdYear,
|
|
552
|
+
});
|
|
553
|
+
}
|
|
554
|
+
buildFlatInterpretation(parsedHash) {
|
|
555
|
+
const intYear = parsedHash["trailing_year"] !== undefined
|
|
556
|
+
? extractValue(parsedHash["trailing_year"])
|
|
557
|
+
: undefined;
|
|
558
|
+
const baseHash = { ...parsedHash };
|
|
559
|
+
delete baseHash["interpretation"];
|
|
560
|
+
delete baseHash["trailing_month"];
|
|
561
|
+
delete baseHash["trailing_year"];
|
|
562
|
+
const base = this.buildSingleIdentifier(baseHash, false);
|
|
563
|
+
return new InterpretationClass({
|
|
564
|
+
base, year: intYear,
|
|
565
|
+
});
|
|
566
|
+
}
|
|
567
|
+
buildInterpretationSupplement(parsedHash) {
|
|
568
|
+
const base = ieeeParseSingle(this.reconstructBaseString(asHash(parsedHash["base"])));
|
|
569
|
+
const intYear = extractValue(parsedHash["int_year"]);
|
|
570
|
+
return new InterpretationClass({
|
|
571
|
+
base, year: intYear,
|
|
572
|
+
});
|
|
573
|
+
}
|
|
574
|
+
buildAmendmentSupplement(parsedHash) {
|
|
575
|
+
const base = ieeeParseSingle(this.reconstructBaseString(asHash(parsedHash["base"])));
|
|
576
|
+
return new AmendmentClass({
|
|
577
|
+
base,
|
|
578
|
+
number: extractValue(parsedHash["amd_number"]),
|
|
579
|
+
year: extractValue(parsedHash["amd_year"]),
|
|
580
|
+
});
|
|
581
|
+
}
|
|
582
|
+
buildConformanceSupplement(parsedHash) {
|
|
583
|
+
const base = ieeeParseSingle(this.reconstructBaseString(asHash(parsedHash["base"])));
|
|
584
|
+
return new ConformanceClass({
|
|
585
|
+
base,
|
|
586
|
+
number: extractValue(parsedHash["conf_number"]),
|
|
587
|
+
year: extractValue(parsedHash["conf_year"]),
|
|
588
|
+
});
|
|
589
|
+
}
|
|
590
|
+
buildJointDevelopment(parsed) {
|
|
591
|
+
const attributes = {};
|
|
592
|
+
if (parsed["joint_publishers"] !== undefined) {
|
|
593
|
+
const jointPubStr = extractValue(parsed["joint_publishers"]) ?? "";
|
|
594
|
+
const pubs = jointPubStr.split("/");
|
|
595
|
+
attributes["publishers"] = pubs;
|
|
596
|
+
attributes["publisher"] = pubs[0];
|
|
597
|
+
attributes["copublisher"] = pubs.slice(1);
|
|
598
|
+
}
|
|
599
|
+
const codeParts = [];
|
|
600
|
+
if (parsed["part"] !== undefined)
|
|
601
|
+
codeParts.push(extractValue(parsed["part"]) ?? "");
|
|
602
|
+
let codeStr = extractValue(parsed["number"]);
|
|
603
|
+
if (codeStr !== undefined && codeParts.length > 0) {
|
|
604
|
+
codeStr += `.${codeParts.join(".")}`;
|
|
605
|
+
}
|
|
606
|
+
if (codeStr !== undefined) {
|
|
607
|
+
const codeObj = IeeeCode.parse(codeStr);
|
|
608
|
+
if (codeObj !== undefined) {
|
|
609
|
+
attributes["number"] = codeObj.number;
|
|
610
|
+
if (codeObj.prefix !== undefined)
|
|
611
|
+
attributes["prefix"] = codeObj.prefix;
|
|
612
|
+
if (codeObj.parts.length > 0)
|
|
613
|
+
attributes["parts"] = codeObj.parts;
|
|
614
|
+
if (codeObj.originalSeparator !== undefined)
|
|
615
|
+
attributes["separator"] = codeObj.originalSeparator;
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
if (parsed["year"] !== undefined) {
|
|
619
|
+
attributes["year"] = extractValue(parsed["year"]);
|
|
620
|
+
}
|
|
621
|
+
else if (parsed["edition_year"] !== undefined) {
|
|
622
|
+
attributes["year"] = extractValue(parsed["edition_year"]);
|
|
623
|
+
}
|
|
624
|
+
if (parsed["month"] !== undefined)
|
|
625
|
+
attributes["month"] = extractValue(parsed["month"]);
|
|
626
|
+
if (parsed["draft_year"] !== undefined) {
|
|
627
|
+
if (attributes["year"] === undefined)
|
|
628
|
+
attributes["year"] = extractValue(parsed["draft_year"]);
|
|
629
|
+
if (attributes["month"] === undefined)
|
|
630
|
+
attributes["month"] = extractValue(parsed["draft_month"]);
|
|
631
|
+
}
|
|
632
|
+
if (parsed["edition"] !== undefined)
|
|
633
|
+
attributes["edition"] = extractValue(parsed["edition"]);
|
|
634
|
+
if (parsed["edition_month"] !== undefined) {
|
|
635
|
+
attributes["edition_month"] = extractValue(parsed["edition_month"]);
|
|
636
|
+
}
|
|
637
|
+
if (parsed["draft_version"] !== undefined) {
|
|
638
|
+
const draftVer = (extractValue(parsed["draft_version"]) ?? "").replace(/^D/, "");
|
|
639
|
+
if (draftVer !== "")
|
|
640
|
+
attributes["ieee_draft"] = `D${draftVer}`;
|
|
641
|
+
}
|
|
642
|
+
// The catalogue-PRINTED joint form (dash-year / ", Month YYYY" /
|
|
643
|
+
// date-trailing-the-draft / date-less parenthetical): a Standard
|
|
644
|
+
// carrying publisher/copublisher renders it as printed; the colon-year
|
|
645
|
+
// spelling stays the ISO-style JointDevelopment. Stage-WORD drafts
|
|
646
|
+
// (letters, not a D-number) stay joint - their canonical renders drop
|
|
647
|
+
// the P and keep the joint spelling.
|
|
648
|
+
const numericDraft = parsed["draft_version"] !== undefined &&
|
|
649
|
+
/^\d/.test(extractValue(parsed["draft_version"]) ?? "");
|
|
650
|
+
if (parsed["iso_published"] !== undefined &&
|
|
651
|
+
(parsed["printed_dash_year"] !== undefined || parsed["printed_month_year"] !== undefined ||
|
|
652
|
+
(numericDraft && parsed["draft_month"] !== undefined) ||
|
|
653
|
+
(parsed["year"] === undefined && parsed["parameters"] !== undefined &&
|
|
654
|
+
typeof parsed["parameters"] === "object" && !Array.isArray(parsed["parameters"]) &&
|
|
655
|
+
parsed["parameters"]["parenthetical_content"] !== undefined))) {
|
|
656
|
+
const sep = parsed["part_dash"] !== undefined ? "-" : ".";
|
|
657
|
+
const printedCode = [extractValue(parsed["number"]), extractValue(parsed["part"])]
|
|
658
|
+
.filter((x) => x !== undefined).join(sep);
|
|
659
|
+
const printedAttrs = {
|
|
660
|
+
publisher: attributes["publisher"],
|
|
661
|
+
copublisher: attributes["copublisher"],
|
|
662
|
+
typed_stage: locateStage("Std") !== undefined ? new IeeeTypedStage(locateStage("Std")) : undefined,
|
|
663
|
+
};
|
|
664
|
+
let printedDraft = attributes["ieee_draft"];
|
|
665
|
+
let finalCode = printedCode;
|
|
666
|
+
if (parsed["printed_dash_year"] !== undefined && parsed["month"] !== undefined) {
|
|
667
|
+
// A dash-year-month date glues onto the printed code before any
|
|
668
|
+
// draft - the render's month slot would lose the printed form.
|
|
669
|
+
finalCode = `${printedCode}-${attributes["year"]}-${attributes["month"]}`;
|
|
670
|
+
}
|
|
671
|
+
else if (parsed["printed_dash_year"] !== undefined) {
|
|
672
|
+
// A bare dash-year is the identity year - an attribute.
|
|
673
|
+
printedAttrs["year"] = attributes["year"];
|
|
674
|
+
}
|
|
675
|
+
else if (parsed["printed_month_year"] !== undefined) {
|
|
676
|
+
printedAttrs["year"] = attributes["year"];
|
|
677
|
+
printedAttrs["month"] = attributes["month"];
|
|
678
|
+
}
|
|
679
|
+
else if (parsed["draft_month"] !== undefined) {
|
|
680
|
+
// The date trails the draft itself; keep it inside the draft so
|
|
681
|
+
// the code stays date-less.
|
|
682
|
+
printedDraft = `${printedDraft}, ${extractValue(parsed["draft_month"])} ${extractValue(parsed["draft_year"])}`;
|
|
683
|
+
}
|
|
684
|
+
const codeObj = IeeeCode.parse(finalCode);
|
|
685
|
+
if (codeObj !== undefined) {
|
|
686
|
+
printedAttrs["number"] = codeObj.number;
|
|
687
|
+
if (codeObj.prefix !== undefined)
|
|
688
|
+
printedAttrs["prefix"] = codeObj.prefix;
|
|
689
|
+
if (codeObj.parts.length > 0)
|
|
690
|
+
printedAttrs["parts"] = codeObj.parts;
|
|
691
|
+
if (codeObj.originalSeparator !== undefined)
|
|
692
|
+
printedAttrs["separator"] = codeObj.originalSeparator;
|
|
693
|
+
}
|
|
694
|
+
if (printedDraft !== undefined)
|
|
695
|
+
printedAttrs["draft"] = printedDraft;
|
|
696
|
+
if (attributes["edition"] !== undefined)
|
|
697
|
+
printedAttrs["edition"] = attributes["edition"];
|
|
698
|
+
if (attributes["edition_month"] !== undefined)
|
|
699
|
+
printedAttrs["edition_month"] = attributes["edition_month"];
|
|
700
|
+
const params = parsed["parameters"];
|
|
701
|
+
if (params !== undefined && typeof params === "object" && !Array.isArray(params) &&
|
|
702
|
+
params["parenthetical_content"] !== undefined) {
|
|
703
|
+
printedAttrs["parenthetical_content"] = extractValue(params["parenthetical_content"]);
|
|
704
|
+
}
|
|
705
|
+
for (const k of Object.keys(printedAttrs)) {
|
|
706
|
+
if (printedAttrs[k] === undefined)
|
|
707
|
+
delete printedAttrs[k];
|
|
708
|
+
}
|
|
709
|
+
return new StandardClass(printedAttrs);
|
|
710
|
+
}
|
|
711
|
+
if (parsed["iso_stage"] !== undefined) {
|
|
712
|
+
attributes["lead_party"] = "ISO";
|
|
713
|
+
const stageAbbr = extractValue(parsed["iso_stage"]);
|
|
714
|
+
attributes["iso_stage"] = stageAbbr;
|
|
715
|
+
if (stageAbbr !== undefined) {
|
|
716
|
+
const record = locateStage(stageAbbr);
|
|
717
|
+
if (record !== undefined)
|
|
718
|
+
attributes["typed_stage"] = new IeeeTypedStage(record);
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
else if (parsed["iso_published"] !== undefined) {
|
|
722
|
+
attributes["lead_party"] = "ISO";
|
|
723
|
+
}
|
|
724
|
+
else {
|
|
725
|
+
attributes["lead_party"] = "IEEE";
|
|
726
|
+
attributes["type"] = "P";
|
|
727
|
+
const record = locateStage("P");
|
|
728
|
+
if (record !== undefined)
|
|
729
|
+
attributes["typed_stage"] = new IeeeTypedStage(record);
|
|
730
|
+
}
|
|
731
|
+
const joint = new JointDevelopmentClass(attributes);
|
|
732
|
+
if (parsed["amd_number"] === undefined)
|
|
733
|
+
return joint;
|
|
734
|
+
const amdYear = parsed["amd_year"] !== undefined ? extractValue(parsed["amd_year"]) : undefined;
|
|
735
|
+
return new AmendmentClass({
|
|
736
|
+
base: joint,
|
|
737
|
+
number: extractValue(parsed["amd_number"]),
|
|
738
|
+
year: amdYear,
|
|
739
|
+
});
|
|
740
|
+
}
|
|
741
|
+
buildSiPsi(parsed) {
|
|
742
|
+
const attributes = {};
|
|
743
|
+
const siType = extractValue(parsed["si_type"]);
|
|
744
|
+
if (parsed["publishers"] !== undefined) {
|
|
745
|
+
const publishersStr = extractValue(parsed["publishers"]) ?? "";
|
|
746
|
+
const pubs = publishersStr.split("/");
|
|
747
|
+
attributes["publisher"] = pubs[0];
|
|
748
|
+
if (pubs.length > 1)
|
|
749
|
+
attributes["copublisher"] = pubs.slice(1);
|
|
750
|
+
}
|
|
751
|
+
const codeStr = extractValue(parsed["number"]);
|
|
752
|
+
if (codeStr !== undefined) {
|
|
753
|
+
const codeObj = IeeeCode.parse(codeStr);
|
|
754
|
+
if (codeObj !== undefined) {
|
|
755
|
+
attributes["number"] = codeObj.number;
|
|
756
|
+
if (codeObj.prefix !== undefined)
|
|
757
|
+
attributes["prefix"] = codeObj.prefix;
|
|
758
|
+
if (codeObj.parts.length > 0)
|
|
759
|
+
attributes["parts"] = codeObj.parts;
|
|
760
|
+
if (codeObj.originalSeparator !== undefined)
|
|
761
|
+
attributes["separator"] = codeObj.originalSeparator;
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
const stageRecord = SI_STAGES.find((ts) => siType !== undefined && ts.abbr.includes(siType));
|
|
765
|
+
if (stageRecord !== undefined)
|
|
766
|
+
attributes["typed_stage"] = new IeeeTypedStage(stageRecord);
|
|
767
|
+
if (siType === "PSI" && parsed["draft_version"] !== undefined) {
|
|
768
|
+
attributes["draft"] = new IeeeDraft({ version: extractValue(parsed["draft_version"]) ?? "" }).render();
|
|
769
|
+
}
|
|
770
|
+
if (parsed["year"] !== undefined)
|
|
771
|
+
attributes["year"] = extractValue(parsed["year"]);
|
|
772
|
+
if (parsed["month"] !== undefined)
|
|
773
|
+
attributes["month"] = extractValue(parsed["month"]);
|
|
774
|
+
if (parsed["relationship_type"] !== undefined || parsed["relationship_clause"] !== undefined) {
|
|
775
|
+
attributes["relationships"] = this.buildRelationships(parsed);
|
|
776
|
+
}
|
|
777
|
+
this.handleParameters(parsed, attributes);
|
|
778
|
+
return new SiStandardClass(attributes);
|
|
779
|
+
}
|
|
780
|
+
buildMultiNumbered(parsed) {
|
|
781
|
+
const primaryId = this.buildSingleIdentifier(asHash(parsed["primary_identifier"]), false);
|
|
782
|
+
let secondaryId;
|
|
783
|
+
if (parsed["secondary_crossref"] !== undefined) {
|
|
784
|
+
const crossref = extractValue(parsed["secondary_crossref"]) ?? "";
|
|
785
|
+
secondaryId = new StandardClass({
|
|
786
|
+
publisher: "IEEE",
|
|
787
|
+
number: crossref.replace(/^\//, ""),
|
|
788
|
+
});
|
|
789
|
+
}
|
|
790
|
+
else if (parsed["secondary_joint"] !== undefined) {
|
|
791
|
+
secondaryId = this.buildSingleIdentifier(asHash(parsed["secondary_joint"]), true);
|
|
792
|
+
}
|
|
793
|
+
return new MultiNumberedClass({
|
|
794
|
+
primary_identifier: primaryId,
|
|
795
|
+
secondary_identifier: secondaryId,
|
|
796
|
+
});
|
|
797
|
+
}
|
|
798
|
+
buildCsaDualPublished(parsed) {
|
|
799
|
+
const ieeeId = this.buildSingleIdentifier(asHash(parsed["ieee_portion"]), false);
|
|
800
|
+
// The CSA portion normalizes "No." to the catalogue's "NO." spelling
|
|
801
|
+
// (the Ruby CSA component uppercases it) so every alias renders the
|
|
802
|
+
// same canonical form.
|
|
803
|
+
const csaString = (extractValue(parsed["csa_portion"]) ?? "").replace(/\bNo\./, "NO.");
|
|
804
|
+
return new CsaDualPublishedClass({
|
|
805
|
+
ieee_identifier: ieeeId,
|
|
806
|
+
csa_string: csaString,
|
|
807
|
+
year: ieeeId.year,
|
|
808
|
+
typed_stage: ieeeId.typed_stage,
|
|
809
|
+
});
|
|
810
|
+
}
|
|
811
|
+
buildSDesignation(parsed) {
|
|
812
|
+
const attributes = {
|
|
813
|
+
number: extractValue(parsed["s_number"]),
|
|
814
|
+
publisher: extractValue(parsed["publisher"]) ?? "IEEE",
|
|
815
|
+
type: "Std",
|
|
816
|
+
};
|
|
817
|
+
const stdRecord = locateStage("Std");
|
|
818
|
+
if (stdRecord !== undefined)
|
|
819
|
+
attributes["typed_stage"] = new IeeeTypedStage(stdRecord);
|
|
820
|
+
if (parsed["ipcea_copub"] !== undefined) {
|
|
821
|
+
attributes["crossref"] = extractValue(parsed["ipcea_copub"]);
|
|
822
|
+
}
|
|
823
|
+
this.handleParameters(parsed, attributes);
|
|
824
|
+
return new StandardClass(attributes);
|
|
825
|
+
}
|
|
826
|
+
buildCombinedAiee(parsed) {
|
|
827
|
+
const firstId = this.buildAiee(asHash(parsed["first_aiee"]));
|
|
828
|
+
const secondId = this.buildAiee(asHash(parsed["second_aiee"]));
|
|
829
|
+
return new DualPublishedClass({
|
|
830
|
+
first_identifier: firstId,
|
|
831
|
+
second_identifier: secondId,
|
|
832
|
+
});
|
|
833
|
+
}
|
|
834
|
+
buildIecIeeCopublished(parsed) {
|
|
835
|
+
const content = extractValue(parsed["content"]);
|
|
836
|
+
let copublishedNumber;
|
|
837
|
+
let draftInfo;
|
|
838
|
+
let iecYear;
|
|
839
|
+
let dateInfo;
|
|
840
|
+
if (content !== undefined) {
|
|
841
|
+
if (content.includes("IEC:")) {
|
|
842
|
+
copublishedNumber = content.split(" IEC:")[0]?.trim();
|
|
843
|
+
}
|
|
844
|
+
else if (content.includes(", ")) {
|
|
845
|
+
copublishedNumber = content.split(", ")[0]?.trim();
|
|
846
|
+
}
|
|
847
|
+
else if (content.includes(" (")) {
|
|
848
|
+
copublishedNumber = content.split(" (")[0]?.trim();
|
|
849
|
+
}
|
|
850
|
+
else {
|
|
851
|
+
copublishedNumber = content.trim();
|
|
852
|
+
}
|
|
853
|
+
if (copublishedNumber !== undefined && copublishedNumber.includes("/D")) {
|
|
854
|
+
const parts = copublishedNumber.split("/D");
|
|
855
|
+
copublishedNumber = parts[0];
|
|
856
|
+
draftInfo = `/D${parts[1] ?? ""}`;
|
|
857
|
+
}
|
|
858
|
+
if (content.includes("IEC:")) {
|
|
859
|
+
const iecPart = content.split("IEC:")[1];
|
|
860
|
+
if (iecPart !== undefined)
|
|
861
|
+
iecYear = iecPart.split(" ")[0];
|
|
862
|
+
}
|
|
863
|
+
if (content.includes(" (")) {
|
|
864
|
+
const datePart = content.split(" (")[1];
|
|
865
|
+
if (datePart !== undefined && datePart.includes(")")) {
|
|
866
|
+
dateInfo = datePart.split(")")[0];
|
|
867
|
+
}
|
|
868
|
+
}
|
|
869
|
+
}
|
|
870
|
+
const attrs = {};
|
|
871
|
+
if (draftInfo !== undefined)
|
|
872
|
+
attrs["draft_info"] = draftInfo;
|
|
873
|
+
if (iecYear !== undefined)
|
|
874
|
+
attrs["iec_year"] = iecYear;
|
|
875
|
+
if (dateInfo !== undefined)
|
|
876
|
+
attrs["date_info"] = dateInfo;
|
|
877
|
+
Object.assign(attrs, copublishedStructured(copublishedNumber));
|
|
878
|
+
return new IecIeeeCopublishedClass(attrs);
|
|
879
|
+
}
|
|
880
|
+
// --- AIEE / IRE / NESC builders ---------------------------------------------
|
|
881
|
+
buildAiee(parsed) {
|
|
882
|
+
const attributes = { publisher: "AIEE" };
|
|
883
|
+
const typeStr = extractValue(parsed["type"]);
|
|
884
|
+
attributes["type"] = typeStr !== undefined && typeStr.startsWith("Standard") ? "No" : typeStr;
|
|
885
|
+
const numberValue = parsed["number"];
|
|
886
|
+
let codeStr;
|
|
887
|
+
if (isObj(numberValue)) {
|
|
888
|
+
const main = extractValue(numberValue["main_number"]);
|
|
889
|
+
const paren = numberValue["parenthetical"];
|
|
890
|
+
const alt = isObj(paren) ? extractValue(paren["alt_number"]) : undefined;
|
|
891
|
+
codeStr = alt !== undefined && main !== undefined ? `${main} (${alt})` : main;
|
|
892
|
+
}
|
|
893
|
+
else {
|
|
894
|
+
codeStr = extractValue(numberValue);
|
|
895
|
+
}
|
|
896
|
+
if (codeStr !== undefined) {
|
|
897
|
+
const codeObj = IeeeCode.parse(codeStr);
|
|
898
|
+
if (codeObj !== undefined) {
|
|
899
|
+
attributes["number"] = codeObj.number;
|
|
900
|
+
if (codeObj.prefix !== undefined)
|
|
901
|
+
attributes["prefix"] = codeObj.prefix;
|
|
902
|
+
if (codeObj.parts.length > 0)
|
|
903
|
+
attributes["parts"] = codeObj.parts;
|
|
904
|
+
if (codeObj.originalSeparator !== undefined)
|
|
905
|
+
attributes["separator"] = codeObj.originalSeparator;
|
|
906
|
+
}
|
|
907
|
+
}
|
|
908
|
+
attributes["year"] = extractValue(parsed["year"]);
|
|
909
|
+
const monthStr = extractValue(parsed["month"]);
|
|
910
|
+
if (monthStr !== undefined)
|
|
911
|
+
attributes["month"] = monthStr;
|
|
912
|
+
const separatorStr = extractValue(parsed["separator"]);
|
|
913
|
+
if (separatorStr !== undefined)
|
|
914
|
+
attributes["date_separator"] = separatorStr;
|
|
915
|
+
attributes["original_format"] = separatorStr !== undefined || monthStr !== undefined ? "long" : "short";
|
|
916
|
+
return new AieeClass(attributes);
|
|
917
|
+
}
|
|
918
|
+
buildIre(parsed) {
|
|
919
|
+
const attributes = {};
|
|
920
|
+
attributes["publisher"] = extractValue(parsed["publisher"]);
|
|
921
|
+
attributes["type"] = extractValue(parsed["type"]);
|
|
922
|
+
const numberStr = extractValue(parsed["number"]);
|
|
923
|
+
if (numberStr !== undefined) {
|
|
924
|
+
const codeObj = IeeeCode.parse(numberStr);
|
|
925
|
+
if (codeObj !== undefined) {
|
|
926
|
+
attributes["number"] = codeObj.number;
|
|
927
|
+
if (codeObj.prefix !== undefined)
|
|
928
|
+
attributes["prefix"] = codeObj.prefix;
|
|
929
|
+
if (codeObj.parts.length > 0)
|
|
930
|
+
attributes["parts"] = codeObj.parts;
|
|
931
|
+
if (codeObj.originalSeparator !== undefined)
|
|
932
|
+
attributes["separator"] = codeObj.originalSeparator;
|
|
933
|
+
}
|
|
934
|
+
}
|
|
935
|
+
const yearStr = extractValue(parsed["year"]);
|
|
936
|
+
if (yearStr !== undefined) {
|
|
937
|
+
const yearInt = Number.parseInt(yearStr, 10);
|
|
938
|
+
attributes["year"] = String(yearInt >= 12 && yearInt <= 63 ? yearInt + 1900 : yearInt);
|
|
939
|
+
}
|
|
940
|
+
const fullYearStr = extractValue(parsed["full_year"]);
|
|
941
|
+
if (fullYearStr !== undefined)
|
|
942
|
+
attributes["year"] = String(Number.parseInt(fullYearStr, 10));
|
|
943
|
+
return new IreClass(attributes);
|
|
944
|
+
}
|
|
945
|
+
buildNesc(parsedHash) {
|
|
946
|
+
// Ruby falls through the variant case on a non-matching value (the
|
|
947
|
+
// nested name_first variant captures as a hash) and reaches Standard
|
|
948
|
+
// via the code check; Edition is only the no-code fallback.
|
|
949
|
+
let klass = NescEditionClass;
|
|
950
|
+
if (parsedHash["draft"] !== undefined) {
|
|
951
|
+
klass = NescDraftClass;
|
|
952
|
+
}
|
|
953
|
+
else if (typeof parsedHash["variant"] === "string") {
|
|
954
|
+
const variant = parsedHash["variant"];
|
|
955
|
+
if (variant === "Handbook")
|
|
956
|
+
klass = NescHandbookClass;
|
|
957
|
+
else if (variant === "Redline")
|
|
958
|
+
klass = NescRedlineClass;
|
|
959
|
+
}
|
|
960
|
+
if (klass === NescEditionClass && parsedHash["code"] !== undefined) {
|
|
961
|
+
klass = NescStandardClass;
|
|
962
|
+
}
|
|
963
|
+
const attrs = { code: parsedHash["code"] ?? "C2" };
|
|
964
|
+
const codeObj = IeeeCode.parse(String(attrs["code"]));
|
|
965
|
+
if (codeObj !== undefined) {
|
|
966
|
+
attrs["number"] = codeObj.number;
|
|
967
|
+
if (codeObj.prefix !== undefined)
|
|
968
|
+
attrs["prefix"] = codeObj.prefix;
|
|
969
|
+
if (codeObj.parts.length > 0)
|
|
970
|
+
attrs["parts"] = codeObj.parts;
|
|
971
|
+
}
|
|
972
|
+
if (parsedHash["year"] !== undefined)
|
|
973
|
+
attrs["year"] = String(parsedHash["year"]);
|
|
974
|
+
if (parsedHash["variant"] !== undefined)
|
|
975
|
+
attrs["variant"] = String(parsedHash["variant"]);
|
|
976
|
+
if (parsedHash["edition"] !== undefined)
|
|
977
|
+
attrs["edition"] = String(parsedHash["edition"]);
|
|
978
|
+
if (parsedHash["month"] !== undefined)
|
|
979
|
+
attrs["month"] = String(parsedHash["month"]);
|
|
980
|
+
if (parsedHash["name_registered"] !== undefined || parsedHash["abbr_registered"] !== undefined) {
|
|
981
|
+
attrs["registered"] = true;
|
|
982
|
+
}
|
|
983
|
+
if (parsedHash["paren_abbr"] !== undefined) {
|
|
984
|
+
attrs["abbr_suffix"] = true;
|
|
985
|
+
if (parsedHash["paren_registered"] !== undefined)
|
|
986
|
+
attrs["abbr_suffix_registered"] = true;
|
|
987
|
+
}
|
|
988
|
+
return new klass(attrs);
|
|
989
|
+
}
|
|
990
|
+
}
|
|
991
|
+
function copublishedStructured(copublishedNumber) {
|
|
992
|
+
if (copublishedNumber === undefined || copublishedNumber === "")
|
|
993
|
+
return {};
|
|
994
|
+
const attrs = {};
|
|
995
|
+
let remainder = copublishedNumber;
|
|
996
|
+
let year;
|
|
997
|
+
let yearSep;
|
|
998
|
+
const yearMatch = /([-:])((?:19|20)\d\d)$/.exec(copublishedNumber);
|
|
999
|
+
if (yearMatch !== null) {
|
|
1000
|
+
yearSep = yearMatch[1];
|
|
1001
|
+
year = yearMatch[2];
|
|
1002
|
+
remainder = copublishedNumber.slice(0, copublishedNumber.length - yearSep.length - year.length);
|
|
1003
|
+
}
|
|
1004
|
+
const all = remainder.match(/^[^.\-]+|[.\-][^.\-]+/g) ?? [];
|
|
1005
|
+
const parts = [];
|
|
1006
|
+
const separators = [];
|
|
1007
|
+
for (const token of all.slice(1)) {
|
|
1008
|
+
parts.push(token.slice(1));
|
|
1009
|
+
separators.push(token[0] ?? "");
|
|
1010
|
+
}
|
|
1011
|
+
attrs["number"] = all[0];
|
|
1012
|
+
if (parts.length > 0) {
|
|
1013
|
+
attrs["parts"] = parts;
|
|
1014
|
+
attrs["separators"] = separators;
|
|
1015
|
+
}
|
|
1016
|
+
if (year !== undefined) {
|
|
1017
|
+
attrs["year"] = year;
|
|
1018
|
+
if (yearSep !== "-")
|
|
1019
|
+
attrs["year_sep"] = yearSep;
|
|
1020
|
+
}
|
|
1021
|
+
return attrs;
|
|
1022
|
+
}
|
|
1023
|
+
// --- parse orchestration -------------------------------------------------------
|
|
1024
|
+
function ieeeParseSingle(input) {
|
|
1025
|
+
const cleaned = preprocessIeee(applyUpdateCodes(input));
|
|
1026
|
+
const tree = parseGrammar(ieeeGrammar, cleaned);
|
|
1027
|
+
const builder = new IeeeBuilder();
|
|
1028
|
+
builder.originalInput = input;
|
|
1029
|
+
return builder.build(tree);
|
|
1030
|
+
}
|
|
1031
|
+
// The aiee_simple fallback parses WITHOUT the legacy update-codes table -
|
|
1032
|
+
// the Ruby reference routes "AIEE …" to the AIEE sub-parser only, so an
|
|
1033
|
+
// update-codes rewrite (e.g. "AIEE Nos 72 and 73 - 1932") must not make
|
|
1034
|
+
// a line parse that the reference rejects.
|
|
1035
|
+
function ieeeParseSingleNoCodes(input) {
|
|
1036
|
+
const tree = parseGrammar(ieeeGrammar, preprocessIeee(input));
|
|
1037
|
+
const builder = new IeeeBuilder();
|
|
1038
|
+
builder.originalInput = input;
|
|
1039
|
+
return builder.build(tree);
|
|
1040
|
+
}
|
|
1041
|
+
// The aiee_simple fallback parses WITHOUT the legacy update-codes table -
|
|
1042
|
+
// the Ruby reference routes "AIEE …" to the AIEE sub-parser only, so an
|
|
1043
|
+
// update-codes rewrite (e.g. "AIEE Nos 72 and 73 - 1932") must not make
|
|
1044
|
+
// a line parse that the reference rejects.
|
|
1045
|
+
function parseAieeDirect(input) {
|
|
1046
|
+
const builder = new IeeeBuilder();
|
|
1047
|
+
builder.originalInput = input;
|
|
1048
|
+
const tree = parseGrammar({ rules: ieeeGrammar.rules, root: "aiee_identifier" }, input);
|
|
1049
|
+
return builder.buildAiee(asHash(tree));
|
|
1050
|
+
}
|
|
1051
|
+
function normalizeIecAdoption(part) {
|
|
1052
|
+
return part
|
|
1053
|
+
.replace(/\s+Edition\s+([0-9.]+)\s+([0-9-]+)/, ":$2 ED$1")
|
|
1054
|
+
.replace(/\s+Edition\s+([0-9.]+)\s*$/, " ED$1");
|
|
1055
|
+
}
|
|
1056
|
+
function buildDual(parts) {
|
|
1057
|
+
const first = ieeeParseSingle(parts[0]);
|
|
1058
|
+
const second = ieeeParseSingle(parts[1]);
|
|
1059
|
+
return new DualPublishedClass({
|
|
1060
|
+
first_identifier: first,
|
|
1061
|
+
second_identifier: second,
|
|
1062
|
+
});
|
|
1063
|
+
}
|
|
1064
|
+
function buildReaffirmed(input, reaffirmed) {
|
|
1065
|
+
const parsed = ieeeParseSingle(input);
|
|
1066
|
+
parsed["reaffirmed"] = reaffirmed;
|
|
1067
|
+
return parsed;
|
|
1068
|
+
}
|
|
1069
|
+
function buildDualWithReaffirmed(parts, reaffirmed) {
|
|
1070
|
+
const ieeeId = ieeeParseSingle(parts[0]);
|
|
1071
|
+
ieeeId["reaffirmed"] = reaffirmed;
|
|
1072
|
+
const ireId = ieeeParseSingle(parts[1]);
|
|
1073
|
+
return new DualPublishedClass({
|
|
1074
|
+
first_identifier: ieeeId,
|
|
1075
|
+
second_identifier: ireId,
|
|
1076
|
+
});
|
|
1077
|
+
}
|
|
1078
|
+
function parseAdoptedPart(part) {
|
|
1079
|
+
if (part.startsWith("IEC")) {
|
|
1080
|
+
const impl = grammarImplementation("iec");
|
|
1081
|
+
if (impl === undefined)
|
|
1082
|
+
throw new ParseFailed("IEC implementation unavailable", 0);
|
|
1083
|
+
return impl.parse(normalizeIecAdoption(part));
|
|
1084
|
+
}
|
|
1085
|
+
if (part.startsWith("ANSI")) {
|
|
1086
|
+
const impl = grammarImplementation("ansi");
|
|
1087
|
+
if (impl === undefined)
|
|
1088
|
+
throw new ParseFailed("ANSI implementation unavailable", 0);
|
|
1089
|
+
return impl.parse(part);
|
|
1090
|
+
}
|
|
1091
|
+
return ieeeParseSingle(part);
|
|
1092
|
+
}
|
|
1093
|
+
function buildAdopted(parts) {
|
|
1094
|
+
const ieeeId = ieeeParseSingle(parts[0]);
|
|
1095
|
+
const adoptedParts = parts[1].split(",").map((p) => p.trim());
|
|
1096
|
+
const adoptedIds = adoptedParts.map(parseAdoptedPart);
|
|
1097
|
+
const AdoptedClass = AdoptedStandardClass;
|
|
1098
|
+
return new AdoptedClass({
|
|
1099
|
+
ieee_identifier: ieeeId,
|
|
1100
|
+
adopted_identifiers: adoptedIds,
|
|
1101
|
+
});
|
|
1102
|
+
}
|
|
1103
|
+
// A sentinel for "the reference rejects this line outright" - distinct from
|
|
1104
|
+
// ParseFailed so ieeeParse's blanket retry (load-bearing for other forms)
|
|
1105
|
+
// does not resurrect it.
|
|
1106
|
+
class RejectedOutright extends Error {
|
|
1107
|
+
}
|
|
1108
|
+
export function ieeeParse(input) {
|
|
1109
|
+
try {
|
|
1110
|
+
return ieeeParseDispatched(input);
|
|
1111
|
+
}
|
|
1112
|
+
catch (e) {
|
|
1113
|
+
if (e instanceof ParseFailed && !(e instanceof RejectedOutright))
|
|
1114
|
+
return ieeeParseSingle(input);
|
|
1115
|
+
if (e instanceof RejectedOutright)
|
|
1116
|
+
throw new ParseFailed(e.message, 0);
|
|
1117
|
+
throw e;
|
|
1118
|
+
}
|
|
1119
|
+
}
|
|
1120
|
+
function ieeeParseDispatched(input) {
|
|
1121
|
+
const result = preParse(input);
|
|
1122
|
+
switch (result.dispatch) {
|
|
1123
|
+
case "aiee_simple":
|
|
1124
|
+
// Ruby: Aiee::Identifier.parse, with the WHOLE parse falling back to
|
|
1125
|
+
// parse_single on ParseFailed (forms the AIEE sub-grammar rejects,
|
|
1126
|
+
// e.g. "AIEE 15-May 1928", parse through the generic bucket).
|
|
1127
|
+
try {
|
|
1128
|
+
return parseAieeDirect(result.input);
|
|
1129
|
+
}
|
|
1130
|
+
catch {
|
|
1131
|
+
// Ruby: Aiee::Identifier.parse with no retry - an update-codes
|
|
1132
|
+
// rewrite must not make an AIEE-form line parse that the
|
|
1133
|
+
// reference rejects ("AIEE Nos 72 and 73 - 1932").
|
|
1134
|
+
try {
|
|
1135
|
+
return ieeeParseSingleNoCodes(input);
|
|
1136
|
+
}
|
|
1137
|
+
catch {
|
|
1138
|
+
throw new RejectedOutright(input);
|
|
1139
|
+
}
|
|
1140
|
+
}
|
|
1141
|
+
case "iec_ieee_copublished":
|
|
1142
|
+
case "dual_semicolon":
|
|
1143
|
+
case "dual_space_separated":
|
|
1144
|
+
if (result.dispatch === "dual_semicolon" || result.dispatch === "dual_space_separated") {
|
|
1145
|
+
return buildDual(result.parts);
|
|
1146
|
+
}
|
|
1147
|
+
try {
|
|
1148
|
+
return ieeeParseSingle(result.input);
|
|
1149
|
+
}
|
|
1150
|
+
catch {
|
|
1151
|
+
return ieeeParseSingle(input);
|
|
1152
|
+
}
|
|
1153
|
+
case "dual_reaffirmed":
|
|
1154
|
+
return buildReaffirmed(result.input, result.metadata["reaffirmed"] ?? "");
|
|
1155
|
+
case "dual_ire":
|
|
1156
|
+
return buildDualWithReaffirmed(result.parts, result.metadata["reaffirmed"] ?? "");
|
|
1157
|
+
case "dual_and":
|
|
1158
|
+
case "dual_ampersand":
|
|
1159
|
+
return buildDual(result.parts);
|
|
1160
|
+
case "aiee_asa_adoption": {
|
|
1161
|
+
const aieeId = ieeeParseSingle(result.parts[0]);
|
|
1162
|
+
const asaId = ieeeParseSingle(result.parts[1]);
|
|
1163
|
+
const AdoptedClass = AdoptedStandardClass;
|
|
1164
|
+
return new AdoptedClass({
|
|
1165
|
+
ieee_identifier: aieeId,
|
|
1166
|
+
adopted_identifiers: [asaId],
|
|
1167
|
+
});
|
|
1168
|
+
}
|
|
1169
|
+
case "adopted":
|
|
1170
|
+
return buildAdopted(result.parts);
|
|
1171
|
+
default:
|
|
1172
|
+
try {
|
|
1173
|
+
return ieeeParseSingle(result.input);
|
|
1174
|
+
}
|
|
1175
|
+
catch {
|
|
1176
|
+
return ieeeParseSingle(input);
|
|
1177
|
+
}
|
|
1178
|
+
}
|
|
1179
|
+
}
|
|
1180
|
+
export function ieeeGrammarImplementation() {
|
|
1181
|
+
return {
|
|
1182
|
+
parse(input) {
|
|
1183
|
+
return ieeeParse(input);
|
|
1184
|
+
},
|
|
1185
|
+
};
|
|
1186
|
+
}
|