@pubid/pubid 0.1.10 → 0.1.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/dist/flavors/ieee/index.js +92 -10
  2. package/dist/flavors/ieee/model.js +93 -33
  3. package/dist/flavors/ieee/preprocessor.js +19 -3
  4. package/package.json +2 -2
  5. package/vendor/parg/adobe.json +1 -1
  6. package/vendor/parg/aiee.json +1 -1
  7. package/vendor/parg/amca.json +1 -1
  8. package/vendor/parg/ansi.json +1 -1
  9. package/vendor/parg/api.json +1 -1
  10. package/vendor/parg/ashrae.json +1 -1
  11. package/vendor/parg/asme.json +1 -1
  12. package/vendor/parg/astm.json +1 -1
  13. package/vendor/parg/bipm.json +1 -1
  14. package/vendor/parg/bsi.json +1 -1
  15. package/vendor/parg/calconnect.json +1 -1
  16. package/vendor/parg/ccsds.json +1 -1
  17. package/vendor/parg/cen_cenelec.json +1 -1
  18. package/vendor/parg/cie.json +1 -1
  19. package/vendor/parg/csa.json +1 -1
  20. package/vendor/parg/doi.json +1 -1
  21. package/vendor/parg/easc.json +1 -1
  22. package/vendor/parg/ecma.json +1 -1
  23. package/vendor/parg/etsi.json +1 -1
  24. package/vendor/parg/evs.json +1 -1
  25. package/vendor/parg/gb.json +1 -1
  26. package/vendor/parg/gost.json +1 -1
  27. package/vendor/parg/iala.json +1 -1
  28. package/vendor/parg/iana.json +1 -1
  29. package/vendor/parg/idf.json +1 -1
  30. package/vendor/parg/iec.json +1 -1
  31. package/vendor/parg/ieee.json +1 -1
  32. package/vendor/parg/ietf.json +1 -1
  33. package/vendor/parg/ire.json +1 -1
  34. package/vendor/parg/isbn.json +1 -1
  35. package/vendor/parg/iso.json +1 -1
  36. package/vendor/parg/itu.json +1 -1
  37. package/vendor/parg/jcgm.json +1 -1
  38. package/vendor/parg/jis.json +1 -1
  39. package/vendor/parg/nesc.json +1 -1
  40. package/vendor/parg/nist.json +1 -1
  41. package/vendor/parg/oasis.json +1 -1
  42. package/vendor/parg/ogc.json +1 -1
  43. package/vendor/parg/oiml.json +1 -1
  44. package/vendor/parg/omg.json +1 -1
  45. package/vendor/parg/parg.json +1 -1
  46. package/vendor/parg/plateau.json +1 -1
  47. package/vendor/parg/sae.json +1 -1
  48. package/vendor/parg/tgpp.json +1 -1
  49. package/vendor/parg/un.json +1 -1
  50. package/vendor/parg/w3c.json +1 -1
  51. package/vendor/parg/xsf.json +1 -1
@@ -339,6 +339,10 @@ class IeeeBuilder {
339
339
  }
340
340
  if (typeValue === undefined && this.originalInput !== "" && /ANSI\s+P/.test(this.originalInput)) {
341
341
  typeValue = "P";
342
+ // The P is identity on a non-IEEE-led publisher too (the C1
343
+ // ruling): record the marker so the render prepends it —
344
+ // "ANSI PN42.34/D9a, 2015" round-trips.
345
+ attributes["project_marker"] = true;
342
346
  }
