@pubid/pubid 0.1.3 → 0.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (185) hide show
  1. package/artifact/corpus.json.gz +0 -0
  2. package/dist/conformance/cli.js +5 -1
  3. package/dist/flavors/amca/grammar.d.ts +4 -0
  4. package/dist/flavors/amca/grammar.js +87 -0
  5. package/dist/flavors/amca/index.d.ts +4 -0
  6. package/dist/flavors/amca/index.js +76 -0
  7. package/dist/flavors/amca/model.d.ts +29 -0
  8. package/dist/flavors/amca/model.js +146 -0
  9. package/dist/flavors/ansi/index.d.ts +24 -0
  10. package/dist/flavors/ansi/index.js +147 -0
  11. package/dist/flavors/api/grammar.d.ts +4 -0
  12. package/dist/flavors/api/grammar.js +79 -0
  13. package/dist/flavors/api/index.d.ts +4 -0
  14. package/dist/flavors/api/index.js +71 -0
  15. package/dist/flavors/api/model.d.ts +27 -0
  16. package/dist/flavors/api/model.js +114 -0
  17. package/dist/flavors/ashrae/grammar.d.ts +2 -0
  18. package/dist/flavors/ashrae/grammar.js +667 -0
  19. package/dist/flavors/ashrae/index.d.ts +4 -0
  20. package/dist/flavors/ashrae/index.js +306 -0
  21. package/dist/flavors/ashrae/model.d.ts +87 -0
  22. package/dist/flavors/ashrae/model.js +335 -0
  23. package/dist/flavors/ashrae/preprocessor.d.ts +7 -0
  24. package/dist/flavors/ashrae/preprocessor.js +44 -0
  25. package/dist/flavors/asme/grammar.d.ts +2 -0
  26. package/dist/flavors/asme/grammar.js +200 -0
  27. package/dist/flavors/asme/index.d.ts +4 -0
  28. package/dist/flavors/asme/index.js +138 -0
  29. package/dist/flavors/asme/model.d.ts +34 -0
  30. package/dist/flavors/asme/model.js +123 -0
  31. package/dist/flavors/astm/grammar.d.ts +2 -0
  32. package/dist/flavors/astm/grammar.js +110 -0
  33. package/dist/flavors/astm/index.d.ts +2 -0
  34. package/dist/flavors/astm/index.js +127 -0
  35. package/dist/flavors/astm/model.d.ts +42 -0
  36. package/dist/flavors/astm/model.js +263 -0
  37. package/dist/flavors/bipm/index.d.ts +30 -0
  38. package/dist/flavors/bipm/index.js +434 -0
  39. package/dist/flavors/bsi/grammar.d.ts +4 -0
  40. package/dist/flavors/bsi/grammar.js +535 -0
  41. package/dist/flavors/bsi/index.d.ts +4 -0
  42. package/dist/flavors/bsi/index.js +941 -0
  43. package/dist/flavors/bsi/model.d.ts +127 -0
  44. package/dist/flavors/bsi/model.js +863 -0
  45. package/dist/flavors/calconnect/index.d.ts +21 -0
  46. package/dist/flavors/calconnect/index.js +113 -0
  47. package/dist/flavors/cen_cenelec/grammar.d.ts +4 -0
  48. package/dist/flavors/cen_cenelec/grammar.js +107 -0
  49. package/dist/flavors/cen_cenelec/index.d.ts +5 -0
  50. package/dist/flavors/cen_cenelec/index.js +263 -0
  51. package/dist/flavors/cen_cenelec/model.d.ts +45 -0
  52. package/dist/flavors/cen_cenelec/model.js +490 -0
  53. package/dist/flavors/cie/grammar.d.ts +5 -0
  54. package/dist/flavors/cie/grammar.js +127 -0
  55. package/dist/flavors/cie/index.d.ts +2 -0
  56. package/dist/flavors/cie/index.js +311 -0
  57. package/dist/flavors/cie/model.d.ts +122 -0
  58. package/dist/flavors/cie/model.js +464 -0
  59. package/dist/flavors/csa/grammar.d.ts +6 -0
  60. package/dist/flavors/csa/grammar.js +239 -0
  61. package/dist/flavors/csa/index.d.ts +2 -0
  62. package/dist/flavors/csa/index.js +634 -0
  63. package/dist/flavors/csa/model.d.ts +33 -0
  64. package/dist/flavors/csa/model.js +505 -0
  65. package/dist/flavors/doi/index.d.ts +13 -0
  66. package/dist/flavors/doi/index.js +65 -0
  67. package/dist/flavors/easc/index.d.ts +4 -0
  68. package/dist/flavors/easc/index.js +107 -0
  69. package/dist/flavors/ecma/index.d.ts +4 -0
  70. package/dist/flavors/ecma/index.js +117 -0
  71. package/dist/flavors/etsi/index.d.ts +14 -0
  72. package/dist/flavors/etsi/index.js +307 -0
  73. package/dist/flavors/evs/grammar.d.ts +2 -0
  74. package/dist/flavors/evs/grammar.js +22 -0
  75. package/dist/flavors/evs/index.d.ts +2 -0
  76. package/dist/flavors/evs/index.js +24 -0
  77. package/dist/flavors/evs/model.d.ts +19 -0
  78. package/dist/flavors/evs/model.js +36 -0
  79. package/dist/flavors/gb/index.d.ts +31 -0
  80. package/dist/flavors/gb/index.js +159 -0
  81. package/dist/flavors/gost/grammar.d.ts +2 -0
  82. package/dist/flavors/gost/grammar.js +46 -0
  83. package/dist/flavors/gost/index.d.ts +2 -0
  84. package/dist/flavors/gost/index.js +165 -0
  85. package/dist/flavors/gost/model.d.ts +61 -0
  86. package/dist/flavors/gost/model.js +147 -0
  87. package/dist/flavors/gost/prefix_routes.d.ts +15 -0
  88. package/dist/flavors/gost/prefix_routes.js +192 -0
  89. package/dist/flavors/iala/index.d.ts +32 -0
  90. package/dist/flavors/iala/index.js +300 -0
  91. package/dist/flavors/iana/index.d.ts +19 -0
  92. package/dist/flavors/iana/index.js +71 -0
  93. package/dist/flavors/idf/grammar.d.ts +2 -0
  94. package/dist/flavors/idf/grammar.js +71 -0
  95. package/dist/flavors/idf/index.d.ts +2 -0
  96. package/dist/flavors/idf/index.js +100 -0
  97. package/dist/flavors/idf/model.d.ts +54 -0
  98. package/dist/flavors/idf/model.js +359 -0
  99. package/dist/flavors/iec/grammar.d.ts +3 -0
  100. package/dist/flavors/iec/grammar.js +187 -0
  101. package/dist/flavors/iec/index.d.ts +4 -0
  102. package/dist/flavors/iec/index.js +507 -0
  103. package/dist/flavors/iec/model.d.ts +54 -0
  104. package/dist/flavors/iec/model.js +437 -0
  105. package/dist/flavors/ieee/grammar.d.ts +2 -0
  106. package/dist/flavors/ieee/grammar.js +697 -0
  107. package/dist/flavors/ieee/index.d.ts +3 -0
  108. package/dist/flavors/ieee/index.js +1258 -0
  109. package/dist/flavors/ieee/model.d.ts +144 -0
  110. package/dist/flavors/ieee/model.js +1237 -0
  111. package/dist/flavors/ieee/preprocessor.d.ts +8 -0
  112. package/dist/flavors/ieee/preprocessor.js +410 -0
  113. package/dist/flavors/ieee/update_codes.d.ts +8 -0
  114. package/dist/flavors/ieee/update_codes.js +197 -0
  115. package/dist/flavors/ietf/index.d.ts +30 -0
  116. package/dist/flavors/ietf/index.js +151 -0
  117. package/dist/flavors/iho/index.d.ts +4 -0
  118. package/dist/flavors/iho/index.js +126 -0
  119. package/dist/flavors/index.d.ts +9 -0
  120. package/dist/flavors/index.js +136 -0
  121. package/dist/flavors/isbn/index.d.ts +13 -0
  122. package/dist/flavors/isbn/index.js +97 -0
  123. package/dist/flavors/iso/grammar.d.ts +2 -0
  124. package/dist/flavors/iso/grammar.js +207 -0
  125. package/dist/flavors/iso/index.d.ts +2 -0
  126. package/dist/flavors/iso/index.js +343 -0
  127. package/dist/flavors/iso/model.d.ts +159 -0
  128. package/dist/flavors/iso/model.js +802 -0
  129. package/dist/flavors/iso/stages.generated.d.ts +13 -0
  130. package/dist/flavors/iso/stages.generated.js +391 -0
  131. package/dist/flavors/itu/grammar.d.ts +4 -0
  132. package/dist/flavors/itu/grammar.js +205 -0
  133. package/dist/flavors/itu/index.d.ts +2 -0
  134. package/dist/flavors/itu/index.js +224 -0
  135. package/dist/flavors/itu/model.d.ts +184 -0
  136. package/dist/flavors/itu/model.js +599 -0
  137. package/dist/flavors/jcgm/index.d.ts +7 -0
  138. package/dist/flavors/jcgm/index.js +300 -0
  139. package/dist/flavors/jis/index.d.ts +4 -0
  140. package/dist/flavors/jis/index.js +267 -0
  141. package/dist/flavors/nist/grammar.d.ts +2 -0
  142. package/dist/flavors/nist/grammar.js +287 -0
  143. package/dist/flavors/nist/index.d.ts +2 -0
  144. package/dist/flavors/nist/index.js +1244 -0
  145. package/dist/flavors/nist/model.d.ts +155 -0
  146. package/dist/flavors/nist/model.js +823 -0
  147. package/dist/flavors/nist/preprocessor.d.ts +11 -0
  148. package/dist/flavors/nist/preprocessor.js +281 -0
  149. package/dist/flavors/oasis/index.d.ts +23 -0
  150. package/dist/flavors/oasis/index.js +110 -0
  151. package/dist/flavors/ogc/index.d.ts +20 -0
  152. package/dist/flavors/ogc/index.js +75 -0
  153. package/dist/flavors/oiml/grammar.d.ts +2 -0
  154. package/dist/flavors/oiml/grammar.js +206 -0
  155. package/dist/flavors/oiml/implementation.d.ts +9 -0
  156. package/dist/flavors/oiml/implementation.js +45 -0
  157. package/dist/flavors/oiml/model.d.ts +23 -0
  158. package/dist/flavors/oiml/model.js +592 -0
  159. package/dist/flavors/omg/index.d.ts +14 -0
  160. package/dist/flavors/omg/index.js +73 -0
  161. package/dist/flavors/plateau/index.d.ts +4 -0
  162. package/dist/flavors/plateau/index.js +97 -0
  163. package/dist/flavors/tgpp/index.d.ts +4 -0
  164. package/dist/flavors/tgpp/index.js +122 -0
  165. package/dist/flavors/un/index.d.ts +13 -0
  166. package/dist/flavors/un/index.js +90 -0
  167. package/dist/flavors/w3c/index.d.ts +14 -0
  168. package/dist/flavors/w3c/index.js +148 -0
  169. package/dist/flavors/xsf/index.d.ts +18 -0
  170. package/dist/flavors/xsf/index.js +65 -0
  171. package/dist/grammar/engine.d.ts +78 -0
  172. package/dist/grammar/engine.js +351 -0
  173. package/dist/index.d.ts +1 -0
  174. package/dist/index.js +3 -0
  175. package/dist/model/attribute.d.ts +54 -0
  176. package/dist/model/attribute.js +53 -0
  177. package/dist/model/builder.d.ts +39 -0
  178. package/dist/model/builder.js +124 -0
  179. package/dist/model/component.d.ts +70 -0
  180. package/dist/model/component.js +170 -0
  181. package/dist/model/identifier.d.ts +84 -0
  182. package/dist/model/identifier.js +270 -0
  183. package/dist/model/urn-generator.d.ts +27 -0
  184. package/dist/model/urn-generator.js +91 -0
  185. package/package.json +1 -1
@@ -0,0 +1,697 @@
1
+ import { match, ref, str } from "../../grammar/engine.js";
2
+ /**
3
+ * Port of lib/pubid/ieee/parser.rb (and the aiee/ire/nesc sub-parsers),
4
+ * 1:1. The identifier alternation order is load-bearing.
5
+
6
+ * Parslet notes preserved from the Ruby: sequences fold strings away when a
7
+ * capture appears; `.as()` wraps the whole then-chain it closes; duplicate
8
+ * capture keys in one sequence raise ("Duplicate subtrees"), which the Ruby
9
+ * grammar avoids by design (distinct :trailing_year vs :year keys etc.).
10
+ */
11
+ const MONTHS = [
12
+ "Sept.", "Oct.", "Nov.", "Dec.", "Jan.", "Feb.", "Mar.", "Apr.",
13
+ "Jun.", "Jul.", "Aug.",
14
+ "January", "February", "March", "April", "May", "June", "July",
15
+ "August", "September", "October", "November", "December",
16
+ "Jan", "Feb", "Mar", "Apr", "Jun", "Jul", "Aug", "Sep", "Sept",
17
+ "Oct", "Nov", "Dec",
18
+ ];
19
+ function literalAlternation(tokens) {
20
+ const sorted = [...new Set(tokens)].sort((a, b) => b.length - a.length);
21
+ return sorted.map((t) => str(t)).reduce((a, b) => a.or(b));
22
+ }
23
+ function buildRules() {
24
+ const rules = {};
25
+ const rule = (name, build) => {
26
+ rules[name] = build();
27
+ };
28
+ // Forward-safe rule read (mirrors parslet's named-rule indirection).
29
+ const R = (name) => ref(rules, name);
30
+ const space = str(" ");
31
+ const dash = str("-");
32
+ const dot = str(".");
33
+ const slash = str("/");
34
+ const comma = str(", ");
35
+ const digit = match("[0-9]");
36
+ const digits = digit.repeat(1, Infinity);
37
+ const upper = match("[A-Z]");
38
+ const lower = match("[a-z]");
39
+ const letter = match("[A-Za-z]");
40
+ const anyChar = match("[\\s\\S]");
41
+ const spaceMaybe = () => space.maybe();
42
+ const dashMaybe = () => dash.maybe();
43
+ const monthName = () => literalAlternation(MONTHS);
44
+ const absent = (p) => p.absent();
45
+ // The ISO/IEC draft-stage vocabulary of the D= notation
46
+ // (docs/IEEE-DRAFT-STAGES.md §1.2). Ordered so the longest token wins
47
+ // ("FDIS" over "DIS").
48
+ const stageVocab = () => literalAlternation(["FDIS", "CDV", "PWI", "DIS", "WD", "NP", "CD"]);
49
+ rule("year_digits", () => str("19").or(str("20")).then(digit.repeat(2, 2)).then(lower.repeat(0, 2)).then(absent(digits)));
50
+ rule("month_numeric", () => str("0").then(match("[1-9]")).or(str("1").then(match("[0-2]"))));
51
+ rule("date_with_month_text", () => monthName().as("month").then(space).then(R("year_digits").as("year")));
52
+ rule("date_with_month_numeric", () => R("year_digits").as("year").then(dash).then(R("month_numeric").as("month")));
53
+ rule("date_standalone", () => ref(rules, "date_with_month_text")
54
+ .or(ref(rules, "date_with_month_numeric"))
55
+ .or(R("year_digits").as("year")));
56
+ rule("trailing_month_year", () => (comma.or(space)
57
+ .then(monthName().as("trailing_month"))
58
+ .then(space)
59
+ .then(R("year_digits").as("trailing_year"))).or(comma.or(space)
60
+ .then(R("month_numeric").as("trailing_month"))
61
+ .then(space.or(dash))
62
+ .then(R("year_digits").as("trailing_year"))));
63
+ rule("organization", () => literalAlternation([
64
+ "IEEE", "AIEE", "ANSI", "ASA", "ANS", "IEC", "ISO", "ASTM", "CSA",
65
+ "ASME", "NACE", "NSF", "ASHRAE", "NCTA", "AESC", "EIA",
66
+ "USEMCSC", "AMPP", "USAS", "EAB", "MPAI",
67
+ ]));
68
+ rule("complex_org_prefix", () => str("ANSI/IEEE-ANS").or(str("ANSI/IEEE")).or(str("ANSI")));
69
+ rule("characteristic_ieee_number", () => (str("C").then(digit.repeat(2, 2)).then(dot).then(digits).then(match("[a-z]").repeat(0, Infinity).maybe())).or(str("802").then(dot).then(digits).then(match("[a-z]").repeat(0, Infinity).maybe())).or(str("P").then(digits.repeat(1, Infinity))));
70
+ rule("publisher", () => R("complex_org_prefix").or(R("organization")).as("publisher"));
71
+ rule("copublisher", () => str("/ISO/IEC").as("copublisher")
72
+ .or(str("/IEC/ISO").as("copublisher"))
73
+ .or(slash.then(spaceMaybe()).then(R("organization").as("copublisher"))));
74
+ rule("conformance", () => (spaceMaybe().then(slash)
75
+ .then(str("Conformance"))
76
+ .then(match("[0-9]").repeat(1, Infinity).as("conf_number"))
77
+ .then(dash)
78
+ .then(R("year_digits").as("conf_year"))).as("conformance"));
79
+ rule("ashrae_copub", () => (slash.then(str("ASHRAE")).then(space)
80
+ .then(str("Guideline").then(space).maybe())
81
+ .then(digits.as("ashrae_number"))
82
+ .then(dash.then(R("year_digits").as("ashrae_year")).maybe())).as("ashrae_copub"));
83
+ rule("ieee_crossref", () => (slash.then(str("C")).then(digits).then(dot).then(digits).then(dot).then(digits)
84
+ .then(dash).then(R("year_digits"))).as("ieee_crossref"));
85
+ rule("ipcea_copub", () => (slash.then(str("IPCEA")).then(space)
86
+ .then(match("[A-Za-z0-9.\\-]").repeat(1, Infinity))).as("ipcea_copub"));
87
+ rule("s_designation", () => (R("publisher").then(space).maybe()).maybe()
88
+ .then((ref(rules, "type_word").as("type").then(spaceMaybe()).maybe()).maybe())
89
+ .then(str("S").then(dash).then(digits).as("s_number"))
90
+ .then(ref(rules, "ipcea_copub").maybe())
91
+ .then(ref(rules, "parenthetical").maybe()));
92
+ rule("number", () => (str("P").maybe()
93
+ .then(upper.repeat(0, Infinity)).then(digits).then(digits.or(upper).repeat(0, Infinity))
94
+ .then(dash.then(digits).then(absent(R("year_digits"))).then(dash.then(digits).repeat(0, Infinity)).maybe())
95
+ .then(lower.maybe())).as("number"));
96
+ rule("type_word", () => str("Draft Std")
97
+ .or(str("STD"))
98
+ .or(str("Standard"))
99
+ .or(str("Std No."))
100
+ .or(str("Std"))
101
+ .or(str("PTC"))
102
+ .or(match("[Nn]").then(str("o.")))
103
+ .or(match("[Nn]").then(str("o")))
104
+ .or(str("No")));
105
+ rule("part", () => (dot.or(dash)).then(match("[0-9A-Za-z]").repeat(1, Infinity).as("part")));
106
+ rule("subpart", () => (dot.or(dash).or(str("_"))).then((str("REV").or(str("Rev")).maybe()
107
+ .then(match("[0-9a-z]").repeat(1, Infinity))
108
+ .then(dot.then(digits).maybe())).as("subpart")));
109
+ rule("year", () => dot.or(dash).then(ref(rules, "date_standalone")).then(str("(E)").maybe()));
110
+ rule("draft_status", () => literalAlternation([
111
+ "Active Unapproved", "Active Approved", "Unapproved", "Approved", "Active",
112
+ ]).then(space));
113
+ rule("draft_prefix", () => spaceMaybe().then(slash.or(str("_")).or(dash).or(space)));
114
+ rule("draft_version", () => absent(str("R").then(dash))
115
+ .then(str("D").then(absent(str("IS"))).maybe())
116
+ .then((match("[0-9]").repeat(1, 2).then(dot).then(match("[0-9]").repeat(1, 2)).then(lower.maybe())).or(dot.then(digits))
117
+ .or(digits.then(str("+")).then(digits))
118
+ .or(digits.then(dot.maybe()).then(str("e")).then(digits))
119
+ .or(str("-").maybe()
120
+ .then(match("[0-9A-Za-z]").repeat(1, Infinity))
121
+ .then(str("-d").or(str("_").then(match("[0-9A-Za-z]").repeat(0, Infinity))).maybe())).as("draft_version")));
122
+ rule("draft_date", () => (comma.or(space).then(monthName().as("month")).then(space).then(R("year_digits").as("year"))).or(
123
+ // Space-separated bare year after the draft designator
124
+ // ("IEEE Draft Std P14764/D1 2004, Nov 2004" - the "D1 2004" draft
125
+ // carries its own year, with the print date still trailing).
126
+ space.then(R("year_digits").as("year"))).or(comma.or(space).then(R("month_numeric").as("month")).then(space.or(dash)).then(R("year_digits").as("year"))).or((spaceMaybe().then(comma).then(spaceMaybe()).or(space)).then(monthName().as("month")).then((space.then(digits.as("day")).then(comma.or(space).or(dash)).then(R("year_digits").as("year"))).or(space.then(digits.as("day")).maybe().then(comma).then(R("year_digits").as("year"))).or(comma.then(spaceMaybe()).then(R("year_digits").as("year")))
127
+ .or(space.then(R("year_digits").as("year"))))));
128
+ rule("fdraft", () => (slash
129
+ .then(literalAlternation(["FDIS", "CDV", "CD", "WD", "PWI", "NP"]))
130
+ .then((comma.or(space).then(monthName().as("month")).then(space).then(R("year_digits").as("year"))).or(comma.or(space).then(R("year_digits").as("year"))).maybe())
131
+ .then(ref(rules, "parenthetical").maybe())).as("fdraft"));
132
+ rule("draft", () => (ref(rules, "draft_prefix")
133
+ .then(ref(rules, "draft_version").repeat(1, 2))
134
+ .then(dot.then(digits.as("revision")).maybe())
135
+ .then(
136
+ // The compound both-systems form (docs/IEEE-DRAFT-STAGES.md
137
+ // §1.3): "=DDIS.3" - IEEE draft ordinal = draft of the ISO/IEC
138
+ // stage, with its iteration. The glued "=DDIS3" / "=DDIS-3"
139
+ // spellings are accepted aliases of "=DDIS.3".
140
+ str("=")
141
+ .then(str("D").then(stageVocab().as("draft_iso_stage"))
142
+ .or(stageVocab().as("draft_iso_stage")))
143
+ .then((dot.or(dash)).maybe().then(digits.as("draft_iso_iteration")).maybe())
144
+ .maybe())
145
+ .then(ref(rules, "draft_date").maybe())).as("draft"));
146
+ rule("revision_suffix", () => slash.then(str("R")).then(dash).then(match("[0-9A-Za-z]").repeat(1, Infinity).as("revision")));
147
+ rule("edition", () => (comma.then(R("year_digits").as("edition_year")).then(str(" Edition"))).or(space.or(dash)
148
+ .then(str("Edition "))
149
+ .then((digits.then(dot).then(digits)).as("edition"))
150
+ .then(str(" - ").or(space).or(dash))
151
+ .then(R("year_digits").as("edition_year"))
152
+ .then(dash.then(digit.repeat(2, 2).as("edition_month")).maybe())));
153
+ rule("part_subpart_year", () => (ref(rules, "part").then(ref(rules, "subpart").repeat(1, 2)).then(ref(rules, "year"))).or(ref(rules, "part").then(ref(rules, "subpart")).then(ref(rules, "year")))
154
+ .or(ref(rules, "part").then(ref(rules, "year")))
155
+ .or(ref(rules, "part").then(ref(rules, "subpart")))
156
+ .or(ref(rules, "year"))
157
+ .or(ref(rules, "part")));
158
+ rule("corrigendum", () => (str("_").or(slash).or(dash).or(space)
159
+ .then(str("Corrigendum").or(str("Cor")))
160
+ .then(dash.or(dot).or(space).maybe())
161
+ .then(spaceMaybe())
162
+ .then(digits.as("cor_number").maybe())
163
+ .then((dash.or(str(":")).or(space)).then(R("year_digits").as("cor_year")).maybe())).as("corrigendum"));
164
+ rule("amendment", () => (str("_").or(slash).or(dash).or(space)
165
+ .then(str("Amendment").or(str("Amd")))
166
+ .then(dash.or(dot).or(space).maybe())
167
+ .then(spaceMaybe())
168
+ .then(digits.as("amd_number").maybe())
169
+ .then((dash.or(str(":")).or(space)).then(R("year_digits").as("amd_year")).maybe())).as("amendment"));
170
+ rule("interpretation", () => (slash.then(str("INT")).then((dash.or(str(":")).or(space)).then(R("year_digits").as("int_year")).maybe())).as("interpretation"));
171
+ rule("reaffirmed", () => (str("Reaffirmed ").then(R("year_digits").as("year"))).or(space.maybe().then(str("(R")).then(R("year_digits").as("year")).then(str(")"))).as("reaffirmed"));
172
+ rule("redline", () => (space.then(dash.then(space).maybe())
173
+ .then(literalAlternation(["Redline", "REDLINE", "redline"]))).as("redline"));
174
+ rule("book_nickname", () => space.then(str("[")).then(match("[^\\]]").repeat(1, Infinity).as("nickname")).then(str("]")));
175
+ const relationshipType = () => literalAlternation([
176
+ "Draft Amendment to ", "DRAFT Amendment to ", "Draft Revision of ",
177
+ "Previously designated as ", "Reaffirmation of ", "Redesignation of ",
178
+ "redesignated as ", "Supersedes ", "Supercedes ", "Includes ",
179
+ "Revision of ", "Revison of ", "Amendment to ", "Corrigendum to ",
180
+ "Corrigenda to ", "incorporates ", "Incorporating ", "Incorporates ",
181
+ "Adoption of ", "Supplement to ",
182
+ ]);
183
+ rule("relationship_type", () => (literalAlternation(["Draft Amendment to ", "DRAFT Amendment to "]).as("draft_amendment_to")).or(str("Draft Revision of ").as("draft_revision_of"))
184
+ .or(str("Previously designated as ").as("previously_designated_as"))
185
+ .or(str("Reaffirmation of ").as("reaffirmation_of"))
186
+ .or(literalAlternation(["Redesignation of ", "redesignated as "]).as("redesignation_of"))
187
+ .or(literalAlternation(["Supersedes ", "Supercedes "]).as("supersedes"))
188
+ .or(str("Includes ").as("includes"))
189
+ .or(literalAlternation(["Revision of ", "Revison of "]).as("revision_of"))
190
+ .or(str("Amendment to ").as("amendment_to"))
191
+ .or(literalAlternation(["Corrigendum to ", "Corrigenda to "]).as("corrigendum_to"))
192
+ .or(literalAlternation(["incorporates ", "Incorporating ", "Incorporates "]).as("incorporates"))
193
+ .or(str("Adoption of ").as("adoption_of"))
194
+ .or(str("Supplement to ").as("supplement_to")));
195
+ rule("relationship_separator", () => space.maybe().then(slash).then(space.maybe()).or(space.maybe().then(str(";")).then(space.maybe())).or(space.maybe().then(dash).then(space.maybe())));
196
+ rule("relationship_break", () => ref(rules, "relationship_separator").then(spaceMaybe()).then(ref(rules, "relationship_type")));
197
+ rule("identifier_string", () => (absent(str(", and "))
198
+ .then(absent(str(" and ")))
199
+ .then(absent(str(", ")))
200
+ .then(absent(str(" as amended by ")))
201
+ .then(absent(ref(rules, "relationship_break")))
202
+ .then(absent(str(")")))
203
+ .then(anyChar)).repeat(1, Infinity));
204
+ rule("identifier_list", () => ref(rules, "identifier_string").as("id").then((str(", and ").or(str(" and ")).or(str(", ")).then(ref(rules, "identifier_string").as("id"))).repeat(0, Infinity)));
205
+ rule("as_amended_by_clause", () => str(" as amended by IEEE's ").then(ref(rules, "identifier_list").as("amendments"))
206
+ .or(str(" as amended by ").then(ref(rules, "identifier_list").as("amendments")))
207
+ .or(str(" and its approved amendments").as("approved_amendments")));
208
+ rule("relationship_clause", () => spaceMaybe().then(str("("))
209
+ .then(ref(rules, "relationship_type").as("relationship_type"))
210
+ .then(ref(rules, "identifier_list").as("related_ids"))
211
+ .then(ref(rules, "as_amended_by_clause").maybe())
212
+ .then((ref(rules, "relationship_separator")
213
+ .then(ref(rules, "relationship_type").as("relationship_type"))
214
+ .then(ref(rules, "identifier_list").as("related_ids"))
215
+ .then(ref(rules, "as_amended_by_clause").maybe())).repeat(0, Infinity).as("additional_rels"))
216
+ .then(str(")")));
217
+ rule("title_portion", () => str(":").then(space).then(match("[^\\n]").repeat(1, Infinity).as("title")));
218
+ rule("approved_draft_suffix", () => space.then(str("- (Approved Draft)")).or(space.then(str("(Approved Draft)"))));
219
+ rule("additional_parameters", () => (spaceMaybe().then(str("(")).then(ref(rules, "reaffirmed")
220
+ .or(str("Revision of IEEE Std ").then(spaceMaybe())
221
+ .then(match("[^)]").repeat(1, Infinity).as("revision_of")))
222
+ .or(str("Revison of IEEE Std ").then(spaceMaybe())
223
+ .then(match("[^)]").repeat(1, Infinity).as("revision_of")))
224
+ .or(str("Revision to IEEE Std ").then(spaceMaybe())
225
+ .then(match("[^)]").repeat(1, Infinity).as("revision_of")))
226
+ .or(str("Revison to IEEE Std ").then(spaceMaybe())
227
+ .then(match("[^)]").repeat(1, Infinity).as("revision_of")))
228
+ .or(literalAlternation(["DRAFT", "Draft", "draft"]).then(str(" Amendment to "))
229
+ .then(match("[^)]").repeat(1, Infinity).as("draft_amendment_to")))
230
+ .or(str("Amendment to IEEE Std ").then(spaceMaybe())
231
+ .then(match("[^)]").repeat(1, Infinity).as("amendment_to")))
232
+ .or(str("Adoption of ").then(match("[^)]").repeat(1, Infinity).as("adoption")))
233
+ .or(str("Notebooks").then(spaceMaybe())
234
+ .then(match("[^,\\)]").repeat(1, Infinity).as("notebooks")))
235
+ .or(str("Standard Newspaper(s)").then(spaceMaybe())
236
+ .then(match("[^,\\)]").repeat(1, Infinity).as("standard_newspapers")))
237
+ .or(match("[^)]").repeat(1, Infinity).as("parenthetical_content")))
238
+ .then(str(")").maybe())).as("parameters"));
239
+ rule("parenthetical", () => ref(rules, "relationship_clause").or(ref(rules, "additional_parameters")));
240
+ rule("iec_ieee_copublished", () => str("IEC/IEEE")
241
+ .then(space)
242
+ .then(absent(str("P")))
243
+ .then(match("[^0-9\\n]").repeat(0, Infinity).then(digit).present())
244
+ .then(match("[^\\n]").repeat(1, Infinity).as("content")));
245
+ rule("joint_development_ieee_format", () => literalAlternation(["ISO/IEC/IEEE", "ISO/IEEE", "IEC/IEEE", "IEEE/CSA"]).as("joint_publishers")
246
+ .then(space)
247
+ // P = project (the document is a draft): identity-bearing, so it
248
+ // is captured and preserved, never silently consumed.
249
+ .then(str("P").as("project_marker"))
250
+ .then(digits.as("number"))
251
+ .then((dot.or(dash)).then(digits.as("part")).maybe())
252
+ .then(slash.then(digits).then(dot.then(digits).maybe())
253
+ .then(dash.then(digits.as("draft_version")).maybe()).maybe())
254
+ .then(
255
+ // Variant 1b: the ordinal-less stage draft "D=CDV[:2020]" -
256
+ // D (draft) = CDV (the IEC stage it drafts). The year rides in
257
+ // the draft clause (a distinct key, so the builder keeps the
258
+ // date inside the designator).
259
+ slash.then(str("D")).then(str("="))
260
+ .then(stageVocab().as("draft_iso_stage"))
261
+ .then(str(":").then(R("year_digits").as("draft_stage_year")).maybe())
262
+ .or(
263
+ // Variant 1: /D8 notation (original), with the compound
264
+ // both-systems suffix "=DDIS.3" (docs/IEEE-DRAFT-STAGES.md
265
+ // §1.3). The doubled-D spelling is consumed and echoed: the
266
+ // joint form prints the stage as spelled.
267
+ slash.then(str("D")).then(digits.as("draft_version"))
268
+ .then(str("=")
269
+ .then(str("D").as("draft_stage_d").then(stageVocab().as("draft_iso_stage"))
270
+ .or(stageVocab().as("draft_iso_stage")))
271
+ .then((dot.or(dash)).maybe().then(digits.as("draft_iso_iteration")).maybe())
272
+ .maybe()))
273
+ .or(
274
+ // Variant 2: , CDV1 notation (comma before stage code) —
275
+ // the stage draft of the named ISO/IEC stage, its iteration
276
+ comma.then(literalAlternation(["CDV", "FDIS", "CD", "DIS"]).as("iec_stage"))
277
+ .then(digits.maybe().as("stage_iteration")))
278
+ .maybe())
279
+ .then(ref(rules, "edition").maybe())
280
+ .then((dash.then(R("year_digits").as("year"))).or(comma.maybe().then(space).then(monthName().as("month")).then(spaceMaybe())
281
+ .then(R("year_digits").as("year"))).maybe())
282
+ .then(ref(rules, "revision_suffix").maybe()));
283
+ rule("joint_development_iso_format", () => {
284
+ const isoLed = literalAlternation([
285
+ "ISO/IEC/IEEE", "IEEE/ISO/IEC", "IEEE/IEC/ISO", "ISO/IEEE",
286
+ ]);
287
+ const stagedOnly = literalAlternation([
288
+ "IEC/IEEE", "IEEE/IEC", "ISO/IEC", "IEEE",
289
+ ]);
290
+ const isoStage = () => str("FDIS")
291
+ .or(str("FCD"))
292
+ .or(str("CDV"))
293
+ .or(str("DIS").then(digit.maybe()))
294
+ .or(str("CD").then(digit.maybe()))
295
+ .or(str("WD"))
296
+ .or(str("PWI"))
297
+ .or(str("NP"))
298
+ .as("iso_stage");
299
+ const stdNoise = () => (space.then(str("Std"))).maybe();
300
+ // The dash-year and ", Month YYYY" spellings are the catalogue-PRINTED
301
+ // joint form; tag them so the builder routes to a Standard. A
302
+ // dash-joined part is tagged too (printed parts spell the dash).
303
+ const dateClause = () => (str(":").then(R("year_digits").as("year"))).or(dash.then(R("year_digits").as("year"))
304
+ .then(dash.then(R("month_numeric").as("month")).maybe())
305
+ .then(str("").as("printed_dash_year"))).or((comma.or(space)).then(monthName().as("month")).then(space)
306
+ .then(R("year_digits").as("year"))
307
+ .then(str("").as("printed_month_year"))).maybe();
308
+ return (isoLed.as("joint_publishers").then(space)
309
+ .then(isoStage().then(stdNoise()).then(space)
310
+ .or(str("").as("iso_published").then(spaceMaybe())))
311
+ .or(stagedOnly.as("joint_publishers").then(space).then(isoStage()).then(stdNoise()).then(space)))
312
+ .then(str("P").as("project_marker").maybe())
313
+ .then(digits.as("number"))
314
+ .then((dot.then(absent(R("year_digits"))).then(digits.as("part")))
315
+ .or(dash.then(str("").as("part_dash")).then(absent(R("year_digits")))
316
+ .then(digits.as("part")))
317
+ .maybe())
318
+ .then(dateClause())
319
+ .then(
320
+ // The ISO/IEC edition marker may sit between the year and an
321
+ // amendment/draft tail ("8802.11:2012 (E)/Amd 1-2014").
322
+ (spaceMaybe().then(str("("))
323
+ .then(match("[^)]").repeat(1, Infinity).as("edition_marker"))
324
+ .then(str(")"))).maybe())
325
+ .then(
326
+ // The stage-draft clause of the ISO-led print: "/D=WD.5" - D
327
+ // (draft) = the ISO/IEC stage it drafts, with its iteration
328
+ // (docs/IEEE-DRAFT-STAGES.md §1.2).
329
+ (slash.then(str("D")).then(str("="))
330
+ .then(stageVocab().as("draft_iso_stage"))
331
+ .then(dot.then(digits.then(match("[A-Za-z]").repeat(0, 1)).as("draft_iso_iteration")).maybe()))
332
+ .or(slash.then(str("D")).then(dashMaybe())
333
+ .then(match("[0-9.]").repeat(1, Infinity).as("draft_version"))
334
+ .then(((comma.or(space)).then(monthName().as("draft_month")).then(space)
335
+ .then(R("year_digits").as("draft_year"))).or(comma.then(R("year_digits").as("draft_year"))).maybe())).maybe())
336
+ .then((slash.then(str("Amd")).then(dot.or(space).maybe())
337
+ .then(digits.as("amd_number"))
338
+ .then((str(":").or(dash)).then(R("year_digits").as("amd_year")).maybe())).maybe())
339
+ .then(ref(rules, "edition").maybe())
340
+ .then(ref(rules, "revision_suffix").maybe())
341
+ .then(ref(rules, "parenthetical").maybe());
342
+ });
343
+ // The stage-less ISO/IEC label with a colon year and the ISO/IEC
344
+ // edition marker: "ISO/IEC 13210:1994 (E)" - the ISO/IEC portion of a
345
+ // double-labeled standard. The (E) parenthetical is REQUIRED: without it
346
+ // this spelling is the ISO flavor's own form and must not be stolen.
347
+ rule("joint_development_iso_iec_edition", () => str("ISO/IEC").as("joint_publishers")
348
+ .then(space)
349
+ .then(str("").as("iso_published"))
350
+ .then(str("P").as("project_marker").maybe())
351
+ .then(digits.as("number"))
352
+ // The part may be dot- or dash-joined ("8802-9"); a dash-year is
353
+ // not a part. A distinct key: the iso-format route's part_dash
354
+ // prints as a dot in the joint code; only the label keeps its dash.
355
+ .then((dot.then(digits.as("part")))
356
+ .or(dash.then(str("").as("iec_label_dash")).then(absent(R("year_digits"))).then(digits.as("part")))
357
+ .maybe())
358
+ .then(str(":").then(spaceMaybe()).then(R("year_digits").as("year")))
359
+ .then(spaceMaybe())
360
+ .then(ref(rules, "parenthetical")));
361
+ rule("joint_development_embedded_stage", () => literalAlternation([
362
+ "ISO/IEC/IEEE", "IEEE/ISO/IEC", "IEEE/IEC/ISO", "ISO/IEEE",
363
+ "IEC/IEEE", "IEEE/IEC", "ISO/IEC", "IEEE",
364
+ ]).as("joint_publishers")
365
+ .then(space)
366
+ .then(str("P").as("project_marker").maybe())
367
+ .then(digits.as("number"))
368
+ .then((dot.or(dash)).then(absent(R("year_digits"))).then(digits.as("part")).maybe())
369
+ .then(dot)
370
+ .then(str("FDIS")
371
+ .or(str("FCD"))
372
+ .or(str("CDV"))
373
+ .or(str("DIS").then(digit.maybe()))
374
+ .or(str("CD").then(digit.maybe()))
375
+ .or(str("WD"))
376
+ .or(str("PWI"))
377
+ .or(str("NP"))
378
+ .as("iso_stage"))
379
+ .then(absent(digit.or(letter)))
380
+ .then((str(":").then(R("year_digits").as("year"))).or(dash.then(R("year_digits").as("year"))
381
+ .then(dash.then(R("month_numeric").as("month")).maybe())).or((comma.or(space)).then(monthName().as("month")).then(space)
382
+ .then(R("year_digits").as("year"))).maybe()));
383
+ rule("number_first_identifier", () => ref(rules, "number")
384
+ .then(dash.then(R("year_digits").as("year")).maybe())
385
+ .then(space)
386
+ .then((R("publisher").then(R("copublisher").repeat(0, Infinity).as("copublishers"))).as("publishers"))
387
+ .then(space)
388
+ .then(ref(rules, "type_word").as("type").then(spaceMaybe()).maybe())
389
+ .then(match("[^\\n]").repeat(0, Infinity).as("title")));
390
+ rule("ieee_p_identifier", () => (str("IEEE").as("publisher").then(space).maybe())
391
+ .then(ref(rules, "number"))
392
+ .then(ref(rules, "part_subpart_year").or(ref(rules, "edition")).maybe())
393
+ .then((slash.then(digits.as("draft_version"))).as("digit_draft").maybe())
394
+ .then(ref(rules, "fdraft").maybe())
395
+ .then(ref(rules, "trailing_month_year").maybe())
396
+ .then(ref(rules, "corrigendum").maybe())
397
+ .then(ref(rules, "draft").maybe())
398
+ .then(ref(rules, "revision_suffix").maybe())
399
+ .then(ref(rules, "trailing_month_year").maybe())
400
+ .then(ref(rules, "corrigendum").maybe())
401
+ .then(ref(rules, "parenthetical").maybe()));
402
+ rule("ansi_p_identifier", () => str("ANSI").as("publisher")
403
+ .then(space)
404
+ .then(str("P"))
405
+ .then(spaceMaybe())
406
+ .then(ref(rules, "number"))
407
+ .then(ref(rules, "part_subpart_year").or(ref(rules, "edition")).maybe())
408
+ .then(ref(rules, "trailing_month_year").maybe())
409
+ .then(ref(rules, "corrigendum").maybe())
410
+ .then(ref(rules, "draft").maybe())
411
+ .then(ref(rules, "revision_suffix").maybe())
412
+ .then(ref(rules, "trailing_month_year").maybe())
413
+ .then((comma.or(space)).then(R("year_digits").as("trailing_year")).maybe())
414
+ .then(ref(rules, "corrigendum").maybe())
415
+ .then(ref(rules, "parenthetical").maybe()));
416
+ rule("ieee_draft_p_identifier", () => (str("IEEE").as("publisher").then(space).maybe())
417
+ .then(ref(rules, "draft_status").as("draft_status").maybe())
418
+ .then(str("Draft"))
419
+ .then(space)
420
+ .then(ref(rules, "number"))
421
+ .then(ref(rules, "part_subpart_year").or(ref(rules, "edition")).maybe())
422
+ .then((space.then(monthName().as("trailing_month")).then(space)
423
+ .then(R("year_digits").as("trailing_year"))).or(space.then(R("month_numeric").as("trailing_month")).then(space.or(dash))
424
+ .then(R("year_digits").as("trailing_year"))).maybe())
425
+ .then(ref(rules, "draft").maybe())
426
+ .then(ref(rules, "revision_suffix").maybe())
427
+ .then(ref(rules, "corrigendum").maybe())
428
+ .then(ref(rules, "parenthetical").maybe()));
429
+ rule("ieee_approved_draft_identifier", () => str("IEEE").as("publisher")
430
+ .then(space)
431
+ .then(str("Approved"))
432
+ .then(space)
433
+ .then(str("Draft Std").or(str("Std")).as("type"))
434
+ .then(space)
435
+ .then(str("P").maybe())
436
+ .then(ref(rules, "number"))
437
+ .then(ref(rules, "part_subpart_year").or(ref(rules, "edition")).maybe())
438
+ .then(ref(rules, "draft").maybe())
439
+ .then(ref(rules, "revision_suffix").maybe())
440
+ .then(ref(rules, "parenthetical").maybe()));
441
+ // --- AIEE sub-parser ----------------------------------------------------
442
+ rule("aiee_year", () => str("18").then(digit.repeat(2, 2))
443
+ .or(str("19").then(literalAlternation(["0", "1", "2", "3", "4", "5"]).then(digit)))
444
+ .or(str("196").then(match("[0-3]"))));
445
+ rule("aiee_prefix", () => literalAlternation(["IEEE-AIEE", "A.I.E.E.", "A. I. E. E.", "AIEE"]).as("publisher"));
446
+ rule("aiee_type", () => literalAlternation([
447
+ "Standard No.", "Standard No", "Std No.", "Std No", "Std", "Nos",
448
+ "No.", "No", "no", "Standard", "Trans.",
449
+ ]).as("type"));
450
+ rule("aiee_number", () => ((upper.repeat(2, 3).then(dash).then(digits)).or(digits.then(upper).then(absent(space.then(str("and"))))).or(digits.then(dot).then(digits))
451
+ .or(digits.as("main_number").then(space)
452
+ .then((str("(").then(digits.as("alt_number")).then(str(")"))).as("parenthetical")))
453
+ .or(digits.then(absent(space.then(str("and")).then(space).then(digits))))).as("number"));
454
+ rule("aiee_date_short", () => space.maybe().then(dash).then(R("aiee_year").as("year")));
455
+ rule("aiee_date_long", () => spaceMaybe().then(((str(",").or(dot)).as("separator").then(spaceMaybe())
456
+ .then(monthName().as("month").then(space).maybe())
457
+ .then(R("aiee_year").as("year"))).or(monthName().as("month").then(dash).then(R("aiee_year").as("year")))));
458
+ rule("aiee_date", () => ref(rules, "aiee_date_short").or(ref(rules, "aiee_date_long")).maybe());
459
+ rule("aiee_identifier", () => ref(rules, "aiee_prefix")
460
+ .then(space)
461
+ .then(ref(rules, "aiee_type").then(space).maybe())
462
+ .then(ref(rules, "aiee_number"))
463
+ .then(ref(rules, "aiee_date")));
464
+ // --- IRE sub-parser -----------------------------------------------------
465
+ rule("ire_year_full", () => str("191").then(digit.repeat(1, 1))
466
+ .or(str("19").then(literalAlternation(["2", "3", "4", "5"])).then(digit))
467
+ .or(str("196").then(match("[0-3]"))));
468
+ rule("ire_year_short", () => match("[1-6]").then(digit));
469
+ rule("ire_prefix", () => str("IEEE-IRE").or(str("IRE")).as("publisher"));
470
+ rule("ire_type", () => literalAlternation(["Trans.", "Standard", "Std"]).as("type"));
471
+ rule("ire_number", () => ((digits.then(space.or(dot)).then(upper).then(digits)).or(digits.then(dot).then(str("IRE")).then(digits).then(dot).then(digits).then(upper).then(digits)).or(upper.repeat(2, 4).then(dash).then(digits))
472
+ .or(digits)).as("number"));
473
+ rule("ire_date", () => (spaceMaybe().then(dash.or(str(",")).maybe()).then(spaceMaybe())
474
+ .then(ref(rules, "ire_year_full").or(ref(rules, "ire_year_short")).as("year"))).maybe());
475
+ rule("ire_identifier", () => (ref(rules, "ire_year_full").or(ref(rules, "ire_year_short")).as("year")
476
+ .then(space)
477
+ .then(ref(rules, "ire_prefix"))
478
+ .then(space)
479
+ .then(ref(rules, "ire_type").then(space).maybe())
480
+ .then(ref(rules, "ire_number"))
481
+ .then(spaceMaybe().then(dash.or(str(",")).maybe()).then(spaceMaybe())
482
+ .then(ref(rules, "ire_year_full").as("full_year")).maybe())).or(ref(rules, "ire_prefix")
483
+ .then(space)
484
+ .then(ref(rules, "ire_type").then(space).maybe())
485
+ .then(ref(rules, "ire_number"))
486
+ .then(ref(rules, "ire_date"))));
487
+ // --- NESC sub-parser ----------------------------------------------------
488
+ rule("nesc_c2_code", () => str("C2").as("code"));
489
+ rule("nesc_full_name", () => str("National Electrical Safety Code").or(str("National Electric Safety Code")));
490
+ rule("nesc_registered", () => str("(R)"));
491
+ rule("nesc_edition", () => literalAlternation([
492
+ "Premier Edition", "First Edition", "Second Edition", "Third Edition",
493
+ "Fourth Edition", "Fifth Edition", "Sixth Edition", "Seventh Edition",
494
+ "Eighth Edition", "Ninth Edition", "Tenth Edition",
495
+ ]).as("edition"));
496
+ rule("nesc_variant", () => str("Handbook").or(str("Redline")).as("variant"));
497
+ rule("nesc_month", () => literalAlternation([
498
+ "January", "February", "March", "April", "May", "June", "July",
499
+ "August", "September", "October", "November", "December",
500
+ ]).as("month"));
501
+ rule("nesc_c2_standard", () => ref(rules, "nesc_c2_code")
502
+ .then(dash)
503
+ .then(digit.repeat(4, 4).as("year"))
504
+ .then(str(",").maybe().then(space).maybe())
505
+ .then(ref(rules, "nesc_full_name"))
506
+ .then(ref(rules, "nesc_registered").maybe())
507
+ .then(space.then(str("(")).then(str("NESC")).then(ref(rules, "nesc_registered").maybe())
508
+ .then(str(")")).maybe()));
509
+ rule("nesc_year_first", () => str("IEEE").then(space).then(str("Std")).then(space).maybe()
510
+ .then(digit.repeat(4, 4).as("year"))
511
+ .then(space)
512
+ .then((ref(rules, "nesc_full_name").as("full_name")
513
+ .then(ref(rules, "nesc_registered").as("name_registered").maybe())
514
+ .then(space.then(str("(")).then(str("NESC").as("paren_abbr"))
515
+ .then(ref(rules, "nesc_registered").as("paren_registered").maybe())
516
+ .then(str(")")).maybe())).or(str("NESC").as("abbr").then(ref(rules, "nesc_registered").as("abbr_registered").maybe())))
517
+ .then(space.then(ref(rules, "nesc_variant")).maybe())
518
+ .then(str(",").then(space).then(ref(rules, "nesc_edition")).maybe()));
519
+ rule("nesc_name_first", () => ref(rules, "nesc_full_name")
520
+ .then(ref(rules, "nesc_registered").maybe())
521
+ .then(str(","))
522
+ .then(space)
523
+ .then(ref(rules, "nesc_c2_code"))
524
+ .then(dash)
525
+ .then(digit.repeat(4, 4).as("year"))
526
+ .then(space.then(str("-")).then(space).then(ref(rules, "nesc_variant")).as("variant").maybe()));
527
+ rule("nesc_draft_nesc", () => str("Draft").as("draft")
528
+ .then(space)
529
+ .then(ref(rules, "nesc_full_name").or(str("NESC")))
530
+ .then(ref(rules, "nesc_registered").maybe())
531
+ .then(str(","))
532
+ .then(space)
533
+ .then(ref(rules, "nesc_month"))
534
+ .then(space)
535
+ .then(digit.repeat(4, 4).as("year")));
536
+ rule("nesc_identifier", () => ref(rules, "nesc_draft_nesc")
537
+ .or(ref(rules, "nesc_name_first"))
538
+ .or(ref(rules, "nesc_c2_standard"))
539
+ .or(ref(rules, "nesc_year_first")));
540
+ // --- PSI/SI -------------------------------------------------------------
541
+ rule("psi_draft", () => slash.then(str("D")).then(dashMaybe()).then(digits.as("draft_version")));
542
+ rule("psi_date", () => (comma.then(monthName().or(R("month_numeric")).as("month")).then(space.or(dash))
543
+ .then(R("year_digits").as("year"))).or(dash.then(R("year_digits").as("year"))
544
+ .then(dash.then(digit.repeat(2, 2).as("month")).maybe())));
545
+ rule("ieee_astm_si_psi", () => str("IEEE/ASTM").or(str("IEEE")).as("publishers")
546
+ .then(space)
547
+ .then(str("PSI").or(str("SI")).as("si_type"))
548
+ .then(space.or(str(".")))
549
+ .then(digits.as("number"))
550
+ .then(str(".").then(R("year_digits").as("year")).maybe())
551
+ .then((ref(rules, "psi_draft").then(ref(rules, "psi_date").maybe())).or(ref(rules, "psi_date").then(ref(rules, "psi_draft").maybe())).maybe())
552
+ .then(ref(rules, "parenthetical").maybe()));
553
+ rule("no_prefix_ieee", () => R("characteristic_ieee_number").as("number")
554
+ .then((dash.then(letter)).maybe().as("suffix"))
555
+ .then((dash.then(R("year_digits"))).maybe().as("year"))
556
+ .then(ref(rules, "draft").maybe())
557
+ .then(str("(E)").or(str("(F)")).maybe())
558
+ .then(ref(rules, "parenthetical").maybe()));
559
+ rule("corrigendum_identifier", () => (R("publisher").then(R("copublisher").repeat(0, Infinity).as("copublishers")).as("publishers")
560
+ .then(space).maybe()).maybe()
561
+ .then(ref(rules, "type_word").as("type").then(spaceMaybe()).maybe())
562
+ .then(ref(rules, "number"))
563
+ .then(ref(rules, "part_subpart_year").maybe())
564
+ .as("base")
565
+ .then(slash.or(dash).or(space))
566
+ .then(str("Cor"))
567
+ .then(dash.or(dot).or(space).maybe())
568
+ .then(spaceMaybe())
569
+ .then(digits.as("cor_number"))
570
+ .then((dash.or(str(":")).or(space)).then(R("year_digits").as("cor_year")).maybe())
571
+ .then(ref(rules, "parenthetical").maybe()));
572
+ rule("interpretation_identifier", () => (R("publisher").then(R("copublisher").repeat(0, Infinity).as("copublishers")).as("publishers")
573
+ .then(space).maybe()).maybe()
574
+ .then(ref(rules, "type_word").as("type").then(spaceMaybe()).maybe())
575
+ .then(ref(rules, "number"))
576
+ .then(ref(rules, "part_subpart_year").maybe())
577
+ .as("base")
578
+ .then(slash.or(dash).or(space))
579
+ .then(str("INT"))
580
+ .then((dash.or(str(":")).or(space)).then(R("year_digits").as("int_year")).maybe())
581
+ .then(ref(rules, "parenthetical").maybe()));
582
+ rule("conformance_identifier", () => (R("publisher").then(R("copublisher").repeat(0, Infinity).as("copublishers")).as("publishers")
583
+ .then(space).maybe()).maybe()
584
+ .then(ref(rules, "type_word").as("type").then(spaceMaybe()).maybe())
585
+ .then(ref(rules, "number"))
586
+ .then(ref(rules, "part_subpart_year").maybe())
587
+ .as("base")
588
+ .then(slash.or(dash).or(space))
589
+ .then(str("Conformance"))
590
+ .then(match("[0-9]").repeat(1, Infinity).as("conf_number"))
591
+ .then(dash)
592
+ .then(R("year_digits").as("conf_year"))
593
+ .then(ref(rules, "parenthetical").maybe()));
594
+ rule("multi_numbered_identifier", () => ((R("publisher").then(space).maybe()).maybe()
595
+ .then(ref(rules, "type_word").as("type").then(spaceMaybe()).maybe())
596
+ .then(ref(rules, "number"))
597
+ .then(ref(rules, "part_subpart_year").or(ref(rules, "edition")).maybe())).as("primary_identifier")
598
+ .then(((slash.then(str("C")).then(digits).then(dot).then(digits).then(dot).then(digits)
599
+ .then(dash).then(R("year_digits"))).as("secondary_crossref")))
600
+ .or(str(",").then(space)
601
+ .then(ref(rules, "type_word").as("type").then(spaceMaybe()).maybe())
602
+ .then(ref(rules, "number"))
603
+ .then(dash)
604
+ .then(R("year_digits"))
605
+ .as("secondary_joint")));
606
+ rule("csa_dual_published", () => (R("publisher").then(space)
607
+ .then(ref(rules, "type_word").as("type").then(spaceMaybe()).maybe())
608
+ .then(ref(rules, "number"))
609
+ .then(ref(rules, "part_subpart_year").or(ref(rules, "edition")).maybe())).as("ieee_portion")
610
+ .then(slash)
611
+ .then(str("CSA"))
612
+ .then(space)
613
+ .then(((str("C").then(digit.repeat(2, 2)).then(dot).then(digit).then(space)
614
+ .then(str("No").or(str("NO"))).then(dot)
615
+ .then(space).then(match("[0-9.]").repeat(1, Infinity))
616
+ .then(dash.or(str(":"))).then(digit.repeat(2, 2))).or(str("C").then(match("[0-9.]").repeat(1, Infinity)).then(dash).then(digit.repeat(2, 2))).or(str("C").then(digit.repeat(2, 2)).then(dot).then(digit).then(space)
617
+ .then(str("No").or(str("NO")))
618
+ .then(dot).then(space).then(match("[0-9.]").repeat(1, Infinity))
619
+ .then(str(":")).then(digit.repeat(2, 2))).or(str("C").then(match("[0-9.]").repeat(1, Infinity)).then(str(":")).then(digit.repeat(2, 2)))).as("csa_portion")));
620
+ rule("combined_aiee_identifier", () => ref(rules, "aiee_identifier").as("first_aiee")
621
+ .then(space)
622
+ .then(str("and"))
623
+ .then(space)
624
+ .then(ref(rules, "aiee_identifier").as("second_aiee")));
625
+ rule("aiee_delegation", () => ((str("IEEE-AIEE").then(space).then(literalAlternation(["No.", "Nos", "No", "Standard", "Trans."]))).or(str("A.I.E.E.").then(space).then(literalAlternation(["No.", "Nos", "No"]))).or(str("A. I. E. E.").then(space).then(literalAlternation(["No.", "Nos", "No", "Standard"]))).or(str("AIEE").then(space).then(literalAlternation(["No.", "Nos", "No", "Standard", "Trans.", "Std"])))).present()
626
+ .then(ref(rules, "aiee_identifier").as("aiee")));
627
+ rule("ire_delegation", () => ((match("[1-6]").then(digit).then(space).then(str("IRE"))).or(str("19").then(digit.repeat(2, 2)).then(space).then(str("IRE"))).or(str("IRE").then(space).then(digits.or(str("Standard")).or(str("Std")).or(str("Trans")))).or(str("IEEE-IRE").then(space))).present()
628
+ .then(ref(rules, "ire_identifier").as("ire")));
629
+ rule("nesc_delegation", () => (str("C2-").then(R("year_digits"))).or(R("year_digits").then(space).then(str("NESC").or(str("National Electrical Safety Code")))).or(str("Draft").then(space).then(str("NESC").or(str("National Electrical Safety Code")))).or(str("National Electrical Safety Code").then(str(",")).then(space).then(str("C2-"))).or(
630
+ // Catalogue form: "IEEE Std YYYY NESC …" / "IEEE Std YYYY National
631
+ // Electrical Safety Code" - must not fall through to the generic
632
+ // standard grammar, which would read YYYY as a number.
633
+ str("IEEE").then(space).then(str("Std")).then(space).then(R("year_digits")).then(space)
634
+ .then(str("NESC").or(str("National Electrical Safety Code")))).present()
635
+ .then(ref(rules, "nesc_identifier").as("nesc")));
636
+ rule("identifier", () => ref(rules, "combined_aiee_identifier")
637
+ .or(ref(rules, "aiee_delegation"))
638
+ .or(ref(rules, "combined_aiee_identifier"))
639
+ .or(ref(rules, "ire_delegation"))
640
+ .or(ref(rules, "nesc_delegation"))
641
+ .or(ref(rules, "ieee_astm_si_psi"))
642
+ .or(ref(rules, "multi_numbered_identifier"))
643
+ .or(ref(rules, "csa_dual_published"))
644
+ .or(ref(rules, "s_designation"))
645
+ .or(ref(rules, "corrigendum_identifier"))
646
+ .or(ref(rules, "interpretation_identifier"))
647
+ .or(ref(rules, "conformance_identifier"))
648
+ .or(ref(rules, "joint_development_ieee_format"))
649
+ .or(ref(rules, "joint_development_iso_format"))
650
+ .or(ref(rules, "joint_development_iso_iec_edition"))
651
+ .or(ref(rules, "joint_development_embedded_stage"))
652
+ .or(ref(rules, "iec_ieee_copublished"))
653
+ .or(ref(rules, "number_first_identifier"))
654
+ .or(ref(rules, "ieee_approved_draft_identifier"))
655
+ .or(ref(rules, "ieee_draft_p_identifier"))
656
+ .or(ref(rules, "ieee_p_identifier"))
657
+ .or(ref(rules, "ansi_p_identifier"))
658
+ .or((R("publisher").then(R("copublisher").repeat(0, Infinity).as("copublishers")).as("publishers")
659
+ .then(space).maybe()).maybe()
660
+ .then(ref(rules, "draft_status").as("draft_status").maybe())
661
+ .then(str("Draft Std").as("type").then(spaceMaybe()).maybe())
662
+ .then(ref(rules, "type_word").as("type")
663
+ .then(space.then(str("No")).then(space).maybe())
664
+ .then(spaceMaybe()).maybe())
665
+ .then(ref(rules, "number"))
666
+ .then(ref(rules, "part_subpart_year").or(ref(rules, "edition")).maybe())
667
+ .then(ref(rules, "corrigendum").maybe())
668
+ .then(ref(rules, "amendment").maybe())
669
+ .then(ref(rules, "interpretation").maybe())
670
+ .then(ref(rules, "conformance").maybe())
671
+ .then(ref(rules, "ashrae_copub").maybe())
672
+ .then(ref(rules, "ieee_crossref").maybe())
673
+ .then(ref(rules, "draft").maybe())
674
+ .then(ref(rules, "revision_suffix").maybe())
675
+ .then(ref(rules, "trailing_month_year").maybe())
676
+ .then(
677
+ // The ASHRAE joint suffix may also trail a draft+date
678
+ // ("IEEE P1635/D13, December, 2017/ASHRAE Guideline 21").
679
+ ref(rules, "ashrae_copub").maybe())
680
+ .then(
681
+ // A bracketed narrative may sit between the base and a trailing
682
+ // corrigendum ("IEEE Std 671-1985 [Corrigendum to …]/Cor. 1-2010").
683
+ ref(rules, "book_nickname").maybe())
684
+ .then(ref(rules, "corrigendum").maybe())
685
+ .then(ref(rules, "edition").maybe())
686
+ .then(ref(rules, "parenthetical").maybe())
687
+ .then(ref(rules, "book_nickname").maybe())
688
+ .then(ref(rules, "redline").maybe())
689
+ .then(ref(rules, "title_portion").maybe())
690
+ .then(ref(rules, "approved_draft_suffix").maybe()))
691
+ .or(ref(rules, "no_prefix_ieee")));
692
+ return rules;
693
+ }
694
+ export const ieeeGrammar = {
695
+ rules: buildRules(),
696
+ root: "identifier",
697
+ };