343
347
  if (codeStr !== undefined && codeStr.startsWith("P") && this.originalInput.includes("/CSA")) {
344
348
  const pubData = parsed["publishers"] !== undefined ? asHash(parsed["publishers"]) : undefined;
@@ -480,7 +484,10 @@ class IeeeBuilder {
480
484
  const dv = draftData["draft_version"];
481
485
  const version = Array.isArray(dv) ? dv.map((v) => extractValue(v) ?? "").join("") : extractValue(dv);
482
486
  if (version !== undefined) {
483
- const draftAbbr = `D${version}`;
487
+ // relaton's hyphenated "/D-2" spelling captures the dash inside
488
+ // draft_version; the stage registry keys on "D2". A date-embedded
489
+ // version ("3-2017-07") keys on its leading ordinal.
490
+ const draftAbbr = `D${version.replace(/^-/, "").replace(/-\d{4}(-\d{2})?$/, "")}`;
484
491
  const stage = locateStage(draftAbbr);
485
492
  if (stage !== undefined && stage.abbr.includes(draftAbbr))
486
493
  return draftAbbr;
@@ -532,6 +539,15 @@ class IeeeBuilder {
532
539
  revision = extractValue(draftData["revision"]);
533
540
  isoStage = extractValue(draftData["draft_iso_stage"]);
534
541
  isoIteration = extractValue(draftData["draft_iso_iteration"]);
542
+ // FDIS/CDV/… are ISO/IEC stage tokens, not draft ordinals (C1
543
+ // ruling, testsuite#2). "/DDIS" and "/DFDIS" are hallucinated
544
+ // concatenations — the designator D does not merge onto a stage
545
+ // word. The draft of a stage rides the iso_stage slot, which
546
+ // Draft#to_s renders as the D= designator face ("…/D=DIS-2020").
547
+ if (version !== undefined && /^(FDIS|FCD|CDV|DIS|CD|WD|PWI|NP)$/.test(version)) {
548
+ isoStage = version;
549
+ version = undefined;
550
+ }
535
551
  month = extractValue(draftData["month"]);
536
552
  year = extractValue(draftData["year"]);
537
553
  // The apostrophe-year catalogue convention ("P1484.20.1/D7,
@@ -567,7 +583,8 @@ class IeeeBuilder {
567
583
  month = year = day = undefined;
568
584
  }
569
585
  }
570
- if (version !== undefined || (isObj(draftData) && draftData["draft_iso_stage"] !== undefined)) {
586
+ if (version !== undefined || isoStage !== undefined ||
587
+ (isObj(draftData) && draftData["draft_iso_stage"] !== undefined)) {
571
588
  const draftObj = new IeeeDraft({
572
589
  version,
573
590
  revision,
@@ -821,6 +838,15 @@ class IeeeBuilder {
821
838
  const codeParts = [];
822
839
  if (parsed["part"] !== undefined)
823
840
  codeParts.push(extractValue(parsed["part"]) ?? "");
841
+ // The part/subpart captures carry their printed separator
842
+ // (separator-in-capture); the subpart rides after the part
843
+ // ("P65700.19.03", "60079-30-2" — the reference's joint code
844
+ // assembly).
845
+ if (parsed["subpart"] !== undefined) {
846
+ const subs = Array.isArray(parsed["subpart"]) ? parsed["subpart"] : [parsed["subpart"]];
847
+ for (const sp of subs)
848
+ codeParts.push(extractValue(sp) ?? "");
849
+ }
824
850
  let codeStr = extractValue(parsed["number"]);
825
851
  if (codeStr !== undefined && codeParts.length > 0) {
826
852
  // The ISO/IEC label's part may be dash-joined ("8802-9") - keep the
@@ -859,6 +885,39 @@ class IeeeBuilder {
859
885
  if (attributes["month"] === undefined)
860
886
  attributes["month"] = extractValue(parsed["draft_month"]);
861
887
  }
888
+ // The IEEE-led tail word-stage ("IEEE/ISO/IEC P15026-3/CD,
889
+ // December 2021") composes the D= designator with the glued
890
+ // 6-digit date — the identity its D= twin spelling parses to (the
891
+ // corpus canonical: joint-development, lead IEEE, stage P). The
892
+ // ISO-led lists converge to the published-Std identity (the issue
893
+ // #216 semantics). The zero-width printed_month_year capture
894
+ // carries "" — truthy in the reference (nil-check), falsy in JS:
895
+ // test presence, not truth.
896
+ if (parsed["tail_iso_stage"] !== undefined &&
897
+ parsed["printed_month_year"] !== undefined &&
898
+ parsed["part"] !== undefined) {
899
+ const stage = extractValue(parsed["tail_iso_stage"]);
900
+ const year = extractValue(parsed["year"]) ?? "";
901
+ const monthName = (extractValue(parsed["month"]) ?? "").replace(/\.$/, "");
902
+ const monthNum = DRAFT_MONTH_NAMES[monthName];
903
+ if (stage !== undefined && monthNum !== undefined) {
904
+ attributes["ieee_draft"] = `D=${stage}-${year}${monthNum.padStart(2, "0")}`;
905
+ parsed["year"] = undefined;
906
+ parsed["month"] = undefined;
907
+ parsed["printed_month_year"] = undefined;
908
+ delete attributes["year"];
909
+ delete attributes["month"];
910
+ // The ISO-led lists converge to the published-Std identity; the
911
+ // IEEE-led lists stay the live project draft (stage P).
912
+ if (attributes["publisher"] !== "IEEE") {
913
+ parsed["iso_published"] = { value: "" };
914
+ const stdRecord = locateStage("Std");
915
+ if (stdRecord !== undefined) {
916
+ attributes["typed_stage"] = new IeeeTypedStage(stdRecord);
917
+ }
918
+ }
919
+ }
920
+ }
862
921
  if (parsed["edition"] !== undefined)
863
922
  attributes["edition"] = extractValue(parsed["edition"]);
864
923
  if (parsed["edition_month"] !== undefined) {
@@ -971,9 +1030,10 @@ class IeeeBuilder {
971
1030
  jointDraft += `.${extractValue(parsed["draft_iso_iteration"])}`;
972
1031
  }
973
1032
  if (parsed["draft_stage_year"] !== undefined) {
974
- // The capture carries its separator (":2020") — strip it (the
975
- // #471 separator-in-capture rule).
976
- jointDraft += `:${(extractValue(parsed["draft_stage_year"]) ?? "").replace(/^[\-:]/, "")}`;
1033
+ // The capture carries its separator verbatim (":2020" /
1034
+ // "-201112" - the #471 separator-in-capture rule): the ruby
1035
+ // builder appends it raw, so the face keeps the printed form.
1036
+ jointDraft += extractValue(parsed["draft_stage_year"]) ?? "";
977
1037
  }
978
1038
  attributes["ieee_draft"] = jointDraft;
979
1039
  }
@@ -992,8 +1052,14 @@ class IeeeBuilder {
992
1052
  typeof parsed["parameters"] === "object" && !Array.isArray(parsed["parameters"]) &&
993
1053
  parsed["parameters"]["parenthetical_content"] !== undefined))) {
994
1054
  const sep = parsed["part_dash"] !== undefined ? "-" : ".";
995
- let printedCode = [extractValue(parsed["number"]), extractValue(parsed["part"])]
996
- .filter((x) => x !== undefined).join(sep);
1055
+ // The part capture carries its own separator (C1
1056
+ // separator-in-capture); join verbatim, synthesizing one only
1057
+ // for a bare capture — the reference's printed_joint rule.
1058
+ const partVal = extractValue(parsed["part"]);
1059
+ let printedCode = extractValue(parsed["number"]) ?? "";
1060
+ if (partVal !== undefined) {
1061
+ printedCode += /^[._-]/.test(partVal) ? partVal : `${sep}${partVal}`;
1062
+ }
997
1063
  // P = project: the marker is identity, preserved as spelled.
998
1064
  if (parsed["project_marker"] !== undefined)
999
1065
  printedCode = `P${printedCode}`;
@@ -1065,9 +1131,22 @@ class IeeeBuilder {
1065
1131
  else {
1066
1132
  attributes["lead_party"] = "IEEE";
1067
1133
  attributes["type"] = "P";
1068
- const record = locateStage("P");
1069
- if (record !== undefined)
1070
- attributes["typed_stage"] = new IeeeTypedStage(record);
1134
+ if ((parsed["draft_iso_stage"] !== undefined ||
1135
+ parsed["tail_iso_stage"] !== undefined) &&
1136
+ attributes["publisher"] === "ISO") {
1137
+ // The ISO-led D= designator (the issue #216 convergence) is
1138
+ // the stage-tracked draft of a published standard - the typed
1139
+ // stage reads Std/published.
1140
+ const stdRecord = locateStage("Std");
1141
+ if (stdRecord !== undefined) {
1142
+ attributes["typed_stage"] = new IeeeTypedStage(stdRecord);
1143
+ }
1144
+ }
1145
+ else {
1146
+ const record = locateStage("P");
1147
+ if (record !== undefined)
1148
+ attributes["typed_stage"] = new IeeeTypedStage(record);
1149
+ }
1071
1150
  }
1072
1151
  // A plain IEEE-designator draft on joint publishers ("/D8, June
1073
1152
  // 2010") carries no ISO stage machinery: it builds as the project
@@ -1081,6 +1160,9 @@ class IeeeBuilder {
1081
1160
  const projectAttrs = {
1082
1161
  draft: attributes["draft"],
1083
1162
  };
1163
+ // The comma-year tail rides the draft verbatim ("D4, 2019" — the
1164
+ // reference keeps the comma face on the joint project drafts; the
1165
+ // year never promotes to the identity slots).
1084
1166
  // The code columns (number/parts/separator/prefix) are the
1085
1167
  // ProjectDraft render/hash face; the spelled P is the project
1086
1168
  // marker (identity), whatever the lead publisher.
@@ -186,8 +186,11 @@ export class IeeeDraft {
186
186
  // The compound stage suffix (docs/IEEE-DRAFT-STAGES.md §1.3):
187
187
  // "=DIS.3" is canonical - D (draft) = DIS (the stage), iteration 3.
188
188
  // "=DDIS.3", "=DDIS3", "=DDIS-3" (the stage echoed with its own D)
189
- // are accepted aliases. Captures [stage, iteration].
190
- const compound = /=D?(PWI|NP|WD|CDV|FDIS|DIS|CD)(?:[.-]?(\d+))?$/;
189
+ // are accepted aliases. Captures [stage, iteration]. The iteration
190
+ // ordinal stays short (one or two digits): a glued D= date
191
+ // ("-201908", the pubid#203 convention) must ride the version body
192
+ // verbatim, not fold into the iteration slot.
193
+ const compound = /=D?(PWI|NP|WD|CDV|FDIS|DIS|CD)(?:[.-]?(\d{1,2}[a-z]?))?$/;
191
194
  let isoStage;
192
195
  let isoIteration;
193
196
  const cm = compound.exec(body);
@@ -200,7 +203,7 @@ export class IeeeDraft {
200
203
  .sort((a, b) => b.length - a.length)
201
204
  .map((m) => `${m.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}\\.?`)
202
205
  .join("|");
203
- const suffix = new RegExp(`(?:(, | )(${monthAlt})(?: (\\d{1,2}))?(?:, | )| )((?:19|20)\\d{2}[a-z]{0,2})$`);
206
+ const suffix = new RegExp(`(?:(, | )(${monthAlt})(?: (\\d{1,2}))?(?:, | )|, | )((?:19|20)\\d{2}[a-z]{0,2})$`);
204
207
  const m = suffix.exec(body);
205
208
  if (m === null) {
206
209
  return new IeeeDraft({ version: body, iso_stage: isoStage, iso_iteration: isoIteration });
@@ -216,7 +219,7 @@ export class IeeeDraft {
216
219
  });
217
220
  }
218
221
  render() {
219
- let result = `/D${this.version}`;
222
+ let result = `/D${this.version ?? ""}`;
220
223
  if (this.isoStage !== undefined)
221
224
  result += `=${this.isoStage}`;
222
225
  if (this.isoStage !== undefined && this.isoIteration !== undefined) {
@@ -225,6 +228,15 @@ export class IeeeDraft {
225
228
  if (this.revision !== undefined)
226
229
  result += `.${this.revision}`;
227
230
  if (this.year !== undefined) {
231
+ if (this.isoStage !== undefined) {
232
+ // The D= designator face dash-joins its date in IEEE's
233
+ // convention: the year, and a draft month rides the
234
+ // designator zero-padded ("D=FDIS-201008", pubid#203).
235
+ result += `-${this.year}`;
236
+ if (this.month !== undefined)
237
+ result += this.month.padStart(2, "0");
238
+ return result;
239
+ }
228
240
  const displayMonth = this.originalMonth;
229
241
  if (displayMonth !== undefined) {
230
242
  const useCommaBefore = this.commaBeforeMonthSet
@@ -236,7 +248,10 @@ export class IeeeDraft {
236
248
  result += displayMonth.length <= 4 || displayMonth === "Sept" ? ` ${this.year}` : `, ${this.year}`;
237
249
  }
238
250
  else {
239
- result += ` ${this.year}`;
251
+ // The year-only date joins with its comma - the grammar's
252
+ // comma-year draft tail (pubid-grammar 17244fc) - so the
253
+ // render re-parses through the same clause.
254
+ result += `, ${this.year}`;
240
255
  }
241
256
  }
242
257
  return result;
@@ -884,8 +899,12 @@ export const ProjectDraftIdentifierClass = ieeeClass({ kind: "project-draft-iden
884
899
  codeColumns: true,
885
900
  extraDefs: {
886
901
  project_marker: { type: "boolean", default: false },
902
+ // The ISO-led joint project drafts carry the designator as the
903
+ // stage ("ISO/IEC/IEEE P42010/D4, 2019" - stage D4), the same
904
+ // key the ruby identity serializes.
905
+ stage: { type: "string" },
887
906
  },
888
- extraMappings: keyValue({ wire: "project_marker", to: "project_marker" }),
907
+ extraMappings: keyValue({ wire: "project_marker", to: "project_marker" }, { wire: "stage", to: "stage" }),
889
908
  });
890
909
  export const SiStandardClass = ieeeClass({ kind: "si-standard" }, {
891
910
  codeColumns: true,
@@ -1104,28 +1123,35 @@ export const JointDevelopmentClass = ieeeClass({ kind: "joint-development" }, {
1104
1123
  const isoStage = id["iso_stage"];
1105
1124
  const ieeeDraft = id["ieee_draft"];
1106
1125
  const codeObj = id.codeObj;
1107
- // ISO-led renders the ISO format ALWAYS (the stage-less published
1126
+ // ISO-led renders the ISO format (the stage-less published
1108
1127
  // form "ISO/IEC/IEEE 12207.2:2020" prints colon-year, no stage).
1109
1128
  // IEEE semantics: P = project (a draft); no P = a standard. The
1110
1129
  // P-state is identity-bearing and prints as spelled - it is never
1111
1130
  // added or stripped here.
1112
- if (leadParty === "ISO") {
1113
- // A D= designator row ("P26511/D8=DDIS.3") prints the designator
1114
- // after the code, not the stage as a word; only genuine stage
1115
- // rows print the stage position.
1116
- const designatorDraft = id["ieee_draft"];
1117
- const printsDesignator = designatorDraft !== undefined && /^D\d*=/.test(designatorDraft);
1131
+ // A stage-tracked D= designator is IEEE draft notation — its
1132
+ // canonical face is the designator spelling (§1.3 spelling 7),
1133
+ // whatever the lead party (the reference's canonical_format).
1134
+ if (leadParty === "ISO" && !(ieeeDraft ?? "").startsWith("D=")) {
1135
+ // The stage word is the ISO format's own position convention —
1136
+ // it prints whenever the identifier carries one, as stored,
1137
+ // iteration included ("DIS2", "CD4" — the lossless face,
1138
+ // pubid#477). A stage-tracked D= designator decomposes into its
1139
+ // stage word and date ("D=CD-2020" → "CD", 2020); the P project
1140
+ // stage is IEEE convention and never prints here.
1141
+ let stageWord = isoStage ?? "";
1142
+ let draftYear;
1143
+ if (stageWord === "" && ieeeDraft !== undefined) {
1144
+ const decomposed = /^D=([A-Z]+)(?:\.(\d+[a-z]?))?(?:[-:](\d{4}))?$/.exec(ieeeDraft);
1145
+ if (decomposed !== null) {
1146
+ stageWord = decomposed[1] ?? "";
1147
+ draftYear = decomposed[3];
1148
+ }
1149
+ }
1118
1150
  const parts = [];
1119
1151
  if (publishers !== undefined && publishers.length > 0)
1120
1152
  parts.push(publishers.join("/"));
1121
- if (!printsDesignator) {
1122
- if (id.typed_stage !== undefined) {
1123
- parts.push(id.typed_stage.record.iso_stage_equivalent ?? id.typed_stage.render());
1124
- }
1125
- else if (isoStage !== undefined) {
1126
- parts.push(isoStage);
1127
- }
1128
- }
1153
+ if (stageWord !== "")
1154
+ parts.push(stageWord);
1129
1155
  let codeStr = codeObj?.render() ?? "";
1130
1156
  // A P-prefixed joint project prints its parts dot-joined on the
1131
1157
  // ISO face ("ISO/IEEE DIS P15500.1"), whatever separator the
@@ -1134,17 +1160,28 @@ export const JointDevelopmentClass = ieeeClass({ kind: "joint-development" }, {
1134
1160
  codeStr = codeStr.replaceAll("-", ".");
1135
1161
  if (codeStr !== "")
1136
1162
  parts.push(codeStr);
1163
+ // The ISO-face date, in the spelling that parses back to the
1164
+ // same year and month: the colon year (":2018"); a numeric
1165
+ // month glued with dashes ("-2018-05"); a text month as
1166
+ // ", February 2015".
1137
1167
  let result = parts.join(" ");
1138
- if (id.year !== undefined)
1139
- result += `:${id.year}`;
1140
- // The joint stage-draft clause ("D=WD.5") rides after the year in
1141
- // the ISO-led print; only the bare language/edition marker ("(E)")
1142
- // prints - a relationship narrative is metadata, not identity.
1143
- const jointDraft = id["ieee_draft"];
1144
- if (jointDraft !== undefined && /^D\d*=/.test(jointDraft))
1145
- result += `/${jointDraft}`;
1168
+ const dateYear = id.year ?? draftYear;
1169
+ if (dateYear !== undefined) {
1170
+ if (id.month === undefined) {
1171
+ result += `:${dateYear}`;
1172
+ }
1173
+ else if (/^\d+$/.test(id.month)) {
1174
+ result += `-${dateYear}-${id.month.padStart(2, "0")}`;
1175
+ }
1176
+ else {
1177
+ result += `, ${id.month} ${dateYear}`;
1178
+ }
1179
+ }
1180
+ // Lossless: parse(to_s) == self (gem c148d267, the 2026-10-19
1181
+ // ruling) — the parenthetical rides unconditionally on both
1182
+ // joint faces.
1146
1183
  const marker = id["parenthetical_content"];
1147
- if (marker !== undefined && /^[A-Z](?:\s*[/&]\s*[A-Z])*$/.test(marker)) {
1184
+ if (marker !== undefined) {
1148
1185
  result += ` (${marker})`;
1149
1186
  }
1150
1187
  // The joint ISO-print redline is a distinct document (pubid#215):
@@ -1160,16 +1197,39 @@ export const JointDevelopmentClass = ieeeClass({ kind: "joint-development" }, {
1160
1197
  // The P-state prints as spelled (P = project draft; no P =
1161
1198
  // standard). Never added or stripped.
1162
1199
  let codeStr = codeObj?.render() ?? "";
1163
- if (ieeeDraft !== undefined)
1200
+ let designatorCarriesYear = false;
1201
+ if (ieeeDraft !== undefined && ieeeDraft.startsWith("D=") && id.year !== undefined) {
1202
+ // The ordinal-less stage draft's canonical face (the
1203
+ // UpdateCodes rewrite): the publication year colon-joins the
1204
+ // code and the designator trails — "P16326:2017/D=WD.5".
1205
+ codeStr += `:${id.year}`;
1206
+ codeStr += `/${ieeeDraft}`;
1207
+ designatorCarriesYear = true;
1208
+ }
1209
+ else if (ieeeDraft !== undefined) {
1164
1210
  codeStr += `/${ieeeDraft}`;
1165
- else if (id.typed_stage?.ieeeDraftEquivalent !== undefined) {
1211
+ }
1212
+ else if (isoStage !== undefined) {
1213
+ // The ordinal-less stage draft: an iteration glued onto the
1214
+ // printed word ("CD2") renders in the doctrine's ".iter" slot
1215
+ // ("D=CD.2" — docs/IEEE-DRAFT-STAGES.md §1.3).
1216
+ const glued = /([A-Z]+?)(\d+)/.exec(isoStage);
1217
+ codeStr += glued !== null ? `/D=${glued[1]}.${glued[2]}` : `/D=${isoStage}`;
1218
+ }
1219
+ else if (id.typed_stage?.ieeeDraftEquivalent !== undefined &&
1220
+ !codeStr.startsWith(id.typed_stage.ieeeDraftEquivalent)) {
1166
1221
  codeStr += `/${id.typed_stage.ieeeDraftEquivalent}`;
1167
1222
  }
1168
1223
  if (codeStr !== "")
1169
1224
  parts.push(codeStr);
1170
1225
  let result = parts.join(" ");
1171
- if (id.year !== undefined)
1226
+ if (id.year !== undefined && !designatorCarriesYear &&
1227
+ !(ieeeDraft ?? "").endsWith(`-${id.year}`)) {
1172
1228
  result += `-${id.year}`;
1229
+ }
1230
+ const marker = id["parenthetical_content"];
1231
+ if (marker !== undefined)
1232
+ result += ` (${marker})`;
1173
1233
  if (id.redline === true)
1174
1234
  result += " - Redline";
1175
1235
  return result;
@@ -264,6 +264,22 @@ function normalizeRevisionNotation(input) {
264
264
  // already carries the project semantics (docs/IEEE-DRAFT-STAGES.md
265
265
  // §1.1), so the redundant word drops and the joint route parses.
266
266
  cleaned = cleaned.replace(/IEEE\/CSA Draft (P[A-Z0-9])/g, "IEEE/CSA $1");
267
+ // The same redundant word rides the wider joint lists
268
+ // ("IEEE//ISO/IEC Draft P29119-2/D=DIS-201112"); the crawl also
269
+ // doubles the publisher slash (the 2026-10-14 ruling: the list
270
+ // normalizes to single slashes). Drop the word and collapse the
271
+ // slash before the joint route sees either - scoped to the D=
272
+ // stage-draft tail (the doubled-D and stage-month tails route
273
+ // elsewhere until the grammar carries them).
274
+ cleaned = cleaned.replace(/((?:IEEE|ISO|IEC)(?:\/(?:IEEE|ISO|IEC|CSA))+)\s+Draft\s+(P[A-Z0-9][A-Z0-9.-]*\/D=[A-Z])/g, "$1 $2");
275
+ cleaned = cleaned.replace(/(IEEE|ISO|IEC)\/\//g, "$1/");
276
+ // The lettered REV spellings glue to the number ("P1310Rev3") or
277
+ // carry an after-word separator ("REV.ma", "REV-ma"); the rev rules
278
+ // read a space or a bare word, so the boundary normalizes (the
279
+ // render keeps the glued face). The before-word separator the Rev
280
+ // doctrine carries ("-REVmc") is untouched.
281
+ cleaned = cleaned.replace(/(REV|Rev|rev)[.\-](?=[A-Za-z])/g, "$1");
282
+ cleaned = cleaned.replace(/(\d)(REV|Rev|rev)/g, "$1 $2");
267
283
  // The corrigendum's own draft rides before the ordinal in the house
268
284
  // order ("PC37.101-2006/D2, 2007/Cor. 1"): the catalogue spellings
269
285
  // ".../Cor 1, D4, July 2015" and ".../Cor 1-201x/D5, April 2012"
@@ -401,8 +417,9 @@ export function preprocessIeee(input) {
401
417
  cleaned = cleaned.replace(/^(ISO\/IEC \d+[-.]\d*)\s*:\s*(\d{4})/, "$1:$2");
402
418
  cleaned = cleaned.replace(/^(ISO\/IEC \d+)\s*:\s*(\d{4})/, "$1:$2");
403
419
  cleaned = cleaned.replace(/^(IEC\/IEEE P[\w.-]+)_D/, "$1/D");
404
- cleaned = cleaned.replace(/^IEEE\/ISO\/IEC\s+(P[\w.-]+)/, "ISO/IEC/IEEE $1");
405
- cleaned = cleaned.replace(/^IEEE\/IEC\/ISO\s+(P[\w.-]+)/, "IEC/ISO/IEEE $1");
420
+ // The printed publisher order is identity (pubid#469, the
421
+ // dual-perspective ruling): no IEEE/ISO/IEC or IEEE/IEC/ISO rewrites —
422
+ // the reference parses as printed and renders the printed order back.
406
423
  cleaned = cleaned.replace(/^(IEEE\/IEC P[\w.-]+)\s+D(\d)/, "$1/D$2");
407
424
  cleaned = cleaned.replace(/^(IEEE\/IEC P[\w.-]+)\s+(CDV|FDIS|CD|DIS|ED\d)/, "$1/$2");
408
425
  cleaned = cleaned.replace(/^ISO\s+\/IEC\/IEEE/, "ISO/IEC/IEEE");
@@ -423,7 +440,6 @@ export function preprocessIeee(input) {
423
440
  cleaned = cleaned.replaceAll("Edn.", "Edition");
424
441
  cleaned = cleaned.replaceAll("ASHARE", "ASHRAE");
425
442
  cleaned = cleaned.replace(/^PC(\d)/, "P$1");
426
- cleaned = cleaned.replace(/^IEEE\/ISO\/IEC\s+(8802[\w.-]+)/, "ISO/IEC/IEEE $1");
427
443
  cleaned = cleaned.replace(/^(IEEE\s+C?\d[\d.]*\/D\d+)([A-Z][a-z]+\s+\d{4})/, "$1, $2");
428
444
  cleaned = cleaned.replace(/^(ANSI\/IEEE Std):\s+.*$/, "$1");
429
445
  cleaned = cleaned.replace(/^(IEEE\s+[\d.]+)\s+(IEC\s+\d+[-\d]*\s+.*edition\s+\d{4}-\d{2})$/i, "$1; $2");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pubid/pubid",
3
- "version": "0.1.10",
3
+ "version": "0.1.12",
4
4
  "description": "TypeScript PubID identifiers: resolution, normalization and canonical hashes for every identifier in the pubid-testsuite corpus (41 standards bodies), with a conformance runner mirroring the Ruby reference",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -17,7 +17,7 @@
17
17
  "artifact": "tsc -p tsconfig.json && node scripts/build-artifact.mjs"
18
18
  },
19
19
  "dependencies": {
20
- "parsanol": "^0.10.3",
20
+ "parsanol": "^0.10.4",
21
21
  "yaml": "^2.5.0"
22
22
  },
23
23
  "devDependencies": {
@@ -1 +1 @@
1
- {"bindings":null,"version":"0.1.0","grammar":"PubidAdobe","shape":"parsanol-tree/v2","binding_version":1,"entries":{"identifier":{"root":"identifier","grammar":{"atoms":[{"Entity":{"atom":48}},{"Entity":{"atom":30}},{"Entity":{"atom":9}},{"Str":{"pattern":"Adobe"}},{"Entity":{"atom":5}},{"Str":{"pattern":" "}},{"Str":{"pattern":"TN"}},{"Entity":{"atom":5}},{"Repetition":{"atom":7,"min":0,"max":1,"tag":"Maybe"}},{"Sequence":{"atoms":[3,4,6,8]}},{"Entity":{"atom":24}},{"Str":{"pattern":"Adobe"}},{"Entity":{"atom":5}},{"Str":{"pattern":"Technical"}},{"Entity":{"atom":5}},{"Str":{"pattern":"Note"}},{"Entity":{"atom":5}},{"Repetition":{"atom":16,"min":0,"max":1,"tag":"Maybe"}},{"Str":{"pattern":"#"}},{"Repetition":{"atom":18,"min":0,"max":1,"tag":"Maybe"}},{"Entity":{"atom":5}},{"Repetition":{"atom":20,"min":0,"max":1,"tag":"Maybe"}},{"Sequence":{"atoms":[17,19,21]}},{"Repetition":{"atom":22,"min":0,"max":1,"tag":"Maybe"}},{"Sequence":{"atoms":[11,12,13,14,15,23]}},{"Entity":{"atom":29}},{"Str":{"pattern":"ATN"}},{"Entity":{"atom":5}},{"Repetition":{"atom":27,"min":0,"max":1,"tag":"Maybe"}},{"Sequence":{"atoms":[26,28]}},{"Alternative":{"atoms":[2,10,25]}},{"Entity":{"atom":32}},{"Re":{"pattern":"[\\x30-\\x39]"}},{"Repetition":{"atom":31,"min":1,"max":null,"tag":"Repetition"}},{"Named":{"name":"number","atom":33}},{"Entity":{"atom":36}},{"Str":{"pattern":"."}},{"Entity":{"atom":42}},{"Re":{"pattern":"[\\x41-\\x5a]"}},{"Re":{"pattern":"[\\x61-\\x7a]"}},{"Re":{"pattern":"[\\x30-\\x39]"}},{"Re":{"pattern":"[_]"}},{"Alternative":{"atoms":[38,39,40,41]}},{"Repetition":{"atom":37,"min":1,"max":null,"tag":"Repetition"}},{"Named":{"name":"slug","atom":43}},{"Sequence":{"atoms":[35,44]}},{"Repetition":{"atom":45,"min":0,"max":1,"tag":"Maybe"}},{"Sequence":{"atoms":[1,34,46]}},{"Named":{"name":"tech_note","atom":47}},{"Entity":{"atom":53}},{"Entity":{"atom":32}},{"Repetition":{"atom":50,"min":1,"max":null,"tag":"Repetition"}},{"Named":{"name":"number","atom":51}},{"Named":{"name":"tech_note_bare","atom":52}},{"Entity":{"atom":87}},{"Str":{"pattern":"Adobe Publication "}},{"Repetition":{"atom":55,"min":0,"max":1,"tag":"Maybe"}},{"Entity":{"atom":86}},{"Entity":{"atom":82}},{"Entity":{"atom":75}},{"Entity":{"atom":69}},{"Entity":{"atom":62}},{"Re":{"pattern":"[\\x61-\\x7a]"}},{"Repetition":{"atom":61,"min":1,"max":null,"tag":"Repetition"}},{"Entity":{"atom":67}},{"Re":{"pattern":"[\\x61-\\x7a]"}},{"Re":{"pattern":"[\\x30-\\x39]"}},{"Alternative":{"atoms":[65,66]}},{"Repetition":{"atom":64,"min":0,"max":null,"tag":"Repetition"}},{"Sequence":{"atoms":[63,68]}},{"Entity":{"atom":71}},{"Str":{"pattern":"-"}},{"Entity":{"atom":69}},{"Sequence":{"atoms":[70,72]}},{"Repetition":{"atom":73,"min":0,"max":null,"tag":"Repetition"}},{"Sequence":{"atoms":[60,74]}},{"Named":{"name":"slug","atom":59}},{"Entity":{"atom":71}},{"Entity":{"atom":32}},{"Repetition":{"atom":78,"min":1,"max":null,"tag":"Repetition"}},{"Named":{"name":"version","atom":79}},{"Sequence":{"atoms":[76,77,80]}},{"Named":{"name":"publication_version","atom":81}},{"Entity":{"atom":85}},{"Entity":{"atom":75}},{"Named":{"name":"slug","atom":84}},{"Alternative":{"atoms":[58,83]}},{"Sequence":{"atoms":[56,57]}},{"Alternative":{"atoms":[0,49,54]}}],"root":88},"bindings":[]}},"preprocess":{},"tables":{},"lint":{"order_warnings":["rule tech_note_prefix: branches 1 and 2 are order-dependent (shared first bytes; ordered choice is decisive)","rule tech_note_prefix: branches 1 and 3 are order-dependent (shared first bytes; ordered choice is decisive)","rule tech_note_prefix: branches 2 and 3 are order-dependent (shared first bytes; ordered choice is decisive)","rule publication_slug_or_version: branches 1 and 2 are order-dependent (shared first bytes; ordered choice is decisive)","rule identifier: branches 1 and 3 are order-dependent (shared first bytes; ordered choice is decisive)"]},"default_entry":"identifier","render":{},"derive":{},"tests":[{"entry":"identifier","kind":"accept","input":"Adobe TN 15","expect":{}},{"entry":"identifier","kind":"accept","input":"ATN 30","expect":{}},{"entry":"identifier","kind":"accept","input":"Adobe Technical Note #12","expect":{}},{"entry":"identifier","kind":"reject","input":"###","expect":{}}],"docs":{},"source":"# Port of lib/pubid/adobe/parser.rb: tech notes (Adobe TN 5014, legacy\n# \"Adobe Technical Note #5014\", ATN5014, bare 5014) and publications\n# (adobe-glyph-list, adobe-japan1-7 with the version split tried first).\n\ngrammar PubidAdobe version \"0.1.0\" {\n tech_note_tn_prefix = \"Adobe\" space \"TN\" [space]\n tech_note_long_prefix = \"Adobe\" space \"Technical\" space \"Note\" [[space] [\"#\"] [space]]\n tech_note_atn_prefix = \"ATN\" [space]\n tech_note_prefix = tech_note_tn_prefix / tech_note_long_prefix / tech_note_atn_prefix\n # Capture precedence: (*rep) as name wraps the whole repetition, so a\n # digit run joins to one string instead of re-keying every character;\n # slug is captured exactly once (the bare form) or as a sibling of\n # version inside the publication_version capture.\n tech_note = (tech_note_prefix (1*digit) as number [(dot (1*slug_char) as slug)]) as tech_note\n bare_number = ((1*digit) as number) as tech_note_bare\n slug_segment = 1*lower1 *lowerd\n slug_text = slug_segment *(dash slug_segment)\n slug_inner = (slug_text) as slug\n publication_with_version = ((slug_text) as slug dash (1*digit) as version) as publication_version\n publication_slug_or_version = publication_with_version / slug_inner\n publication = [\"Adobe Publication \"] publication_slug_or_version\n identifier = tech_note / bare_number / publication\n slug_char = %x41-5A / %x61-7A / %x30-39 / %x5F\n lower1 = %x61-7A\n lowerd = %x61-7A / %x30-39\n digit = %x30-39\n space = \" \"\n dot = \".\"\n dash = \"-\"\n entry identifier: identifier\n\n test {\n accept \"Adobe TN 15\"\n accept \"ATN 30\"\n accept \"Adobe Technical Note #12\"\n reject \"###\"\n }\n}\n","checksum":"sha256:38e8488c3da1c0f4a36fe2f63d87fee551d9317c5dae62f56972da1efe842a52"}
1
+ {"bindings":null,"version":"0.1.0","grammar":"PubidAdobe","shape":"parsanol-tree/v2","binding_version":1,"entries":{"identifier":{"root":"identifier","grammar":{"atoms":[{"Entity":{"atom":48}},{"Entity":{"atom":30}},{"Entity":{"atom":9}},{"Str":{"pattern":"Adobe"}},{"Entity":{"atom":5}},{"Str":{"pattern":" "}},{"Str":{"pattern":"TN"}},{"Entity":{"atom":5}},{"Repetition":{"atom":7,"min":0,"max":1,"tag":"Maybe"}},{"Sequence":{"atoms":[3,4,6,8]}},{"Entity":{"atom":24}},{"Str":{"pattern":"Adobe"}},{"Entity":{"atom":5}},{"Str":{"pattern":"Technical"}},{"Entity":{"atom":5}},{"Str":{"pattern":"Note"}},{"Entity":{"atom":5}},{"Repetition":{"atom":16,"min":0,"max":1,"tag":"Maybe"}},{"Str":{"pattern":"#"}},{"Repetition":{"atom":18,"min":0,"max":1,"tag":"Maybe"}},{"Entity":{"atom":5}},{"Repetition":{"atom":20,"min":0,"max":1,"tag":"Maybe"}},{"Sequence":{"atoms":[17,19,21]}},{"Repetition":{"atom":22,"min":0,"max":1,"tag":"Maybe"}},{"Sequence":{"atoms":[11,12,13,14,15,23]}},{"Entity":{"atom":29}},{"Str":{"pattern":"ATN"}},{"Entity":{"atom":5}},{"Repetition":{"atom":27,"min":0,"max":1,"tag":"Maybe"}},{"Sequence":{"atoms":[26,28]}},{"Alternative":{"atoms":[2,10,25]}},{"Entity":{"atom":32}},{"Re":{"pattern":"[\\x30-\\x39]"}},{"Repetition":{"atom":31,"min":1,"max":null,"tag":"Repetition"}},{"Named":{"name":"number","atom":33}},{"Entity":{"atom":36}},{"Str":{"pattern":"."}},{"Entity":{"atom":42}},{"Re":{"pattern":"[\\x41-\\x5a]"}},{"Re":{"pattern":"[\\x61-\\x7a]"}},{"Re":{"pattern":"[\\x30-\\x39]"}},{"Re":{"pattern":"[_]"}},{"Alternative":{"atoms":[38,39,40,41]}},{"Repetition":{"atom":37,"min":1,"max":null,"tag":"Repetition"}},{"Named":{"name":"slug","atom":43}},{"Sequence":{"atoms":[35,44]}},{"Repetition":{"atom":45,"min":0,"max":1,"tag":"Maybe"}},{"Sequence":{"atoms":[1,34,46]}},{"Named":{"name":"tech_note","atom":47}},{"Entity":{"atom":53}},{"Entity":{"atom":32}},{"Repetition":{"atom":50,"min":1,"max":null,"tag":"Repetition"}},{"Named":{"name":"number","atom":51}},{"Named":{"name":"tech_note_bare","atom":52}},{"Entity":{"atom":87}},{"Str":{"pattern":"Adobe Publication "}},{"Repetition":{"atom":55,"min":0,"max":1,"tag":"Maybe"}},{"Entity":{"atom":86}},{"Entity":{"atom":82}},{"Entity":{"atom":75}},{"Entity":{"atom":69}},{"Entity":{"atom":62}},{"Re":{"pattern":"[\\x61-\\x7a]"}},{"Repetition":{"atom":61,"min":1,"max":null,"tag":"Repetition"}},{"Entity":{"atom":67}},{"Re":{"pattern":"[\\x61-\\x7a]"}},{"Re":{"pattern":"[\\x30-\\x39]"}},{"Alternative":{"atoms":[65,66]}},{"Repetition":{"atom":64,"min":0,"max":null,"tag":"Repetition"}},{"Sequence":{"atoms":[63,68]}},{"Entity":{"atom":71}},{"Str":{"pattern":"-"}},{"Entity":{"atom":69}},{"Sequence":{"atoms":[70,72]}},{"Repetition":{"atom":73,"min":0,"max":null,"tag":"Repetition"}},{"Sequence":{"atoms":[60,74]}},{"Named":{"name":"slug","atom":59}},{"Entity":{"atom":71}},{"Entity":{"atom":32}},{"Repetition":{"atom":78,"min":1,"max":null,"tag":"Repetition"}},{"Named":{"name":"version","atom":79}},{"Sequence":{"atoms":[76,77,80]}},{"Named":{"name":"publication_version","atom":81}},{"Entity":{"atom":85}},{"Entity":{"atom":75}},{"Named":{"name":"slug","atom":84}},{"Alternative":{"atoms":[58,83]}},{"Sequence":{"atoms":[56,57]}},{"Alternative":{"atoms":[0,49,54]}}],"root":88},"bindings":[]}},"preprocess":{},"tables":{},"lint":{"order_warnings":["rule tech_note_prefix: branches 1 and 2 are order-dependent (shared first bytes; ordered choice is decisive)","rule tech_note_prefix: branches 1 and 3 are order-dependent (shared first bytes; ordered choice is decisive)","rule tech_note_prefix: branches 2 and 3 are order-dependent (shared first bytes; ordered choice is decisive)","rule publication_slug_or_version: branches 1 and 2 are order-dependent (shared first bytes; ordered choice is decisive)","rule identifier: branches 1 and 3 are order-dependent (shared first bytes; ordered choice is decisive)"]},"default_entry":"identifier","render":{},"derive":{},"tests":[{"entry":"identifier","kind":"accept","input":"Adobe TN 15","expect":{}},{"entry":"identifier","kind":"accept","input":"ATN 30","expect":{}},{"entry":"identifier","kind":"accept","input":"Adobe Technical Note #12","expect":{}},{"entry":"identifier","kind":"reject","input":"###","expect":{}}],"docs":{},"source":"# Port of lib/pubid/adobe/parser.rb: tech notes (Adobe TN 5014, legacy\n# \"Adobe Technical Note #5014\", ATN5014, bare 5014) and publications\n# (adobe-glyph-list, adobe-japan1-7 with the version split tried first).\n\ngrammar PubidAdobe version \"0.1.0\" {\n tech_note_tn_prefix = \"Adobe\" space \"TN\" [space]\n tech_note_long_prefix = \"Adobe\" space \"Technical\" space \"Note\" [[space] [\"#\"] [space]]\n tech_note_atn_prefix = \"ATN\" [space]\n tech_note_prefix = tech_note_tn_prefix / tech_note_long_prefix / tech_note_atn_prefix\n # Capture precedence: (*rep) as name wraps the whole repetition, so a\n # digit run joins to one string instead of re-keying every character;\n # slug is captured exactly once (the bare form) or as a sibling of\n # version inside the publication_version capture.\n tech_note = (tech_note_prefix (1*digit) as number [(dot (1*slug_char) as slug)]) as tech_note\n bare_number = ((1*digit) as number) as tech_note_bare\n slug_segment = 1*lower1 *lowerd\n slug_text = slug_segment *(dash slug_segment)\n slug_inner = (slug_text) as slug\n publication_with_version = ((slug_text) as slug dash (1*digit) as version) as publication_version\n publication_slug_or_version = publication_with_version / slug_inner\n publication = [\"Adobe Publication \"] publication_slug_or_version\n identifier = tech_note / bare_number / publication\n slug_char = %x41-5A / %x61-7A / %x30-39 / %x5F\n lower1 = %x61-7A\n lowerd = %x61-7A / %x30-39\n digit = %x30-39\n space = \" \"\n dot = \".\"\n dash = \"-\"\n entry identifier: identifier\n\n test {\n accept \"Adobe TN 15\"\n accept \"ATN 30\"\n accept \"Adobe Technical Note #12\"\n reject \"###\"\n }\n}\n","source_hash":"bba8ad76fa85bcbf6363b8bfa1502a76a050fa4ca87bcf5a8bfd14a19cab9f5e","compiler_version":"1.3.93","checksum":"sha256:cef9c127759ddb05f7bd725d9bc923b6207c099dbd8a8e73ec4ae84101040361"}
@@ -1 +1 @@
1
- {"bindings":null,"version":"0.1.0","grammar":"PubidAiee","shape":"parsanol-tree/v2","binding_version":1,"entries":{"aiee_identifier":{"root":"aiee_identifier","grammar":{"atoms":[{"Entity":{"atom":6}},{"Str":{"pattern":"IEEE-AIEE"}},{"Str":{"pattern":"A.I.E.E."}},{"Str":{"pattern":"A. I. E. E."}},{"Str":{"pattern":"AIEE"}},{"Alternative":{"atoms":[1,2,3,4]}},{"Named":{"name":"publisher","atom":5}},{"Entity":{"atom":8}},{"Str":{"pattern":" "}},{"Entity":{"atom":22}},{"Str":{"pattern":"Standard No."}},{"Str":{"pattern":"Standard No"}},{"Str":{"pattern":"Std No."}},{"Str":{"pattern":"Std No"}},{"Str":{"pattern":"Std"}},{"Str":{"pattern":"Nos"}},{"Str":{"pattern":"No."}},{"Str":{"pattern":"No"}},{"Str":{"pattern":"no"}},{"Str":{"pattern":"Standard"}},{"Str":{"pattern":"Trans."}},{"Alternative":{"atoms":[10,11,12,13,14,15,16,17,18,19,20]}},{"Named":{"name":"type","atom":21}},{"Entity":{"atom":8}},{"Sequence":{"atoms":[9,23]}},{"Repetition":{"atom":24,"min":0,"max":1,"tag":"Maybe"}},{"Entity":{"atom":68}},{"Entity":{"atom":28}},{"Re":{"pattern":"[\\x41-\\x5a]"}},{"Repetition":{"atom":27,"min":2,"max":3,"tag":"Repetition"}},{"Entity":{"atom":31}},{"Str":{"pattern":"-"}},{"Entity":{"atom":35}},{"Entity":{"atom":34}},{"Re":{"pattern":"[\\x30-\\x39]"}},{"Repetition":{"atom":33,"min":1,"max":null,"tag":"Repetition"}},{"Sequence":{"atoms":[29,30,32]}},{"Entity":{"atom":35}},{"Entity":{"atom":28}},{"Entity":{"atom":8}},{"Str":{"pattern":"and"}},{"Sequence":{"atoms":[39,40]}},{"Lookahead":{"atom":41,"positive":false}},{"Sequence":{"atoms":[37,38,42]}},{"Entity":{"atom":35}},{"Entity":{"atom":46}},{"Str":{"pattern":"."}},{"Entity":{"atom":35}},{"Sequence":{"atoms":[44,45,47]}},{"Entity":{"atom":35}},{"Named":{"name":"main_number","atom":49}},{"Entity":{"atom":8}},{"Str":{"pattern":"("}},{"Entity":{"atom":35}},{"Named":{"name":"alt_number","atom":53}},{"Str":{"pattern":")"}},{"Sequence":{"atoms":[52,54,55]}},{"Named":{"name":"parenthetical","atom":56}},{"Sequence":{"atoms":[50,51,57]}},{"Entity":{"atom":35}},{"Entity":{"atom":8}},{"Str":{"pattern":"and"}},{"Entity":{"atom":8}},{"Entity":{"atom":35}},{"Sequence":{"atoms":[60,61,62,63]}},{"Lookahead":{"atom":64,"positive":false}},{"Sequence":{"atoms":[59,65]}},{"Alternative":{"atoms":[36,43,48,58,66]}},{"Named":{"name":"number","atom":67}},{"Entity":{"atom":155}},{"Entity":{"atom":94}},{"Entity":{"atom":8}},{"Repetition":{"atom":71,"min":0,"max":1,"tag":"Maybe"}},{"Entity":{"atom":31}},{"Entity":{"atom":92}},{"Str":{"pattern":"18"}},{"Entity":{"atom":34}},{"Repetition":{"atom":76,"min":2,"max":2,"tag":"Repetition"}},{"Sequence":{"atoms":[75,77]}},{"Str":{"pattern":"19"}},{"Str":{"pattern":"0"}},{"Str":{"pattern":"1"}},{"Str":{"pattern":"2"}},{"Str":{"pattern":"3"}},{"Str":{"pattern":"4"}},{"Str":{"pattern":"5"}},{"Alternative":{"atoms":[80,81,82,83,84,85]}},{"Entity":{"atom":34}},{"Sequence":{"atoms":[79,86,87]}},{"Str":{"pattern":"196"}},{"Re":{"pattern":"[\\x30-\\x33]"}},{"Sequence":{"atoms":[89,90]}},{"Alternative":{"atoms":[78,88,91]}},{"Named":{"name":"year","atom":74}},{"Sequence":{"atoms":[72,73,93]}},{"Entity":{"atom":153}},{"Entity":{"atom":8}},{"Repetition":{"atom":96,"min":0,"max":1,"tag":"Maybe"}},{"Str":{"pattern":","}},{"Entity":{"atom":46}},{"Alternative":{"atoms":[98,99]}},{"Named":{"name":"separator","atom":100}},{"Entity":{"atom":8}},{"Repetition":{"atom":102,"min":0,"max":1,"tag":"Maybe"}},{"Entity":{"atom":129}},{"Str":{"pattern":"September"}},{"Str":{"pattern":"November"}},{"Str":{"pattern":"December"}},{"Str":{"pattern":"February"}},{"Str":{"pattern":"August"}},{"Str":{"pattern":"June"}},{"Str":{"pattern":"January"}},{"Str":{"pattern":"March"}},{"Str":{"pattern":"April"}},{"Str":{"pattern":"October"}},{"Str":{"pattern":"July"}},{"Str":{"pattern":"May"}},{"Str":{"pattern":"Sept"}},{"Str":{"pattern":"Jan"}},{"Str":{"pattern":"Feb"}},{"Str":{"pattern":"Mar"}},{"Str":{"pattern":"Apr"}},{"Str":{"pattern":"Jun"}},{"Str":{"pattern":"Jul"}},{"Str":{"pattern":"Aug"}},{"Str":{"pattern":"Sep"}},{"Str":{"pattern":"Oct"}},{"Str":{"pattern":"Nov"}},{"Str":{"pattern":"Dec"}},{"Alternative":{"atoms":[105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128]}},{"Named":{"name":"month","atom":104}},{"Entity":{"atom":8}},{"Sequence":{"atoms":[130,131]}},{"Repetition":{"atom":132,"min":0,"max":1,"tag":"Maybe"}},{"Entity":{"atom":92}},{"Named":{"name":"year","atom":134}},{"Sequence":{"atoms":[101,103,133,135]}},{"Sequence":{"atoms":[97,136]}},{"Entity":{"atom":8}},{"Entity":{"atom":31}},{"Sequence":{"atoms":[138,139]}},{"Named":{"name":"separator","atom":140}},{"Entity":{"atom":8}},{"Repetition":{"atom":142,"min":0,"max":1,"tag":"Maybe"}},{"Entity":{"atom":92}},{"Named":{"name":"year","atom":144}},{"Sequence":{"atoms":[141,143,145]}},{"Entity":{"atom":129}},{"Named":{"name":"month","atom":147}},{"Entity":{"atom":31}},{"Entity":{"atom":92}},{"Named":{"name":"year","atom":150}},{"Sequence":{"atoms":[148,149,151]}},{"Alternative":{"atoms":[137,146,152]}},{"Alternative":{"atoms":[70,95]}},{"Repetition":{"atom":154,"min":0,"max":1,"tag":"Maybe"}},{"Sequence":{"atoms":[0,7,25,26,69]}}],"root":156},"bindings":[]}},"preprocess":{},"tables":{},"lint":{"order_warnings":["rule year: branches 1 and 2 are order-dependent (shared first bytes; ordered choice is decisive)","rule year: branches 1 and 3 are order-dependent (shared first bytes; ordered choice is decisive)","rule year: branches 2 and 3 are order-dependent (shared first bytes; ordered choice is decisive)","rule month_name: branches 1 and 13 are order-dependent (shared first bytes; ordered choice is decisive)","rule month_name: branches 1 and 21 are order-dependent (shared first bytes; ordered choice is decisive)","rule month_name: branches 2 and 23 are order-dependent (shared first bytes; ordered choice is decisive)","rule month_name: branches 3 and 24 are order-dependent (shared first bytes; ordered choice is decisive)","rule month_name: branches 4 and 15 are order-dependent (shared first bytes; ordered choice is decisive)","rule month_name: branches 5 and 9 are order-dependent (shared first bytes; ordered choice is decisive)","rule month_name: branches 5 and 17 are order-dependent (shared first bytes; ordered choice is decisive)","rule month_name: branches 5 and 20 are order-dependent (shared first bytes; ordered choice is decisive)","rule month_name: branches 6 and 7 are order-dependent (shared first bytes; ordered choice is decisive)","rule month_name: branches 6 and 11 are order-dependent (shared first bytes; ordered choice is decisive)","rule month_name: branches 6 and 14 are order-dependent (shared first bytes; ordered choice is decisive)","rule month_name: branches 6 and 18 are order-dependent (shared first bytes; ordered choice is decisive)","rule month_name: branches 6 and 19 are order-dependent (shared first bytes; ordered choice is decisive)","rule month_name: branches 7 and 11 are order-dependent (shared first bytes; ordered choice is decisive)","rule month_name: branches 7 and 14 are order-dependent (shared first bytes; ordered choice is decisive)","rule month_name: branches 7 and 18 are order-dependent (shared first bytes; ordered choice is decisive)","rule month_name: branches 7 and 19 are order-dependent (shared first bytes; ordered choice is decisive)","rule month_name: branches 8 and 12 are order-dependent (shared first bytes; ordered choice is decisive)","rule month_name: branches 8 and 16 are order-dependent (shared first bytes; ordered choice is decisive)","rule month_name: branches 9 and 17 are order-dependent (shared first bytes; ordered choice is decisive)","rule month_name: branches 9 and 20 are order-dependent (shared first bytes; ordered choice is decisive)","rule month_name: branches 10 and 22 are order-dependent (shared first bytes; ordered choice is decisive)","rule month_name: branches 11 and 14 are order-dependent (shared first bytes; ordered choice is decisive)","rule month_name: branches 11 and 18 are order-dependent (shared first bytes; ordered choice is decisive)","rule month_name: branches 11 and 19 are order-dependent (shared first bytes; ordered choice is decisive)","rule month_name: branches 12 and 16 are order-dependent (shared first bytes; ordered choice is decisive)","rule month_name: branches 13 and 21 are order-dependent (shared first bytes; ordered choice is decisive)","rule month_name: branches 14 and 18 are order-dependent (shared first bytes; ordered choice is decisive)","rule month_name: branches 14 and 19 are order-dependent (shared first bytes; ordered choice is decisive)","rule month_name: branches 17 and 20 are order-dependent (shared first bytes; ordered choice is decisive)","rule month_name: branches 18 and 19 are order-dependent (shared first bytes; ordered choice is decisive)","rule date_long: branches 1 and 2 are order-dependent (shared first bytes; ordered choice is decisive)"]},"default_entry":"aiee_identifier","render":{},"derive":{},"tests":[{"entry":"aiee_identifier","kind":"accept","input":"AIEE No. 56","expect":{}},{"entry":"aiee_identifier","kind":"accept","input":"AIEE Std 800","expect":{}},{"entry":"aiee_identifier","kind":"accept","input":"IEEE-AIEE No 18-1938","expect":{}},{"entry":"aiee_identifier","kind":"accept","input":"AIEE Standard 19","expect":{}},{"entry":"aiee_identifier","kind":"reject","input":"nonsense","expect":{}}],"docs":{},"source":"# Port of lib/pubid/ieee/aiee/parser.rb — AIEE (pre-IEEE) designations:\n# prefixes (IEEE-AIEE transitional, A.I.E.E. variants, AIEE), types\n# (Standard No./Std No./Nos/No/Trans.), numbers (letters-dash, dotted,\n# parenthetical alternates) and long/short dates. Consumed by the ieee\n# grammar via `use aiee`. Deviation: source \"Sep\"/\"Sept\" order is\n# lint-forced to longest-first.\n\ngrammar PubidAiee version \"0.1.0\" {\n digit = %x30-39\n upper = %x41-5A\n lower = %x61-7A\n digits = 1*digit\n space = \" \"\n dash = \"-\"\n dot = \".\"\n\n year = ((\"18\" 2digit)) / ((\"19\" (\"0\" / \"1\" / \"2\" / \"3\" / \"4\" / \"5\") digit)) / ((\"196\" %x30-33))\n month_name = \"September\" / \"November\" / \"December\" / \"February\" / \"August\" / \"June\" / \"January\" / \"March\" / \"April\" / \"October\" / \"July\" / \"May\" / \"Sept\" / \"Jan\" / \"Feb\" / \"Mar\" / \"Apr\" / \"Jun\" / \"Jul\" / \"Aug\" / \"Sep\" / \"Oct\" / \"Nov\" / \"Dec\"\n aiee_prefix = (\"IEEE-AIEE\" / \"A.I.E.E.\" / \"A. I. E. E.\" / \"AIEE\") as publisher\n aiee_type = (\"Standard No.\" / \"Standard No\" / \"Std No.\" / \"Std No\" / \"Std\" / \"Nos\" / \"No.\" / \"No\" / \"no\" / \"Standard\" / \"Trans.\") as type\n number = (((2*3upper dash digits)) / ((digits upper !((space \"and\")))) / ((digits dot digits)) / (((digits) as main_number space ((( \"(\" (digits) as alt_number \")\"))) as parenthetical)) / ((digits !((space \"and\" space digits))))) as number\n date_long = ([space] ((((\",\" / dot) as separator) [space] [((month_name) as month space)] (year) as year)) / (((space dash) as separator) [space] (year) as year) / (((month_name) as month dash (year) as year)))\n date_short = ([space] dash (year) as year)\n date = [(date_short / date_long)]\n\n aiee_identifier = aiee_prefix space [(aiee_type space)] number date\n\n entry aiee_identifier: aiee_identifier\n\n test {\n accept \"AIEE No. 56\"\n accept \"AIEE Std 800\"\n accept \"IEEE-AIEE No 18-1938\"\n accept \"AIEE Standard 19\"\n reject \"nonsense\"\n }\n}\n","checksum":"sha256:205a248e8cee5eba3c4ff6b7c5ee99f7af268e157b68f2c649300f7651636d19"}
1
+ {"bindings":null,"version":"0.1.0","grammar":"PubidAiee","shape":"parsanol-tree/v2","binding_version":1,"entries":{"aiee_identifier":{"root":"aiee_identifier","grammar":{"atoms":[{"Entity":{"atom":6}},{"Str":{"pattern":"IEEE-AIEE"}},{"Str":{"pattern":"A.I.E.E."}},{"Str":{"pattern":"A. I. E. E."}},{"Str":{"pattern":"AIEE"}},{"Alternative":{"atoms":[1,2,3,4]}},{"Named":{"name":"publisher","atom":5}},{"Entity":{"atom":8}},{"Str":{"pattern":" "}},{"Entity":{"atom":22}},{"Str":{"pattern":"Standard No."}},{"Str":{"pattern":"Standard No"}},{"Str":{"pattern":"Std No."}},{"Str":{"pattern":"Std No"}},{"Str":{"pattern":"Std"}},{"Str":{"pattern":"Nos"}},{"Str":{"pattern":"No."}},{"Str":{"pattern":"No"}},{"Str":{"pattern":"no"}},{"Str":{"pattern":"Standard"}},{"Str":{"pattern":"Trans."}},{"Alternative":{"atoms":[10,11,12,13,14,15,16,17,18,19,20]}},{"Named":{"name":"type","atom":21}},{"Entity":{"atom":8}},{"Sequence":{"atoms":[9,23]}},{"Repetition":{"atom":24,"min":0,"max":1,"tag":"Maybe"}},{"Entity":{"atom":68}},{"Entity":{"atom":28}},{"Re":{"pattern":"[\\x41-\\x5a]"}},{"Repetition":{"atom":27,"min":2,"max":3,"tag":"Repetition"}},{"Entity":{"atom":31}},{"Str":{"pattern":"-"}},{"Entity":{"atom":35}},{"Entity":{"atom":34}},{"Re":{"pattern":"[\\x30-\\x39]"}},{"Repetition":{"atom":33,"min":1,"max":null,"tag":"Repetition"}},{"Sequence":{"atoms":[29,30,32]}},{"Entity":{"atom":35}},{"Entity":{"atom":28}},{"Entity":{"atom":8}},{"Str":{"pattern":"and"}},{"Sequence":{"atoms":[39,40]}},{"Lookahead":{"atom":41,"positive":false}},{"Sequence":{"atoms":[37,38,42]}},{"Entity":{"atom":35}},{"Entity":{"atom":46}},{"Str":{"pattern":"."}},{"Entity":{"atom":35}},{"Sequence":{"atoms":[44,45,47]}},{"Entity":{"atom":35}},{"Named":{"name":"main_number","atom":49}},{"Entity":{"atom":8}},{"Str":{"pattern":"("}},{"Entity":{"atom":35}},{"Named":{"name":"alt_number","atom":53}},{"Str":{"pattern":")"}},{"Sequence":{"atoms":[52,54,55]}},{"Named":{"name":"parenthetical","atom":56}},{"Sequence":{"atoms":[50,51,57]}},{"Entity":{"atom":35}},{"Entity":{"atom":8}},{"Str":{"pattern":"and"}},{"Entity":{"atom":8}},{"Entity":{"atom":35}},{"Sequence":{"atoms":[60,61,62,63]}},{"Lookahead":{"atom":64,"positive":false}},{"Sequence":{"atoms":[59,65]}},{"Alternative":{"atoms":[36,43,48,58,66]}},{"Named":{"name":"number","atom":67}},{"Entity":{"atom":155}},{"Entity":{"atom":94}},{"Entity":{"atom":8}},{"Repetition":{"atom":71,"min":0,"max":1,"tag":"Maybe"}},{"Entity":{"atom":31}},{"Entity":{"atom":92}},{"Str":{"pattern":"18"}},{"Entity":{"atom":34}},{"Repetition":{"atom":76,"min":2,"max":2,"tag":"Repetition"}},{"Sequence":{"atoms":[75,77]}},{"Str":{"pattern":"19"}},{"Str":{"pattern":"0"}},{"Str":{"pattern":"1"}},{"Str":{"pattern":"2"}},{"Str":{"pattern":"3"}},{"Str":{"pattern":"4"}},{"Str":{"pattern":"5"}},{"Alternative":{"atoms":[80,81,82,83,84,85]}},{"Entity":{"atom":34}},{"Sequence":{"atoms":[79,86,87]}},{"Str":{"pattern":"196"}},{"Re":{"pattern":"[\\x30-\\x33]"}},{"Sequence":{"atoms":[89,90]}},{"Alternative":{"atoms":[78,88,91]}},{"Named":{"name":"year","atom":74}},{"Sequence":{"atoms":[72,73,93]}},{"Entity":{"atom":153}},{"Entity":{"atom":8}},{"Repetition":{"atom":96,"min":0,"max":1,"tag":"Maybe"}},{"Str":{"pattern":","}},{"Entity":{"atom":46}},{"Alternative":{"atoms":[98,99]}},{"Named":{"name":"separator","atom":100}},{"Entity":{"atom":8}},{"Repetition":{"atom":102,"min":0,"max":1,"tag":"Maybe"}},{"Entity":{"atom":129}},{"Str":{"pattern":"September"}},{"Str":{"pattern":"November"}},{"Str":{"pattern":"December"}},{"Str":{"pattern":"February"}},{"Str":{"pattern":"August"}},{"Str":{"pattern":"June"}},{"Str":{"pattern":"January"}},{"Str":{"pattern":"March"}},{"Str":{"pattern":"April"}},{"Str":{"pattern":"October"}},{"Str":{"pattern":"July"}},{"Str":{"pattern":"May"}},{"Str":{"pattern":"Sept"}},{"Str":{"pattern":"Jan"}},{"Str":{"pattern":"Feb"}},{"Str":{"pattern":"Mar"}},{"Str":{"pattern":"Apr"}},{"Str":{"pattern":"Jun"}},{"Str":{"pattern":"Jul"}},{"Str":{"pattern":"Aug"}},{"Str":{"pattern":"Sep"}},{"Str":{"pattern":"Oct"}},{"Str":{"pattern":"Nov"}},{"Str":{"pattern":"Dec"}},{"Alternative":{"atoms":[105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128]}},{"Named":{"name":"month","atom":104}},{"Entity":{"atom":8}},{"Sequence":{"atoms":[130,131]}},{"Repetition":{"atom":132,"min":0,"max":1,"tag":"Maybe"}},{"Entity":{"atom":92}},{"Named":{"name":"year","atom":134}},{"Sequence":{"atoms":[101,103,133,135]}},{"Sequence":{"atoms":[97,136]}},{"Entity":{"atom":8}},{"Entity":{"atom":31}},{"Sequence":{"atoms":[138,139]}},{"Named":{"name":"separator","atom":140}},{"Entity":{"atom":8}},{"Repetition":{"atom":142,"min":0,"max":1,"tag":"Maybe"}},{"Entity":{"atom":92}},{"Named":{"name":"year","atom":144}},{"Sequence":{"atoms":[141,143,145]}},{"Entity":{"atom":129}},{"Named":{"name":"month","atom":147}},{"Entity":{"atom":31}},{"Entity":{"atom":92}},{"Named":{"name":"year","atom":150}},{"Sequence":{"atoms":[148,149,151]}},{"Alternative":{"atoms":[137,146,152]}},{"Alternative":{"atoms":[70,95]}},{"Repetition":{"atom":154,"min":0,"max":1,"tag":"Maybe"}},{"Sequence":{"atoms":[0,7,25,26,69]}}],"root":156},"bindings":[]}},"preprocess":{},"tables":{},"lint":{"order_warnings":["rule year: branches 1 and 2 are order-dependent (shared first bytes; ordered choice is decisive)","rule year: branches 1 and 3 are order-dependent (shared first bytes; ordered choice is decisive)","rule year: branches 2 and 3 are order-dependent (shared first bytes; ordered choice is decisive)","rule month_name: branches 1 and 13 are order-dependent (shared first bytes; ordered choice is decisive)","rule month_name: branches 1 and 21 are order-dependent (shared first bytes; ordered choice is decisive)","rule month_name: branches 2 and 23 are order-dependent (shared first bytes; ordered choice is decisive)","rule month_name: branches 3 and 24 are order-dependent (shared first bytes; ordered choice is decisive)","rule month_name: branches 4 and 15 are order-dependent (shared first bytes; ordered choice is decisive)","rule month_name: branches 5 and 9 are order-dependent (shared first bytes; ordered choice is decisive)","rule month_name: branches 5 and 17 are order-dependent (shared first bytes; ordered choice is decisive)","rule month_name: branches 5 and 20 are order-dependent (shared first bytes; ordered choice is decisive)","rule month_name: branches 6 and 7 are order-dependent (shared first bytes; ordered choice is decisive)","rule month_name: branches 6 and 11 are order-dependent (shared first bytes; ordered choice is decisive)","rule month_name: branches 6 and 14 are order-dependent (shared first bytes; ordered choice is decisive)","rule month_name: branches 6 and 18 are order-dependent (shared first bytes; ordered choice is decisive)","rule month_name: branches 6 and 19 are order-dependent (shared first bytes; ordered choice is decisive)","rule month_name: branches 7 and 11 are order-dependent (shared first bytes; ordered choice is decisive)","rule month_name: branches 7 and 14 are order-dependent (shared first bytes; ordered choice is decisive)","rule month_name: branches 7 and 18 are order-dependent (shared first bytes; ordered choice is decisive)","rule month_name: branches 7 and 19 are order-dependent (shared first bytes; ordered choice is decisive)","rule month_name: branches 8 and 12 are order-dependent (shared first bytes; ordered choice is decisive)","rule month_name: branches 8 and 16 are order-dependent (shared first bytes; ordered choice is decisive)","rule month_name: branches 9 and 17 are order-dependent (shared first bytes; ordered choice is decisive)","rule month_name: branches 9 and 20 are order-dependent (shared first bytes; ordered choice is decisive)","rule month_name: branches 10 and 22 are order-dependent (shared first bytes; ordered choice is decisive)","rule month_name: branches 11 and 14 are order-dependent (shared first bytes; ordered choice is decisive)","rule month_name: branches 11 and 18 are order-dependent (shared first bytes; ordered choice is decisive)","rule month_name: branches 11 and 19 are order-dependent (shared first bytes; ordered choice is decisive)","rule month_name: branches 12 and 16 are order-dependent (shared first bytes; ordered choice is decisive)","rule month_name: branches 13 and 21 are order-dependent (shared first bytes; ordered choice is decisive)","rule month_name: branches 14 and 18 are order-dependent (shared first bytes; ordered choice is decisive)","rule month_name: branches 14 and 19 are order-dependent (shared first bytes; ordered choice is decisive)","rule month_name: branches 17 and 20 are order-dependent (shared first bytes; ordered choice is decisive)","rule month_name: branches 18 and 19 are order-dependent (shared first bytes; ordered choice is decisive)","rule date_long: branches 1 and 2 are order-dependent (shared first bytes; ordered choice is decisive)"]},"default_entry":"aiee_identifier","render":{},"derive":{},"tests":[{"entry":"aiee_identifier","kind":"accept","input":"AIEE No. 56","expect":{}},{"entry":"aiee_identifier","kind":"accept","input":"AIEE Std 800","expect":{}},{"entry":"aiee_identifier","kind":"accept","input":"IEEE-AIEE No 18-1938","expect":{}},{"entry":"aiee_identifier","kind":"accept","input":"AIEE Standard 19","expect":{}},{"entry":"aiee_identifier","kind":"reject","input":"nonsense","expect":{}}],"docs":{},"source":"# Port of lib/pubid/ieee/aiee/parser.rb — AIEE (pre-IEEE) designations:\n# prefixes (IEEE-AIEE transitional, A.I.E.E. variants, AIEE), types\n# (Standard No./Std No./Nos/No/Trans.), numbers (letters-dash, dotted,\n# parenthetical alternates) and long/short dates. Consumed by the ieee\n# grammar via `use aiee`. Deviation: source \"Sep\"/\"Sept\" order is\n# lint-forced to longest-first.\n\ngrammar PubidAiee version \"0.1.0\" {\n digit = %x30-39\n upper = %x41-5A\n lower = %x61-7A\n digits = 1*digit\n space = \" \"\n dash = \"-\"\n dot = \".\"\n\n year = ((\"18\" 2digit)) / ((\"19\" (\"0\" / \"1\" / \"2\" / \"3\" / \"4\" / \"5\") digit)) / ((\"196\" %x30-33))\n month_name = \"September\" / \"November\" / \"December\" / \"February\" / \"August\" / \"June\" / \"January\" / \"March\" / \"April\" / \"October\" / \"July\" / \"May\" / \"Sept\" / \"Jan\" / \"Feb\" / \"Mar\" / \"Apr\" / \"Jun\" / \"Jul\" / \"Aug\" / \"Sep\" / \"Oct\" / \"Nov\" / \"Dec\"\n aiee_prefix = (\"IEEE-AIEE\" / \"A.I.E.E.\" / \"A. I. E. E.\" / \"AIEE\") as publisher\n aiee_type = (\"Standard No.\" / \"Standard No\" / \"Std No.\" / \"Std No\" / \"Std\" / \"Nos\" / \"No.\" / \"No\" / \"no\" / \"Standard\" / \"Trans.\") as type\n number = (((2*3upper dash digits)) / ((digits upper !((space \"and\")))) / ((digits dot digits)) / (((digits) as main_number space ((( \"(\" (digits) as alt_number \")\"))) as parenthetical)) / ((digits !((space \"and\" space digits))))) as number\n date_long = ([space] ((((\",\" / dot) as separator) [space] [((month_name) as month space)] (year) as year)) / (((space dash) as separator) [space] (year) as year) / (((month_name) as month dash (year) as year)))\n date_short = ([space] dash (year) as year)\n date = [(date_short / date_long)]\n\n aiee_identifier = aiee_prefix space [(aiee_type space)] number date\n\n entry aiee_identifier: aiee_identifier\n\n test {\n accept \"AIEE No. 56\"\n accept \"AIEE Std 800\"\n accept \"IEEE-AIEE No 18-1938\"\n accept \"AIEE Standard 19\"\n reject \"nonsense\"\n }\n}\n","source_hash":"4d858b677a096e55be57fc24b443cf2bef9b27648d8b4433523115189affca50","compiler_version":"1.3.93","checksum":"sha256:3214fb753c1e1fead5e52d03778b4718384039995d5841d3c11b2d84489a594b"}