@pubid/pubid 0.1.39 → 0.1.40
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/artifact/corpus.json.gz +0 -0
- package/dist/conformance/implementation.d.ts +3 -0
- package/dist/flavors/jis/index.js +64 -20
- package/dist/model/attribute.d.ts +3 -0
- package/dist/model/identifier.d.ts +7 -0
- package/dist/model/identifier.js +17 -0
- package/dist/pubid-urn/schemas/jis.js +10 -3
- package/package.json +1 -1
- package/vendor/parg/iho.json +1 -1
- package/vendor/parg/jis.json +1 -1
package/artifact/corpus.json.gz
CHANGED
|
Binary file
|
|
@@ -24,5 +24,8 @@ export interface Identifier {
|
|
|
24
24
|
toUrn(): string | undefined;
|
|
25
25
|
/** Deserialize the canonical hash; the idempotency gate relies on it. */
|
|
26
26
|
fromHash(hash: Record<string, unknown>): Identifier;
|
|
27
|
+
/** Ruby ==: canonical equality skipping equalityIgnored attributes
|
|
28
|
+
* (the (E) position is spelling, the language itself is not). */
|
|
29
|
+
equals?(other: Identifier): boolean;
|
|
27
30
|
}
|
|
28
31
|
export type ImplementationRegistry = Map<string, FlavorImplementation>;
|
|
@@ -14,7 +14,12 @@ import { BaseUrnGenerator } from "../../model/urn-generator.js";
|
|
|
14
14
|
*
|
|
15
15
|
* WES (welding-engineering-standard, pubid#638) rides the same flavor:
|
|
16
16
|
* "WES <number>[-parts][:year[R]]…" with no series letter and no JIS
|
|
17
|
-
* prefix — the code itself carries the "WES" root.
|
|
17
|
+
* prefix — the code itself carries the "WES" root. A WES id may also
|
|
18
|
+
* carry a TR/TS type after the root ("WES TR 2032:2024", its own
|
|
19
|
+
* welding-engineering-technical-report/-specification classes,
|
|
20
|
+
* pubid#716) and a language before the year ("WES 1112(E):2022",
|
|
21
|
+
* bound only when a colon follows; recorded as language_before_year,
|
|
22
|
+
* which equality ignores — the two (E) positions are one document).
|
|
18
23
|
*/
|
|
19
24
|
function buildRules() {
|
|
20
25
|
const rules = {};
|
|
@@ -61,11 +66,18 @@ function buildRules() {
|
|
|
61
66
|
.then(rules["symbol_clause"].maybe()));
|
|
62
67
|
// WES (Japan Welding Engineering Society) rides the JIS flavor with the
|
|
63
68
|
// same tail but no prefix and no series letter; the root tries it first,
|
|
64
|
-
// as the reference grammar does.
|
|
69
|
+
// as the reference grammar does. A WES id may also carry a TR/TS type
|
|
70
|
+
// after the root ("WES TR 2032:2024") and a language before the year
|
|
71
|
+
// ("WES 1112(E):2022" — bound only when a colon follows, so
|
|
72
|
+
// "WES 1112(E)" with no year still reads as no language).
|
|
73
|
+
rule("wes_type", () => (str("TR").or(str("TS"))).as("wes_type").then(space));
|
|
74
|
+
rule("wes_language", () => jpLparen.or(str("(")).then(match("[EJ]").as("wes_language"), jpRparen.or(str(")"))).then(colon.present()));
|
|
65
75
|
rule("wes_identifier", () => str("WES").as("wes")
|
|
66
76
|
.then(space)
|
|
77
|
+
.then(rules["wes_type"].maybe())
|
|
67
78
|
.then(rules["number"])
|
|
68
79
|
.then(rules["parts"])
|
|
80
|
+
.then(rules["wes_language"].maybe())
|
|
69
81
|
.then(rules["year"].maybe())
|
|
70
82
|
.then(rules["language"].maybe())
|
|
71
83
|
.then(rules["all_parts"].maybe())
|
|
@@ -95,6 +107,13 @@ class JisIdentifier extends BaseIdentifier {
|
|
|
95
107
|
yearWithReaffirmation() {
|
|
96
108
|
return `${this.year}${this.reaffirmed === true ? "R" : ""}`;
|
|
97
109
|
}
|
|
110
|
+
/** The ":year[R]" and "(lang)" tail, in the order the source used
|
|
111
|
+
* (ruby year_and_language). */
|
|
112
|
+
yearAndLanguage() {
|
|
113
|
+
const yearPart = this.year !== undefined ? `:${this.yearWithReaffirmation()}` : "";
|
|
114
|
+
const langPart = this.language !== undefined ? `(${this.language})` : "";
|
|
115
|
+
return this.language_before_year === true ? langPart + yearPart : yearPart + langPart;
|
|
116
|
+
}
|
|
98
117
|
symbolSuffix() {
|
|
99
118
|
if (this.symbol === undefined)
|
|
100
119
|
return "";
|
|
@@ -104,7 +123,7 @@ class JisIdentifier extends BaseIdentifier {
|
|
|
104
123
|
return "";
|
|
105
124
|
}
|
|
106
125
|
}
|
|
107
|
-
const JIS_MAPPINGS = keyValue({ wire: "series", to: "series" }, { wire: "number", to: "number" }, { wire: "parts", to: "parts" }, { wire: "year", to: "year" }, { wire: "language", to: "language" }, { wire: "all_parts", to: "all_parts" }, { wire: "reaffirmed", to: "reaffirmed" }, { wire: "symbol", to: "symbol" });
|
|
126
|
+
const JIS_MAPPINGS = keyValue({ wire: "series", to: "series" }, { wire: "number", to: "number" }, { wire: "parts", to: "parts" }, { wire: "year", to: "year" }, { wire: "language", to: "language" }, { wire: "language_before_year", to: "language_before_year" }, { wire: "all_parts", to: "all_parts" }, { wire: "reaffirmed", to: "reaffirmed" }, { wire: "symbol", to: "symbol" });
|
|
108
127
|
function jisClass(kind) {
|
|
109
128
|
const isSupplement = kind === "amendment" || kind === "corrigendum" || kind === "explanation";
|
|
110
129
|
class JisKindIdentifier extends JisIdentifier {
|
|
@@ -122,6 +141,7 @@ function jisClass(kind) {
|
|
|
122
141
|
parts: { type: "string", collection: true },
|
|
123
142
|
year: { type: "integer" },
|
|
124
143
|
language: { type: "string" },
|
|
144
|
+
language_before_year: { type: "boolean", equalityIgnored: true },
|
|
125
145
|
all_parts: { type: "boolean", default: false },
|
|
126
146
|
reaffirmed: { type: "boolean" },
|
|
127
147
|
symbol: { type: "string" },
|
|
@@ -137,10 +157,7 @@ function jisClass(kind) {
|
|
|
137
157
|
const typePrefix = KIND_PREFIXES[kind];
|
|
138
158
|
let result = typePrefix === undefined ? "JIS" : `JIS ${typePrefix}`;
|
|
139
159
|
result += ` ${this.code()}`;
|
|
140
|
-
|
|
141
|
-
result += `:${this.yearWithReaffirmation()}`;
|
|
142
|
-
if (this.language !== undefined)
|
|
143
|
-
result += `(${this.language})`;
|
|
160
|
+
result += this.yearAndLanguage();
|
|
144
161
|
if (this.all_parts === true)
|
|
145
162
|
result += "(規格群)";
|
|
146
163
|
return result + this.symbolSuffix();
|
|
@@ -167,36 +184,43 @@ const KIND_CLASSES = {
|
|
|
167
184
|
corrigendum: jisClass("corrigendum"),
|
|
168
185
|
explanation: jisClass("explanation"),
|
|
169
186
|
};
|
|
187
|
+
const WES_TYPE_PREFIXES = {
|
|
188
|
+
"welding-engineering-standard": undefined,
|
|
189
|
+
"welding-engineering-technical-report": "TR",
|
|
190
|
+
"welding-engineering-technical-specification": "TS",
|
|
191
|
+
};
|
|
170
192
|
// WES 7700-1:2019 — JSA sells Welding Engineering Standards next to JIS,
|
|
171
193
|
// so they parse through the JIS flavor, but the id carries no series
|
|
172
|
-
// letter and no JIS prefix ("WES" is the root of the designation).
|
|
173
|
-
|
|
194
|
+
// letter and no JIS prefix ("WES" is the root of the designation). The
|
|
195
|
+
// TR/TS type token after the root picks the WES TR / WES TS classes
|
|
196
|
+
// (pubid#716): "WES TR 2032" is not "WES 2032" and not "TR Z 2032".
|
|
197
|
+
function wesClass(kind) {
|
|
174
198
|
class JisWesIdentifier extends JisIdentifier {
|
|
175
|
-
static polymorphicName =
|
|
199
|
+
static polymorphicName = `pubid:jis:${kind}`;
|
|
176
200
|
static attributes = extendAttributes(BaseIdentifier, {
|
|
177
201
|
number: { type: "string" },
|
|
178
202
|
parts: { type: "string", collection: true },
|
|
179
203
|
year: { type: "integer" },
|
|
180
204
|
language: { type: "string" },
|
|
205
|
+
language_before_year: { type: "boolean", equalityIgnored: true },
|
|
181
206
|
all_parts: { type: "boolean", default: false },
|
|
182
207
|
reaffirmed: { type: "boolean" },
|
|
183
208
|
symbol: { type: "string" },
|
|
184
209
|
});
|
|
185
|
-
static mappings = keyValue({ wire: "number", to: "number" }, { wire: "parts", to: "parts" }, { wire: "year", to: "year" }, { wire: "language", to: "language" }, { wire: "all_parts", to: "all_parts" }, { wire: "reaffirmed", to: "reaffirmed" }, { wire: "symbol", to: "symbol" });
|
|
210
|
+
static mappings = keyValue({ wire: "number", to: "number" }, { wire: "parts", to: "parts" }, { wire: "year", to: "year" }, { wire: "language", to: "language" }, { wire: "language_before_year", to: "language_before_year" }, { wire: "all_parts", to: "all_parts" }, { wire: "reaffirmed", to: "reaffirmed" }, { wire: "symbol", to: "symbol" });
|
|
186
211
|
code() {
|
|
187
212
|
if (this.base !== undefined)
|
|
188
213
|
return this.base.code();
|
|
189
|
-
|
|
214
|
+
const prefix = WES_TYPE_PREFIXES[kind];
|
|
215
|
+
const root = prefix === undefined ? "WES" : `WES ${prefix}`;
|
|
216
|
+
let result = `${root} ${this.number}`;
|
|
190
217
|
if (this.parts !== undefined)
|
|
191
218
|
result += this.parts.map((p) => `-${p}`).join("");
|
|
192
219
|
return result;
|
|
193
220
|
}
|
|
194
221
|
render() {
|
|
195
222
|
let result = this.code() ?? "";
|
|
196
|
-
|
|
197
|
-
result += `:${this.yearWithReaffirmation()}`;
|
|
198
|
-
if (this.language !== undefined)
|
|
199
|
-
result += `(${this.language})`;
|
|
223
|
+
result += this.yearAndLanguage();
|
|
200
224
|
if (this.all_parts === true)
|
|
201
225
|
result += "(規格群)";
|
|
202
226
|
return result + this.symbolSuffix();
|
|
@@ -205,7 +229,11 @@ function wesClass() {
|
|
|
205
229
|
registerType(JisWesIdentifier);
|
|
206
230
|
return JisWesIdentifier;
|
|
207
231
|
}
|
|
208
|
-
const
|
|
232
|
+
const WES_CLASSES = {
|
|
233
|
+
"welding-engineering-standard": wesClass("welding-engineering-standard"),
|
|
234
|
+
"welding-engineering-technical-report": wesClass("welding-engineering-technical-report"),
|
|
235
|
+
"welding-engineering-technical-specification": wesClass("welding-engineering-technical-specification"),
|
|
236
|
+
};
|
|
209
237
|
class JisUrnGenerator extends BaseUrnGenerator {
|
|
210
238
|
generate() {
|
|
211
239
|
const id = this.identifier;
|
|
@@ -226,7 +254,7 @@ class JisUrnGenerator extends BaseUrnGenerator {
|
|
|
226
254
|
return parts.join(":");
|
|
227
255
|
}
|
|
228
256
|
}
|
|
229
|
-
for (const klass of [...Object.values(KIND_CLASSES),
|
|
257
|
+
for (const klass of [...Object.values(KIND_CLASSES), ...Object.values(WES_CLASSES)]) {
|
|
230
258
|
klass.urnGenerator = JisUrnGenerator;
|
|
231
259
|
}
|
|
232
260
|
function isObj(v) {
|
|
@@ -294,13 +322,29 @@ class JisBuilder {
|
|
|
294
322
|
};
|
|
295
323
|
if (tree["year"] !== undefined && tree["year"] !== null)
|
|
296
324
|
attrs["year"] = Number(tree["year"]);
|
|
297
|
-
|
|
325
|
+
const wesType = tree["wes_type"] === undefined || tree["wes_type"] === null ? undefined : String(tree["wes_type"]);
|
|
326
|
+
const kind = wesType === "TR"
|
|
327
|
+
? "welding-engineering-technical-report"
|
|
328
|
+
: wesType === "TS"
|
|
329
|
+
? "welding-engineering-technical-specification"
|
|
330
|
+
: "welding-engineering-standard";
|
|
331
|
+
// "wes_language" is a language printed before the year
|
|
332
|
+
// ("WES 1112(E):2022"); an id carries one language, not two.
|
|
333
|
+
if (tree["wes_language"] !== undefined && tree["wes_language"] !== null) {
|
|
334
|
+
if (tree["language"] !== undefined && tree["language"] !== null) {
|
|
335
|
+
throw new ParseFailed("JIS: a WES id carries one language, not two", 0);
|
|
336
|
+
}
|
|
337
|
+
attrs["language"] = String(tree["wes_language"]);
|
|
338
|
+
attrs["language_before_year"] = true;
|
|
339
|
+
}
|
|
340
|
+
else if (tree["language"] !== undefined && tree["language"] !== null) {
|
|
298
341
|
attrs["language"] = String(tree["language"]);
|
|
342
|
+
}
|
|
299
343
|
if (tree["all_parts"] !== undefined)
|
|
300
344
|
attrs["all_parts"] = true;
|
|
301
345
|
if (tree["reaffirmed"] !== undefined && tree["reaffirmed"] !== null)
|
|
302
346
|
attrs["reaffirmed"] = true;
|
|
303
|
-
return new
|
|
347
|
+
return new WES_CLASSES[kind](attrs);
|
|
304
348
|
}
|
|
305
349
|
buildSupplement(tree, kind, key, prefix) {
|
|
306
350
|
const supp = isObj(tree[key]) ? tree[key] : {};
|
|
@@ -18,6 +18,9 @@ export interface AttributeSpec {
|
|
|
18
18
|
collection?: boolean;
|
|
19
19
|
/** Materialize [] when the input hash omits the key (tgpp parts). */
|
|
20
20
|
initializeEmpty?: boolean;
|
|
21
|
+
/** Ruby `equality_ignored`: the attribute serializes, but `==` skips it
|
|
22
|
+
* (jis language_before_year — where the source printed "(E)" is spelling). */
|
|
23
|
+
equalityIgnored?: boolean;
|
|
21
24
|
}
|
|
22
25
|
export type AttributeTable = Record<string, AttributeSpec>;
|
|
23
26
|
/**
|
|
@@ -62,6 +62,13 @@ export declare abstract class BaseIdentifier {
|
|
|
62
62
|
* `PubidUrn.parse(this.toPubidUrn()).toHash == this.toHash`. */
|
|
63
63
|
toPubidUrn(): string;
|
|
64
64
|
fromHash(hash: Record<string, unknown>): BaseIdentifier;
|
|
65
|
+
/** Ruby == (lutaml equality with `equality_ignored`): canonical-hash
|
|
66
|
+
* equality that skips the attributes a flavor declares
|
|
67
|
+
* equalityIgnored. The skipped keys stay in to_hash — it is ==, not
|
|
68
|
+
* serialization, that reads the flag. */
|
|
69
|
+
equals(other: BaseIdentifier): boolean;
|
|
70
|
+
/** The canonical hash minus every equalityIgnored attribute's wire key. */
|
|
71
|
+
protected equalityHash(): Record<string, unknown>;
|
|
65
72
|
/** SubsetMatch: an all-parts reference skips the part attributes. */
|
|
66
73
|
subsetAllPartsWildcard(): boolean;
|
|
67
74
|
protected classAttributes(): AttributeTable;
|
package/dist/model/identifier.js
CHANGED
|
@@ -116,6 +116,23 @@ export class BaseIdentifier {
|
|
|
116
116
|
fromHash(hash) {
|
|
117
117
|
return this.constructor.fromHash(hash);
|
|
118
118
|
}
|
|
119
|
+
/** Ruby == (lutaml equality with `equality_ignored`): canonical-hash
|
|
120
|
+
* equality that skips the attributes a flavor declares
|
|
121
|
+
* equalityIgnored. The skipped keys stay in to_hash — it is ==, not
|
|
122
|
+
* serialization, that reads the flag. */
|
|
123
|
+
equals(other) {
|
|
124
|
+
return canonicalKey(this.equalityHash()) === canonicalKey(other.equalityHash());
|
|
125
|
+
}
|
|
126
|
+
/** The canonical hash minus every equalityIgnored attribute's wire key. */
|
|
127
|
+
equalityHash() {
|
|
128
|
+
const hash = { ...this.toHash() };
|
|
129
|
+
for (const [name, spec] of Object.entries(this.classAttributes())) {
|
|
130
|
+
if (spec.equalityIgnored !== true)
|
|
131
|
+
continue;
|
|
132
|
+
delete hash[this.wireKeyFor(name).wire];
|
|
133
|
+
}
|
|
134
|
+
return hash;
|
|
135
|
+
}
|
|
119
136
|
/** SubsetMatch: an all-parts reference skips the part attributes. */
|
|
120
137
|
subsetAllPartsWildcard() {
|
|
121
138
|
return Boolean(this["all_parts"]);
|
|
@@ -11,14 +11,21 @@ export const jisSchema = define("jis", (s) => {
|
|
|
11
11
|
s.atom("parts", "part", "list");
|
|
12
12
|
s.atom("year", "year", "int");
|
|
13
13
|
s.atom("reaffirmed", "reaffirmed", "bool");
|
|
14
|
+
s.atom("language", "lang");
|
|
15
|
+
s.facet("language_before_year", "langfirst", "bool");
|
|
14
16
|
s.type("pubid:jis:all-parts", "all");
|
|
15
|
-
s.type("pubid:jis:amendment", "amd");
|
|
16
|
-
s.type("pubid:jis:corrigendum", "cor");
|
|
17
|
-
s.type("pubid:jis:explanation", "e"
|
|
17
|
+
s.type("pubid:jis:amendment", "amd", { core: [["number", "int"]] });
|
|
18
|
+
s.type("pubid:jis:corrigendum", "cor", { core: [["number", "int"]] });
|
|
19
|
+
s.type("pubid:jis:explanation", "e", {
|
|
20
|
+
core: [],
|
|
21
|
+
atoms: [["number", "n", "int"]],
|
|
22
|
+
});
|
|
18
23
|
s.type("pubid:jis:identifier", "id");
|
|
19
24
|
s.type("pubid:jis:japanese-industrial-standard", "jis");
|
|
20
25
|
s.type("pubid:jis:standard", "std");
|
|
21
26
|
s.type("pubid:jis:technical-report", "tr");
|
|
22
27
|
s.type("pubid:jis:technical-specification", "ts");
|
|
23
28
|
s.type("pubid:jis:welding-engineering-standard", "wes");
|
|
29
|
+
s.type("pubid:jis:welding-engineering-technical-report", "westr");
|
|
30
|
+
s.type("pubid:jis:welding-engineering-technical-specification", "wests");
|
|
24
31
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pubid/pubid",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.40",
|
|
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",
|
package/vendor/parg/iho.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"bindings":null,"version":"0.2.0","grammar":"PubidIho","shape":"parsanol-tree/v2","binding_version":1,"entries":{"identifier":{"root":"identifier","grammar":{"atoms":[{"Str":{"pattern":"IHO"}},{"Entity":{"atom":2}},{"Str":{"pattern":" "}},{"Sequence":{"atoms":[0,1]}},{"Repetition":{"atom":3,"min":0,"max":1,"tag":"Maybe"}},{"Entity":{"atom":12}},{"Str":{"pattern":"S"}},{"Str":{"pattern":"P"}},{"Str":{"pattern":"M"}},{"Str":{"pattern":"B"}},{"Str":{"pattern":"C"}},{"Alternative":{"atoms":[6,7,8,9,10]}},{"Named":{"name":"type","atom":11}},{"Entity":{"atom":14}},{"Str":{"pattern":"-"}},{"Entity":{"atom":26}},{"Entity":{"atom":17}},{"Re":{"pattern":"[\\x30-\\x39]"}},{"Repetition":{"atom":16,"min":1,"max":null,"tag":"Repetition"}},{"Entity":{"atom":23}},{"Str":{"pattern":":"}},{"Entity":{"atom":17}},{"Repetition":{"atom":21,"min":1,"max":null,"tag":"Repetition"}},{"Sequence":{"atoms":[20,22]}},{"Repetition":{"atom":19,"min":0,"max":1,"tag":"Maybe"}},{"Sequence":{"atoms":[18,24]}},{"Named":{"name":"number","atom":25}},{"Entity":{"atom":53}},{"Str":{"pattern":"-"}},{"Str":{"pattern":"S"}},{"Str":{"pattern":"P"}},{"Str":{"pattern":"M"}},{"Str":{"pattern":"B"}},{"Str":{"pattern":"C"}},{"Alternative":{"atoms":[29,30,31,32,33]}},{"Entity":{"atom":14}},{"Entity":{"atom":17}},{"Repetition":{"atom":36,"min":1,"max":null,"tag":"Repetition"}},{"Sequence":{"atoms":[34,35,37]}},{"Entity":{"atom":17}},{"Repetition":{"atom":39,"min":1,"max":null,"tag":"Repetition"}},{"Entity":{"atom":46}},{"Entity":{"atom":43}},{"Re":{"pattern":"[\\x41-\\x5a]"}},{"Entity":{"atom":45}},{"Re":{"pattern":"[\\x61-\\x7a]"}},{"Alternative":{"atoms":[42,44]}},{"Repetition":{"atom":41,"min":0,"max":null,"tag":"Repetition"}},{"Repetition":{"atom":47,"min":0,"max":1,"tag":"Maybe"}},{"Sequence":{"atoms":[40,48]}},{"Entity":{"atom":43}},{"Alternative":{"atoms":[38,49,50]}},{"Named":{"name":"part","atom":51}},{"Sequence":{"atoms":[28,52]}},{"Repetition":{"atom":27,"min":0,"max":1,"tag":"Maybe"}},{"Entity":{"atom":57}},{"Entity":{"atom":43}},{"Named":{"name":"part","atom":56}},{"Repetition":{"atom":55,"min":0,"max":1,"tag":"Maybe"}},{"Entity":{"atom":94}},{"Str":{"pattern":"/"}},{"Entity":{"atom":17}},{"Repetition":{"atom":61,"min":1,"max":null,"tag":"Repetition"}},{"Named":{"name":"volume","atom":62}},{"Entity":{"atom":92}},{"Entity":{"atom":78}},{"Entity":{"atom":2}},{"Entity":{"atom":17}},{"Repetition":{"atom":67,"min":1,"max":null,"tag":"Repetition"}},{"Entity":{"atom":70}},{"Str":{"pattern":"."}},{"Entity":{"atom":17}},{"Repetition":{"atom":71,"min":1,"max":null,"tag":"Repetition"}},{"Entity":{"atom":70}},{"Entity":{"atom":17}},{"Repetition":{"atom":74,"min":1,"max":null,"tag":"Repetition"}},{"Sequence":{"atoms":[68,69,72,73,75]}},{"Named":{"name":"volume_edition","atom":76}},{"Sequence":{"atoms":[66,77]}},{"Entity":{"atom":90}},{"Entity":{"atom":2}},{"Str":{"pattern":"("}},{"Str":{"pattern":"19"}},{"Str":{"pattern":"20"}},{"Alternative":{"atoms":[82,83]}},{"Entity":{"atom":17}},{"Repetition":{"atom":85,"min":2,"max":null,"tag":"Repetition"}},{"Sequence":{"atoms":[84,86]}},{"Named":{"name":"volume_year","atom":87}},{"Str":{"pattern":")"}},{"Sequence":{"atoms":[80,81,88,89]}},{"Repetition":{"atom":79,"min":0,"max":1,"tag":"Maybe"}},{"Sequence":{"atoms":[65,91]}},{"Repetition":{"atom":64,"min":0,"max":1,"tag":"Maybe"}},{"Sequence":{"atoms":[60,63,93]}},{"Repetition":{"atom":59,"min":0,"max":1,"tag":"Maybe"}},{"Entity":{"atom":137}},{"Entity":{"atom":109}},{"Entity":{"atom":2}},{"Entity":{"atom":17}},{"Repetition":{"atom":99,"min":1,"max":null,"tag":"Repetition"}},{"Entity":{"atom":70}},{"Entity":{"atom":17}},{"Repetition":{"atom":102,"min":1,"max":null,"tag":"Repetition"}},{"Entity":{"atom":70}},{"Entity":{"atom":17}},{"Repetition":{"atom":105,"min":1,"max":null,"tag":"Repetition"}},{"Sequence":{"atoms":[100,101,103,104,106]}},{"Named":{"name":"edition","atom":107}},{"Sequence":{"atoms":[98,108]}},{"Entity":{"atom":122}},{"Entity":{"atom":2}},{"Str":{"pattern":"v"}},{"Entity":{"atom":17}},{"Repetition":{"atom":113,"min":1,"max":null,"tag":"Repetition"}},{"Str":{"pattern":"."}},{"Entity":{"atom":17}},{"Repetition":{"atom":116,"min":1,"max":null,"tag":"Repetition"}},{"Sequence":{"atoms":[115,117]}},{"Repetition":{"atom":118,"min":0,"max":1,"tag":"Maybe"}},{"Sequence":{"atoms":[114,119]}},{"Named":{"name":"edition_shorthand","atom":120}},{"Sequence":{"atoms":[111,112,121]}},{"Alternative":{"atoms":[97,110]}},{"Entity":{"atom":135}},{"Entity":{"atom":2}},{"Str":{"pattern":"("}},{"Str":{"pattern":"19"}},{"Str":{"pattern":"20"}},{"Alternative":{"atoms":[127,128]}},{"Entity":{"atom":17}},{"Repetition":{"atom":130,"min":2,"max":null,"tag":"Repetition"}},{"Sequence":{"atoms":[129,131]}},{"Named":{"name":"year","atom":132}},{"Str":{"pattern":")"}},{"Sequence":{"atoms":[125,126,133,134]}},{"Repetition":{"atom":124,"min":0,"max":1,"tag":"Maybe"}},{"Sequence":{"atoms":[123,136]}},{"Repetition":{"atom":96,"min":0,"max":1,"tag":"Maybe"}},{"Entity":{"atom":177}},{"Entity":{"atom":2}},{"Str":{"pattern":"Suppl"}},{"Str":{"pattern":"Sup"}},{"Alternative":{"atoms":[141,142]}},{"Entity":{"atom":2}},{"Entity":{"atom":17}},{"Repetition":{"atom":145,"min":1,"max":null,"tag":"Repetition"}},{"Named":{"name":"supplement","atom":146}},{"Entity":{"atom":175}},{"Entity":{"atom":161}},{"Entity":{"atom":2}},{"Entity":{"atom":17}},{"Repetition":{"atom":151,"min":1,"max":null,"tag":"Repetition"}},{"Entity":{"atom":70}},{"Entity":{"atom":17}},{"Repetition":{"atom":154,"min":1,"max":null,"tag":"Repetition"}},{"Entity":{"atom":70}},{"Entity":{"atom":17}},{"Repetition":{"atom":157,"min":1,"max":null,"tag":"Repetition"}},{"Sequence":{"atoms":[152,153,155,156,158]}},{"Named":{"name":"supplement_edition","atom":159}},{"Sequence":{"atoms":[150,160]}},{"Entity":{"atom":173}},{"Entity":{"atom":2}},{"Str":{"pattern":"("}},{"Str":{"pattern":"19"}},{"Str":{"pattern":"20"}},{"Alternative":{"atoms":[165,166]}},{"Entity":{"atom":17}},{"Repetition":{"atom":168,"min":2,"max":null,"tag":"Repetition"}},{"Sequence":{"atoms":[167,169]}},{"Named":{"name":"supplement_year","atom":170}},{"Str":{"pattern":")"}},{"Sequence":{"atoms":[163,164,171,172]}},{"Repetition":{"atom":162,"min":0,"max":1,"tag":"Maybe"}},{"Sequence":{"atoms":[149,174]}},{"Repetition":{"atom":148,"min":0,"max":1,"tag":"Maybe"}},{"Sequence":{"atoms":[140,143,144,147,176]}},{"Repetition":{"atom":139,"min":0,"max":1,"tag":"Maybe"}},{"Entity":{"atom":233}},{"Entity":{"atom":2}},{"Str":{"pattern":"Part"}},{"Entity":{"atom":2}},{"Entity":{"atom":203}},{"Entity":{"atom":194}},{"Str":{"pattern":"S"}},{"Str":{"pattern":"P"}},{"Str":{"pattern":"M"}},{"Str":{"pattern":"B"}},{"Str":{"pattern":"C"}},{"Alternative":{"atoms":[185,186,187,188,189]}},{"Entity":{"atom":14}},{"Entity":{"atom":17}},{"Repetition":{"atom":192,"min":1,"max":null,"tag":"Repetition"}},{"Sequence":{"atoms":[190,191,193]}},{"Entity":{"atom":17}},{"Repetition":{"atom":195,"min":1,"max":null,"tag":"Repetition"}},{"Entity":{"atom":46}},{"Repetition":{"atom":197,"min":0,"max":null,"tag":"Repetition"}},{"Repetition":{"atom":198,"min":0,"max":1,"tag":"Maybe"}},{"Sequence":{"atoms":[196,199]}},{"Entity":{"atom":43}},{"Alternative":{"atoms":[184,200,201]}},{"Named":{"name":"part","atom":202}},{"Entity":{"atom":231}},{"Entity":{"atom":217}},{"Entity":{"atom":2}},{"Entity":{"atom":17}},{"Repetition":{"atom":207,"min":1,"max":null,"tag":"Repetition"}},{"Entity":{"atom":70}},{"Entity":{"atom":17}},{"Repetition":{"atom":210,"min":1,"max":null,"tag":"Repetition"}},{"Entity":{"atom":70}},{"Entity":{"atom":17}},{"Repetition":{"atom":213,"min":1,"max":null,"tag":"Repetition"}},{"Sequence":{"atoms":[208,209,211,212,214]}},{"Named":{"name":"part_edition","atom":215}},{"Sequence":{"atoms":[206,216]}},{"Entity":{"atom":229}},{"Entity":{"atom":2}},{"Str":{"pattern":"("}},{"Str":{"pattern":"19"}},{"Str":{"pattern":"20"}},{"Alternative":{"atoms":[221,222]}},{"Entity":{"atom":17}},{"Repetition":{"atom":224,"min":2,"max":null,"tag":"Repetition"}},{"Sequence":{"atoms":[223,225]}},{"Named":{"name":"part_year","atom":226}},{"Str":{"pattern":")"}},{"Sequence":{"atoms":[219,220,227,228]}},{"Repetition":{"atom":218,"min":0,"max":1,"tag":"Maybe"}},{"Sequence":{"atoms":[205,230]}},{"Repetition":{"atom":204,"min":0,"max":1,"tag":"Maybe"}},{"Sequence":{"atoms":[180,181,182,183,232]}},{"Repetition":{"atom":179,"min":0,"max":1,"tag":"Maybe"}},{"Entity":{"atom":270}},{"Entity":{"atom":2}},{"Str":{"pattern":"Annex"}},{"Entity":{"atom":2}},{"Entity":{"atom":43}},{"Named":{"name":"annex","atom":239}},{"Entity":{"atom":268}},{"Entity":{"atom":254}},{"Entity":{"atom":2}},{"Entity":{"atom":17}},{"Repetition":{"atom":244,"min":1,"max":null,"tag":"Repetition"}},{"Entity":{"atom":70}},{"Entity":{"atom":17}},{"Repetition":{"atom":247,"min":1,"max":null,"tag":"Repetition"}},{"Entity":{"atom":70}},{"Entity":{"atom":17}},{"Repetition":{"atom":250,"min":1,"max":null,"tag":"Repetition"}},{"Sequence":{"atoms":[245,246,248,249,251]}},{"Named":{"name":"annex_edition","atom":252}},{"Sequence":{"atoms":[243,253]}},{"Entity":{"atom":266}},{"Entity":{"atom":2}},{"Str":{"pattern":"("}},{"Str":{"pattern":"19"}},{"Str":{"pattern":"20"}},{"Alternative":{"atoms":[258,259]}},{"Entity":{"atom":17}},{"Repetition":{"atom":261,"min":2,"max":null,"tag":"Repetition"}},{"Sequence":{"atoms":[260,262]}},{"Named":{"name":"annex_year","atom":263}},{"Str":{"pattern":")"}},{"Sequence":{"atoms":[256,257,264,265]}},{"Repetition":{"atom":255,"min":0,"max":1,"tag":"Maybe"}},{"Sequence":{"atoms":[242,267]}},{"Repetition":{"atom":241,"min":0,"max":1,"tag":"Maybe"}},{"Sequence":{"atoms":[236,237,238,240,269]}},{"Repetition":{"atom":235,"min":0,"max":1,"tag":"Maybe"}},{"Entity":{"atom":321}},{"Entity":{"atom":2}},{"Str":{"pattern":"Appendix"}},{"Str":{"pattern":"App"}},{"Str":{"pattern":"Ap."}},{"Alternative":{"atoms":[274,275,276]}},{"Entity":{"atom":2}},{"Entity":{"atom":284}},{"Entity":{"atom":43}},{"Entity":{"atom":17}},{"Repetition":{"atom":281,"min":1,"max":null,"tag":"Repetition"}},{"Alternative":{"atoms":[280,282]}},{"Named":{"name":"appendix","atom":283}},{"Entity":{"atom":290}},{"Entity":{"atom":14}},{"Entity":{"atom":17}},{"Repetition":{"atom":287,"min":1,"max":null,"tag":"Repetition"}},{"Named":{"name":"appendix_subnumber","atom":288}},{"Sequence":{"atoms":[286,289]}},{"Repetition":{"atom":285,"min":0,"max":1,"tag":"Maybe"}},{"Entity":{"atom":319}},{"Entity":{"atom":305}},{"Entity":{"atom":2}},{"Entity":{"atom":17}},{"Repetition":{"atom":295,"min":1,"max":null,"tag":"Repetition"}},{"Entity":{"atom":70}},{"Entity":{"atom":17}},{"Repetition":{"atom":298,"min":1,"max":null,"tag":"Repetition"}},{"Entity":{"atom":70}},{"Entity":{"atom":17}},{"Repetition":{"atom":301,"min":1,"max":null,"tag":"Repetition"}},{"Sequence":{"atoms":[296,297,299,300,302]}},{"Named":{"name":"appendix_edition","atom":303}},{"Sequence":{"atoms":[294,304]}},{"Entity":{"atom":317}},{"Entity":{"atom":2}},{"Str":{"pattern":"("}},{"Str":{"pattern":"19"}},{"Str":{"pattern":"20"}},{"Alternative":{"atoms":[309,310]}},{"Entity":{"atom":17}},{"Repetition":{"atom":312,"min":2,"max":null,"tag":"Repetition"}},{"Sequence":{"atoms":[311,313]}},{"Named":{"name":"appendix_year","atom":314}},{"Str":{"pattern":")"}},{"Sequence":{"atoms":[307,308,315,316]}},{"Repetition":{"atom":306,"min":0,"max":1,"tag":"Maybe"}},{"Sequence":{"atoms":[293,318]}},{"Repetition":{"atom":292,"min":0,"max":1,"tag":"Maybe"}},{"Sequence":{"atoms":[273,277,278,279,291,320]}},{"Repetition":{"atom":272,"min":0,"max":1,"tag":"Maybe"}},{"Entity":{"atom":362}},{"Entity":{"atom":348}},{"Entity":{"atom":2}},{"Str":{"pattern":"Vol."}},{"Entity":{"atom":2}},{"Entity":{"atom":17}},{"Repetition":{"atom":328,"min":1,"max":null,"tag":"Repetition"}},{"Named":{"name":"volume","atom":329}},{"Entity":{"atom":346}},{"Entity":{"atom":2}},{"Str":{"pattern":"Issue"}},{"Entity":{"atom":2}},{"Entity":{"atom":17}},{"Repetition":{"atom":335,"min":1,"max":null,"tag":"Repetition"}},{"Named":{"name":"issue","atom":336}},{"Sequence":{"atoms":[332,333,334,337]}},{"Entity":{"atom":2}},{"Str":{"pattern":"("}},{"Entity":{"atom":17}},{"Repetition":{"atom":341,"min":1,"max":null,"tag":"Repetition"}},{"Named":{"name":"issue","atom":342}},{"Str":{"pattern":")"}},{"Sequence":{"atoms":[339,340,343,344]}},{"Alternative":{"atoms":[338,345]}},{"Repetition":{"atom":331,"min":0,"max":1,"tag":"Maybe"}},{"Sequence":{"atoms":[325,326,327,330,347]}},{"Entity":{"atom":358}},{"Entity":{"atom":2}},{"Str":{"pattern":"19"}},{"Str":{"pattern":"20"}},{"Alternative":{"atoms":[351,352]}},{"Entity":{"atom":17}},{"Repetition":{"atom":354,"min":2,"max":null,"tag":"Repetition"}},{"Sequence":{"atoms":[353,355]}},{"Named":{"name":"volume","atom":356}},{"Sequence":{"atoms":[350,357]}},{"Alternative":{"atoms":[324,349]}},{"Entity":{"atom":92}},{"Repetition":{"atom":360,"min":0,"max":1,"tag":"Maybe"}},{"Sequence":{"atoms":[359,361]}},{"Repetition":{"atom":323,"min":0,"max":1,"tag":"Maybe"}},{"Entity":{"atom":135}},{"Repetition":{"atom":364,"min":0,"max":1,"tag":"Maybe"}},{"Sequence":{"atoms":[4,5,13,15,54,58,95,138,178,234,271,322,363,365]}}],"root":366},"bindings":[{"capture":"type","path":"type","type":"string","card":null,"preprocess":null},{"capture":"number","path":"number","type":"string","card":null,"preprocess":null},{"capture":"part","path":"part","type":"string","card":null,"preprocess":null},{"capture":"part_edition","path":"part_edition","type":"string","card":null,"preprocess":null},{"capture":"part_year","path":"part_year","type":"string","card":null,"preprocess":null},{"capture":"annex","path":"annex","type":"string","card":null,"preprocess":null},{"capture":"annex_edition","path":"annex_edition","type":"string","card":null,"preprocess":null},{"capture":"annex_year","path":"annex_year","type":"string","card":null,"preprocess":null},{"capture":"appendix","path":"appendix","type":"string","card":null,"preprocess":null},{"capture":"appendix_subnumber","path":"appendix_subnumber","type":"string","card":null,"preprocess":null},{"capture":"appendix_edition","path":"appendix_edition","type":"string","card":null,"preprocess":null},{"capture":"appendix_year","path":"appendix_year","type":"string","card":null,"preprocess":null},{"capture":"supplement","path":"supplement","type":"string","card":null,"preprocess":null},{"capture":"supplement_edition","path":"supplement_edition","type":"string","card":null,"preprocess":null},{"capture":"supplement_year","path":"supplement_year","type":"string","card":null,"preprocess":null},{"capture":"edition","path":"edition","type":"string","card":null,"preprocess":null},{"capture":"edition_shorthand","path":"edition_shorthand","type":"string","card":null,"preprocess":null},{"capture":"year","path":"year","type":"string","card":null,"preprocess":null},{"capture":"volume","path":"volume","type":"string","card":null,"preprocess":null},{"capture":"volume_edition","path":"volume_edition","type":"string","card":null,"preprocess":null},{"capture":"volume_year","path":"volume_year","type":"string","card":null,"preprocess":null},{"capture":"issue","path":"issue","type":"string","card":null,"preprocess":null}]}},"preprocess":{},"tables":{},"lint":{"order_warnings":["rule volume_issue: branches 1 and 2 are order-dependent (shared first bytes; ordered choice is decisive)"]},"default_entry":"identifier","render":{},"derive":{},"tests":[{"entry":"identifier","kind":"accept","input":"S-5","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO S-5 Appendix 2","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO B-12 3.0.0","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO P-5 2024","expect":{}},{"entry":"identifier","kind":"accept","input":"P-5 2024","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO P-5 Vol. 2024","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO P-5/2024","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO B-7 Vol. 2023","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO P-1 Vol. 30","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO P-1 Vol. 30 (2)","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO P-1 Vol. 30 Issue 2","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO P-1/21","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO P-1/21 1.0.0","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO S-100 5.0.0 Part 2","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO S-98 1.0.0 Part A","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO S-65 1.1.0 Annex A","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO S-122 1.0.0 Appendix D-2","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO S-52 4.0.0 Appendix 1","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO M-2 Sup 1","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO M-2 Suppl 6","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO S-66 2.0.0 Sup 4","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO S-5-B","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO S-100-1","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO S-100-1 1.0.0","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO P-6-3 1.0.0","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO S-5A","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO S-5A 1.0.2","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO S-5 1.0.2 Part A","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO S-100 5.0.0 Part 2 (2024)","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO S-100 v5.1","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO S-100 v1","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO S-100 1.0.0 (2024) Part A","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO S-53 Ap. 1 1.0.0","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO S-98 Part A 1.0.0","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO S-158:100 1.0.0","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO S-158:100 Part 2 1.0.0","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO S-1001","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO S-158 Part S-102 0.2.0","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO S-158-S-102 0.2.0","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO P-6 1.0.0 Vol. 2","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO P-6 Vol. 2 1.0.1","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO S-98 1.0.0 Annex A","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO S-100 5.0.0 Sup 1 2.0.0","expect":{}},{"entry":"identifier","kind":"reject","input":"nonsense","expect":{}},{"entry":"identifier","kind":"reject","input":"IHO B-12 3.0","expect":{}},{"entry":"identifier","kind":"reject","input":"IHO P-5 1850","expect":{}}],"docs":{},"source":"# Port of lib/pubid/iho/parser.rb — IHO identifiers: letter series\n# (S/P/M/B/C), a number with an optional suffix, and the full component\n# tail (edition, supplement, part, annex, appendix + subnumber, volume,\n# issue, year qualifier).\n#\n# == Component model (owner rulings, 2026-11-03)\n#\n# Every component below is a first-class semantic component: its own\n# named capture, its own typed binding, independently addressable in\n# the model, URN-encodable and matchable — never a regex/string suffix.\n#\n# component face capture binding type\n# edition x.y.z (bare) edition string\n# edition v1 / v5.1 (alias) edition_shorthand string (parse-only;\n# the builder pads to\n# x.y.0 — official IHO\n# edition is dotted\n# x.y.z WITHOUT a year)\n# supplement Sup N (Suppl N) supplement string\n# part Part X / Part S-102 part string (letter,\n# number, or SERIES\n# REFERENCE)\n# part -X / -S-102 (short) part string (hyphenated)\n# annex Annex A annex string\n# appendix Appendix B appendix string\n# appendix Appendix D-2 appendix_subnumber string (the -2)\n# volume Vol. N volume string\n# volume /N (short) volume string (the slash\n# chain, P-1/21 or\n# P-5/2020)\n# volume N (bare, legacy) volume string (the yearbook\n# year IS a volume —\n# one serial-locator\n# component)\n# issue (N) / Issue N issue string\n# year (2024) year string (the with-year\n# qualifier on\n# standards; NOT a\n# serial locator)\n#\n# == Component-edition duality (owner ruling: \"this can happen with any\n# independently publishable artifacts\")\n#\n# Supplement, part, annex, appendix and volume can be published on\n# their own publication cycle, so EACH carries an optional\n# `<kind>_edition` (+ `<kind>_year` qualifier) of its own, mutually\n# exclusive with the base edition context:\n#\n# within-edition: IHO P-6 1.0.0 Vol. 2 (the volume rides\n# the base's edition)\n# separately-published: IHO P-6 Vol. 2 1.0.1 (the volume carries\n# IHO S-98 Part A 1.0.0 its own edition;\n# IHO S-158 Part S-102 0.2.0 the base is\n# cited edition-less)\n#\n# In the URN the ed- segment attaches to the node it follows, so the\n# same positional slot records both modes.\n#\n# The part has a COMPACT face, hyphenated onto the code — `IHO S-5-B`\n# (lettered part), `IHO S-100-1` (numbered part), `IHO S-158-S-102`\n# (series-reference part) — which both parses and renders; the\n# canonical expanded face stays `IHO S-100 x.y.z Part 1`. Gluing a part\n# onto the code without a separator (S-5A) is DISALLOWED as a form: it\n# cannot extend to numbered parts without ambiguity (S-1001 = series\n# 1001 vs series 100 part 1). The four lettered bases the corpus\n# records (S-5A, S-5B, S-8A, S-8B) are LEGACY data spellings: they\n# still parse as aliases (S-5A == S-5 Part A) but are never rendered;\n# the owner rules later whether to reject them outright.\n#\n# Series-reference parts: a check standard applied to another IHO\n# series cites the applied series as its part — `IHO S-158 0.2.0 Part\n# S-102` (the wild glued `S-158-102` spelling is a legacy alias whose\n# normalization to Part S-102 needs an IHO series table; the syntax\n# alone cannot tell it from S-100-1 = Part 1, so it currently parses\n# as the plain number part).\n#\n# Two main syntaxes per the owner ruling: `IHO S-100 1.0.0` (dated =\n# edition-specific) and `IHO S-100` (undated = edition-non-specific).\n# A year beside an edition is the with-year variant qualifier\n# (`IHO S-100 1.0.0 Part X (2024)`), never a year-keyed docidentifier —\n# year-keyed docidentifiers for edition-keyed products are wrong. The\n# continuously-updated series have ONE serial locator, the volume:\n# P-1 and P-6 are volume-keyed (`IHO P-1 Vol. 30 (1)`), and the\n# yearbook year IS a volume (`IHO P-5 Vol. 2020`) — the bare year\n# (`IHO P-5 2020`) and all year-faced forms are parse-only legacy\n# aliases that bind into the volume component, never rendered.\n#\n# Aliases: \"Suppl\" (canonical face Sup, the M-2 spelling — why abbreviate\n# by two letters when Annex and Appendix stay full-length), \"App\"/\"Ap.\"\n# (canonical face Appendix), the hyphenated compact part face (S-5-B ==\n# S-5 Part B, S-100-1 == S-100 Part 1), the legacy glued lettered bases\n# (S-5A, parse-only), \"S-100 v1..v5.1\" (edition shorthand), \"Issue N\"\n# (canonical (N)), the bare year (canonical Vol. N).\n#\n# == URN segment grammar (positional, containment-ordered)\n#\n# The URN mirrors the containment tree, one semantic atom per segment:\n# Part contains Annexes; Annex contains Appendices; a D-2 subnumber is\n# a child atom of Appendix D. No key.value concatenations — every\n# non-number component is a marker-prefixed segment whose marker is the\n# lowercased human-face token (edition follows ISO's ed- precedent):\n#\n# urn:iho:<type>:<number>[:ed-<x.y.z>][:year-<yyyy>]\n# [:sup-<n>[:ed-<x.y.z>][:year-<yyyy>]]\n# [:part-<X>[:ed-<x.y.z>][:year-<yyyy>]]\n# [:annex-<A>[...]]\n# [:appendix-<B>[:<sub>][...]]\n# [:vol-<n>[:issue-<n>][...]]\n# [:year-<yyyy>]\n#\n# position segment value vocabulary containment\n# -------- --------------- -------------------------- ------------------\n# 1 <type> s / p / m / b / c namespace root\n# 2 <number> digits + : suffix; may document code\n# span bare segments until\n# the first marker\n# 3 ed-<x.y.z> dotted a.b.c edition qualifier;\n# 4 year-<yyyy> 19xx/20xx ATTACHES TO THE\n# NODE IT FOLLOWS: the\n# base (no component\n# before it) or the\n# component whose\n# segment precedes\n# 5 sup-<n> 1*digit wraps the base\n# 6 part-<X> letter (case kept), contains annexes\n# digits [*letter], or a\n# series reference\n# [SPMBC]-<digits>\n# 7 annex-<A> upper letter (case kept) contains appendices\n# 8 appendix-<B> upper letter or digits contains subnumber\n# 9 <sub> 1*digit, BARE, only child of appendix\n# directly after appendix-\n# 10 vol-<n> 1*digit (incl. yearbook contains issue\n# years, Vol. 2020)\n# 11 issue-<n> 1*digit, only after vol- child of volume\n#\n# The number occupies every leading bare segment up to the first\n# marker, so a colon number (S-158:100) round-trips without escaping;\n# after the markers the only bare segment allowed is the appendix\n# subnumber in its own slot. Both the year qualifier and the volume are\n# marker-tagged so neither can collide with a colon-number segment (the\n# #637 hazard, kept under the positional scheme). Letters are\n# case-preserved: part-A and part-a are distinct documents.\n#\n# Legacy 2.0.x spellings remain decodable but are never emitted: the\n# bare a.b.c segment (edition), the dotted keys part./annex./suppl./\n# ap./appendix./vol./issue. and the single-letter y. year tag (whose\n# value decodes into the volume — the serial-locator unification).\n#\n# Edition 2: ruby#400's capture-flatten keeps text captures over\n# reference-built rules as the matched text, so the v2 tree is the v1\n# tree plus named leaves for non-captured structure.\n\ngrammar PubidIho version \"0.2.0\" edition 2 {\n digit = %x30-39\n upper = %x41-5A\n lower = %x61-7A\n letter = upper / lower\n space = \" \"\n dash = \"-\"\n dot = \".\"\n\n series = (\"S\" / \"P\" / \"M\" / \"B\" / \"C\") as type\n number_suffix = (\":\" 1*digit)\n number = (1*digit [number_suffix]) as number\n # The compact part face, hyphenated onto the code: S-5-B (lettered),\n # S-100-1 (numbered) and S-158-S-102 (series reference) — the dash\n # replaces the old bare-glued suffix, so a number like S-1001 stays a\n # whole number (the dash is what makes the part unambiguous). The\n # dash is an inlined literal: a named dash ref here collides with the\n # sequence's own dash node in the edition-2 tree.\n compact_part = \"-\" (((\"S\" / \"P\" / \"M\" / \"B\" / \"C\") dash (1*digit)) / (1*digit [*letter]) / upper) as part\n # LEGACY glued lettered bases (S-5A, S-5B, S-8A, S-8B in the corpus):\n # parse-only aliases, never rendered. Kept because the records exist;\n # the owner rules later whether to reject them.\n glued = upper as part\n\n # The official edition is the dotted x.y.z; \"v1\"/\"v5.1\" is the S-100\n # shorthand (parse-only, the builder pads to x.y.0).\n edition = space (1*digit dot 1*digit dot 1*digit) as edition\n v_edition = space \"v\" ((1*digit) [\".\" (1*digit)]) as edition_shorthand\n # The with-year qualifier on standards: a parenthesized year beside an\n # edition. This is the ONLY base-level year capture — periodical\n # years are volumes (the serial-locator unification).\n year_qualifier = space \"(\" ((\"19\" / \"20\") 2*digit) as year \")\"\n\n # The series-reference part value: a check standard applied to\n # another IHO series (S-158 checks S-102). Ordered FIRST so \"Part\n # S-102\" takes the series-reference branch, not the lone letter.\n part_series_ref = ((\"S\" / \"P\" / \"M\" / \"B\" / \"C\") dash (1*digit))\n part_value = (part_series_ref / (1*digit [*letter]) / upper) as part\n\n # Component-edition duality: each independently-publishable component\n # may carry its own edition (+ year qualifier), mutually exclusive\n # with the base edition context. The captures are position-scoped\n # (<kind>_edition / <kind>_year) so the model knows which component\n # the edition belongs to and the URN attaches ed- to the node it\n # follows.\n part = space \"Part\" space part_value [part_dated]\n part_dated = {\n part_edition_rule\n [part_year_rule]\n }\n part_edition_rule = space (1*digit dot 1*digit dot 1*digit) as part_edition\n part_year_rule = space \"(\" ((\"19\" / \"20\") 2*digit) as part_year \")\"\n\n supplement = space (\"Suppl\" / \"Sup\") space (1*digit) as supplement [supplement_dated]\n supplement_dated = {\n supplement_edition_rule\n [supplement_year_rule]\n }\n supplement_edition_rule = space (1*digit dot 1*digit dot 1*digit) as supplement_edition\n supplement_year_rule = space \"(\" ((\"19\" / \"20\") 2*digit) as supplement_year \")\"\n\n annex = space \"Annex\" space upper as annex [annex_dated]\n annex_dated = {\n annex_edition_rule\n [annex_year_rule]\n }\n annex_edition_rule = space (1*digit dot 1*digit dot 1*digit) as annex_edition\n annex_year_rule = space \"(\" ((\"19\" / \"20\") 2*digit) as annex_year \")\"\n\n appendix_value = (upper / (1*digit)) as appendix\n appendix_subnumber = dash (1*digit) as appendix_subnumber\n appendix = space (\"Appendix\" / \"App\" / \"Ap.\") space appendix_value [appendix_subnumber] [appendix_dated]\n appendix_dated = {\n appendix_edition_rule\n [appendix_year_rule]\n }\n appendix_edition_rule = space (1*digit dot 1*digit dot 1*digit) as appendix_edition\n appendix_year_rule = space \"(\" ((\"19\" / \"20\") 2*digit) as appendix_year \")\"\n\n volume = space \"Vol.\" space (1*digit) as volume [volume_issue]\n volume_issue = (space \"Issue\" space (1*digit) as issue) / (space \"(\" (1*digit) as issue \")\")\n # The volume's short face — the slash chain (\"IHO P-1/21\",\n # \"IHO P-5/2020\"). The slash no longer joins the number.\n volume_short = \"/\" ((1*digit) as volume) [volume_dated]\n # LEGACY bare year (\"IHO P-5 2024\"): the yearbook year IS a volume,\n # so a bare year binds INTO the volume component. Parse-only alias;\n # the canonical print is \"Vol. N\".\n volume_bare_year = space ((\"19\" / \"20\") 2*digit) as volume\n # The volume's own edition (+ year), shared by the Vol. and slash\n # forms.\n volume_dated = {\n volume_edition_rule\n [volume_year_rule]\n }\n volume_edition_rule = space (1*digit dot 1*digit dot 1*digit) as volume_edition\n volume_year_rule = space \"(\" ((\"19\" / \"20\") 2*digit) as volume_year \")\"\n\n # The edition slot accepts the dotted form or the v-shorthand; the\n # with-year qualifier may sit right after it.\n dated = {\n (edition / v_edition)\n [year_qualifier]\n }\n\n # The serial tail picks exactly one discriminator: the long volume\n # (with its optional issue) or the legacy bare year — both bind the\n # volume component, and both may carry the volume's own edition.\n serial = {\n (volume / volume_bare_year)\n [volume_dated]\n }\n\n identifier = {\n [(\"IHO\" space)]\n series\n dash\n number\n [compact_part]\n [glued]\n [volume_short]\n [dated]\n [supplement]\n [part]\n [annex]\n [appendix]\n [serial]\n [year_qualifier]\n }\n\n entry identifier: identifier\n\n test {\n accept \"S-5\"\n accept \"IHO S-5 Appendix 2\"\n accept \"IHO B-12 3.0.0\"\n accept \"IHO P-5 2024\"\n accept \"P-5 2024\"\n accept \"IHO P-5 Vol. 2024\"\n accept \"IHO P-5/2024\"\n accept \"IHO B-7 Vol. 2023\"\n accept \"IHO P-1 Vol. 30\"\n accept \"IHO P-1 Vol. 30 (2)\"\n accept \"IHO P-1 Vol. 30 Issue 2\"\n accept \"IHO P-1/21\"\n accept \"IHO P-1/21 1.0.0\"\n accept \"IHO S-100 5.0.0 Part 2\"\n accept \"IHO S-98 1.0.0 Part A\"\n accept \"IHO S-65 1.1.0 Annex A\"\n accept \"IHO S-122 1.0.0 Appendix D-2\"\n accept \"IHO S-52 4.0.0 Appendix 1\"\n accept \"IHO M-2 Sup 1\"\n accept \"IHO M-2 Suppl 6\"\n accept \"IHO S-66 2.0.0 Sup 4\"\n accept \"IHO S-5-B\"\n accept \"IHO S-100-1\"\n accept \"IHO S-100-1 1.0.0\"\n accept \"IHO P-6-3 1.0.0\"\n accept \"IHO S-5A\"\n accept \"IHO S-5A 1.0.2\"\n accept \"IHO S-5 1.0.2 Part A\"\n accept \"IHO S-100 5.0.0 Part 2 (2024)\"\n accept \"IHO S-100 v5.1\"\n accept \"IHO S-100 v1\"\n accept \"IHO S-100 1.0.0 (2024) Part A\"\n accept \"IHO S-53 Ap. 1 1.0.0\"\n accept \"IHO S-98 Part A 1.0.0\"\n accept \"IHO S-158:100 1.0.0\"\n accept \"IHO S-158:100 Part 2 1.0.0\"\n accept \"IHO S-1001\"\n accept \"IHO S-158 Part S-102 0.2.0\"\n accept \"IHO S-158-S-102 0.2.0\"\n accept \"IHO P-6 1.0.0 Vol. 2\"\n accept \"IHO P-6 Vol. 2 1.0.1\"\n accept \"IHO S-98 1.0.0 Annex A\"\n accept \"IHO S-100 5.0.0 Sup 1 2.0.0\"\n reject \"nonsense\"\n reject \"IHO B-12 3.0\"\n reject \"IHO P-5 1850\"\n }\n\n bindings identifier {\n type -> type (string)\n number -> number (string)\n part -> part (string)\n part_edition -> part_edition (string)\n part_year -> part_year (string)\n annex -> annex (string)\n annex_edition -> annex_edition (string)\n annex_year -> annex_year (string)\n appendix -> appendix (string)\n appendix_subnumber -> appendix_subnumber (string)\n appendix_edition -> appendix_edition (string)\n appendix_year -> appendix_year (string)\n supplement -> supplement (string)\n supplement_edition -> supplement_edition (string)\n supplement_year -> supplement_year (string)\n edition -> edition (string)\n edition_shorthand -> edition_shorthand (string)\n year -> year (string)\n volume -> volume (string)\n volume_edition -> volume_edition (string)\n volume_year -> volume_year (string)\n issue -> issue (string)\n }\n}\n","source_hash":"66d50de135e5c416bfe003de604effff57ed3b556a7126262c449b5c850995ac","unicode_tables":"onigmo (Ruby 3.4.8)","compiler_version":"1.3.126","edition":2,"semantics_hash":"sha256:711b011976f08ffc691672fafa41f9b60e3f6024a2608451043836fd6d05eff0","checksum":"sha256:15324490896b11703cb63893072ed77fbc43f43e47dd166ae8ddb235e3c2202e"}
|
|
1
|
+
{"bindings":null,"version":"0.3.0","grammar":"PubidIho","shape":"parsanol-tree/v2","binding_version":1,"entries":{"identifier":{"root":"identifier_entry","grammar":{"atoms":[{"Entity":{"atom":41}},{"Str":{"pattern":"IHO"}},{"Entity":{"atom":3}},{"Str":{"pattern":" "}},{"Sequence":{"atoms":[1,2]}},{"Repetition":{"atom":4,"min":0,"max":1,"tag":"Maybe"}},{"Str":{"pattern":"B"}},{"Named":{"name":"spec_part","atom":6}},{"Entity":{"atom":9}},{"Str":{"pattern":"-"}},{"Entity":{"atom":23}},{"Entity":{"atom":22}},{"Str":{"pattern":"1"}},{"Str":{"pattern":"2"}},{"Str":{"pattern":"3"}},{"Str":{"pattern":"4"}},{"Str":{"pattern":"5"}},{"Str":{"pattern":"6"}},{"Alternative":{"atoms":[12,13,14,15,16,17]}},{"Entity":{"atom":20}},{"Re":{"pattern":"[\\x30-\\x39]"}},{"Entity":{"atom":20}},{"Sequence":{"atoms":[18,19,21]}},{"Named":{"name":"spec","atom":11}},{"Entity":{"atom":30}},{"Entity":{"atom":26}},{"Str":{"pattern":"."}},{"Entity":{"atom":20}},{"Repetition":{"atom":27,"min":1,"max":null,"tag":"Repetition"}},{"Named":{"name":"spec_sub","atom":28}},{"Sequence":{"atoms":[25,29]}},{"Repetition":{"atom":24,"min":0,"max":1,"tag":"Maybe"}},{"Entity":{"atom":39}},{"Str":{"pattern":"("}},{"Entity":{"atom":35}},{"Re":{"pattern":"[\\x41-\\x5a]"}},{"Repetition":{"atom":34,"min":1,"max":null,"tag":"Repetition"}},{"Named":{"name":"spec_variant","atom":36}},{"Str":{"pattern":")"}},{"Sequence":{"atoms":[33,37,38]}},{"Repetition":{"atom":32,"min":0,"max":1,"tag":"Maybe"}},{"Sequence":{"atoms":[5,7,8,10,31,40]}},{"Entity":{"atom":435}},{"Str":{"pattern":"IHO"}},{"Entity":{"atom":3}},{"Sequence":{"atoms":[43,44]}},{"Repetition":{"atom":45,"min":0,"max":1,"tag":"Maybe"}},{"Entity":{"atom":54}},{"Str":{"pattern":"S"}},{"Str":{"pattern":"P"}},{"Str":{"pattern":"M"}},{"Str":{"pattern":"B"}},{"Str":{"pattern":"C"}},{"Alternative":{"atoms":[48,49,50,51,52]}},{"Named":{"name":"type","atom":53}},{"Entity":{"atom":9}},{"Entity":{"atom":66}},{"Entity":{"atom":20}},{"Repetition":{"atom":57,"min":1,"max":null,"tag":"Repetition"}},{"Entity":{"atom":63}},{"Str":{"pattern":":"}},{"Entity":{"atom":20}},{"Repetition":{"atom":61,"min":1,"max":null,"tag":"Repetition"}},{"Sequence":{"atoms":[60,62]}},{"Repetition":{"atom":59,"min":0,"max":1,"tag":"Maybe"}},{"Sequence":{"atoms":[58,64]}},{"Named":{"name":"number","atom":65}},{"Entity":{"atom":92}},{"Str":{"pattern":"-"}},{"Str":{"pattern":"S"}},{"Str":{"pattern":"P"}},{"Str":{"pattern":"M"}},{"Str":{"pattern":"B"}},{"Str":{"pattern":"C"}},{"Alternative":{"atoms":[69,70,71,72,73]}},{"Entity":{"atom":9}},{"Entity":{"atom":20}},{"Repetition":{"atom":76,"min":1,"max":null,"tag":"Repetition"}},{"Sequence":{"atoms":[74,75,77]}},{"Entity":{"atom":20}},{"Repetition":{"atom":79,"min":1,"max":null,"tag":"Repetition"}},{"Entity":{"atom":85}},{"Entity":{"atom":35}},{"Entity":{"atom":84}},{"Re":{"pattern":"[\\x61-\\x7a]"}},{"Alternative":{"atoms":[82,83]}},{"Repetition":{"atom":81,"min":0,"max":null,"tag":"Repetition"}},{"Repetition":{"atom":86,"min":0,"max":1,"tag":"Maybe"}},{"Sequence":{"atoms":[80,87]}},{"Entity":{"atom":35}},{"Alternative":{"atoms":[78,88,89]}},{"Named":{"name":"part","atom":90}},{"Sequence":{"atoms":[68,91]}},{"Repetition":{"atom":67,"min":0,"max":1,"tag":"Maybe"}},{"Entity":{"atom":96}},{"Entity":{"atom":35}},{"Named":{"name":"part","atom":95}},{"Repetition":{"atom":94,"min":0,"max":1,"tag":"Maybe"}},{"Entity":{"atom":132}},{"Str":{"pattern":"/"}},{"Entity":{"atom":20}},{"Repetition":{"atom":100,"min":1,"max":null,"tag":"Repetition"}},{"Named":{"name":"volume","atom":101}},{"Entity":{"atom":130}},{"Entity":{"atom":116}},{"Entity":{"atom":3}},{"Entity":{"atom":20}},{"Repetition":{"atom":106,"min":1,"max":null,"tag":"Repetition"}},{"Entity":{"atom":26}},{"Entity":{"atom":20}},{"Repetition":{"atom":109,"min":1,"max":null,"tag":"Repetition"}},{"Entity":{"atom":26}},{"Entity":{"atom":20}},{"Repetition":{"atom":112,"min":1,"max":null,"tag":"Repetition"}},{"Sequence":{"atoms":[107,108,110,111,113]}},{"Named":{"name":"volume_edition","atom":114}},{"Sequence":{"atoms":[105,115]}},{"Entity":{"atom":128}},{"Entity":{"atom":3}},{"Str":{"pattern":"("}},{"Str":{"pattern":"19"}},{"Str":{"pattern":"20"}},{"Alternative":{"atoms":[120,121]}},{"Entity":{"atom":20}},{"Repetition":{"atom":123,"min":2,"max":null,"tag":"Repetition"}},{"Sequence":{"atoms":[122,124]}},{"Named":{"name":"volume_year","atom":125}},{"Str":{"pattern":")"}},{"Sequence":{"atoms":[118,119,126,127]}},{"Repetition":{"atom":117,"min":0,"max":1,"tag":"Maybe"}},{"Sequence":{"atoms":[104,129]}},{"Repetition":{"atom":103,"min":0,"max":1,"tag":"Maybe"}},{"Sequence":{"atoms":[99,102,131]}},{"Repetition":{"atom":98,"min":0,"max":1,"tag":"Maybe"}},{"Entity":{"atom":175}},{"Entity":{"atom":147}},{"Entity":{"atom":3}},{"Entity":{"atom":20}},{"Repetition":{"atom":137,"min":1,"max":null,"tag":"Repetition"}},{"Entity":{"atom":26}},{"Entity":{"atom":20}},{"Repetition":{"atom":140,"min":1,"max":null,"tag":"Repetition"}},{"Entity":{"atom":26}},{"Entity":{"atom":20}},{"Repetition":{"atom":143,"min":1,"max":null,"tag":"Repetition"}},{"Sequence":{"atoms":[138,139,141,142,144]}},{"Named":{"name":"edition","atom":145}},{"Sequence":{"atoms":[136,146]}},{"Entity":{"atom":160}},{"Entity":{"atom":3}},{"Str":{"pattern":"v"}},{"Entity":{"atom":20}},{"Repetition":{"atom":151,"min":1,"max":null,"tag":"Repetition"}},{"Str":{"pattern":"."}},{"Entity":{"atom":20}},{"Repetition":{"atom":154,"min":1,"max":null,"tag":"Repetition"}},{"Sequence":{"atoms":[153,155]}},{"Repetition":{"atom":156,"min":0,"max":1,"tag":"Maybe"}},{"Sequence":{"atoms":[152,157]}},{"Named":{"name":"edition_shorthand","atom":158}},{"Sequence":{"atoms":[149,150,159]}},{"Alternative":{"atoms":[135,148]}},{"Entity":{"atom":173}},{"Entity":{"atom":3}},{"Str":{"pattern":"("}},{"Str":{"pattern":"19"}},{"Str":{"pattern":"20"}},{"Alternative":{"atoms":[165,166]}},{"Entity":{"atom":20}},{"Repetition":{"atom":168,"min":2,"max":null,"tag":"Repetition"}},{"Sequence":{"atoms":[167,169]}},{"Named":{"name":"year","atom":170}},{"Str":{"pattern":")"}},{"Sequence":{"atoms":[163,164,171,172]}},{"Repetition":{"atom":162,"min":0,"max":1,"tag":"Maybe"}},{"Sequence":{"atoms":[161,174]}},{"Repetition":{"atom":134,"min":0,"max":1,"tag":"Maybe"}},{"Entity":{"atom":215}},{"Entity":{"atom":3}},{"Str":{"pattern":"Suppl"}},{"Str":{"pattern":"Sup"}},{"Alternative":{"atoms":[179,180]}},{"Entity":{"atom":3}},{"Entity":{"atom":20}},{"Repetition":{"atom":183,"min":1,"max":null,"tag":"Repetition"}},{"Named":{"name":"supplement","atom":184}},{"Entity":{"atom":213}},{"Entity":{"atom":199}},{"Entity":{"atom":3}},{"Entity":{"atom":20}},{"Repetition":{"atom":189,"min":1,"max":null,"tag":"Repetition"}},{"Entity":{"atom":26}},{"Entity":{"atom":20}},{"Repetition":{"atom":192,"min":1,"max":null,"tag":"Repetition"}},{"Entity":{"atom":26}},{"Entity":{"atom":20}},{"Repetition":{"atom":195,"min":1,"max":null,"tag":"Repetition"}},{"Sequence":{"atoms":[190,191,193,194,196]}},{"Named":{"name":"supplement_edition","atom":197}},{"Sequence":{"atoms":[188,198]}},{"Entity":{"atom":211}},{"Entity":{"atom":3}},{"Str":{"pattern":"("}},{"Str":{"pattern":"19"}},{"Str":{"pattern":"20"}},{"Alternative":{"atoms":[203,204]}},{"Entity":{"atom":20}},{"Repetition":{"atom":206,"min":2,"max":null,"tag":"Repetition"}},{"Sequence":{"atoms":[205,207]}},{"Named":{"name":"supplement_year","atom":208}},{"Str":{"pattern":")"}},{"Sequence":{"atoms":[201,202,209,210]}},{"Repetition":{"atom":200,"min":0,"max":1,"tag":"Maybe"}},{"Sequence":{"atoms":[187,212]}},{"Repetition":{"atom":186,"min":0,"max":1,"tag":"Maybe"}},{"Sequence":{"atoms":[178,181,182,185,214]}},{"Repetition":{"atom":177,"min":0,"max":1,"tag":"Maybe"}},{"Entity":{"atom":297}},{"Entity":{"atom":3}},{"Str":{"pattern":"Part"}},{"Entity":{"atom":3}},{"Entity":{"atom":241}},{"Entity":{"atom":232}},{"Str":{"pattern":"S"}},{"Str":{"pattern":"P"}},{"Str":{"pattern":"M"}},{"Str":{"pattern":"B"}},{"Str":{"pattern":"C"}},{"Alternative":{"atoms":[223,224,225,226,227]}},{"Entity":{"atom":9}},{"Entity":{"atom":20}},{"Repetition":{"atom":230,"min":1,"max":null,"tag":"Repetition"}},{"Sequence":{"atoms":[228,229,231]}},{"Entity":{"atom":20}},{"Repetition":{"atom":233,"min":1,"max":null,"tag":"Repetition"}},{"Entity":{"atom":85}},{"Repetition":{"atom":235,"min":0,"max":null,"tag":"Repetition"}},{"Repetition":{"atom":236,"min":0,"max":1,"tag":"Maybe"}},{"Sequence":{"atoms":[234,237]}},{"Entity":{"atom":35}},{"Alternative":{"atoms":[222,238,239]}},{"Named":{"name":"part","atom":240}},{"Entity":{"atom":269}},{"Entity":{"atom":255}},{"Entity":{"atom":3}},{"Entity":{"atom":20}},{"Repetition":{"atom":245,"min":1,"max":null,"tag":"Repetition"}},{"Entity":{"atom":26}},{"Entity":{"atom":20}},{"Repetition":{"atom":248,"min":1,"max":null,"tag":"Repetition"}},{"Entity":{"atom":26}},{"Entity":{"atom":20}},{"Repetition":{"atom":251,"min":1,"max":null,"tag":"Repetition"}},{"Sequence":{"atoms":[246,247,249,250,252]}},{"Named":{"name":"part_edition","atom":253}},{"Sequence":{"atoms":[244,254]}},{"Entity":{"atom":267}},{"Entity":{"atom":3}},{"Str":{"pattern":"("}},{"Str":{"pattern":"19"}},{"Str":{"pattern":"20"}},{"Alternative":{"atoms":[259,260]}},{"Entity":{"atom":20}},{"Repetition":{"atom":262,"min":2,"max":null,"tag":"Repetition"}},{"Sequence":{"atoms":[261,263]}},{"Named":{"name":"part_year","atom":264}},{"Str":{"pattern":")"}},{"Sequence":{"atoms":[257,258,265,266]}},{"Repetition":{"atom":256,"min":0,"max":1,"tag":"Maybe"}},{"Sequence":{"atoms":[243,268]}},{"Repetition":{"atom":242,"min":0,"max":1,"tag":"Maybe"}},{"Entity":{"atom":295}},{"Str":{"pattern":","}},{"Entity":{"atom":3}},{"Str":{"pattern":"Section"}},{"Entity":{"atom":3}},{"Entity":{"atom":22}},{"Named":{"name":"spec_section","atom":276}},{"Str":{"pattern":","}},{"Entity":{"atom":3}},{"Entity":{"atom":292}},{"Str":{"pattern":"A"}},{"Str":{"pattern":"B"}},{"Str":{"pattern":"C"}},{"Alternative":{"atoms":[281,282,283]}},{"Named":{"name":"spec_part","atom":284}},{"Entity":{"atom":9}},{"Entity":{"atom":23}},{"Entity":{"atom":30}},{"Repetition":{"atom":288,"min":0,"max":1,"tag":"Maybe"}},{"Entity":{"atom":39}},{"Repetition":{"atom":290,"min":0,"max":1,"tag":"Maybe"}},{"Sequence":{"atoms":[285,286,287,289,291]}},{"Sequence":{"atoms":[278,279,280]}},{"Repetition":{"atom":293,"min":0,"max":1,"tag":"Maybe"}},{"Sequence":{"atoms":[272,273,274,275,277,294]}},{"Repetition":{"atom":271,"min":0,"max":1,"tag":"Maybe"}},{"Sequence":{"atoms":[218,219,220,221,270,296]}},{"Repetition":{"atom":217,"min":0,"max":1,"tag":"Maybe"}},{"Entity":{"atom":302}},{"Entity":{"atom":3}},{"Entity":{"atom":292}},{"Sequence":{"atoms":[300,301]}},{"Repetition":{"atom":299,"min":0,"max":1,"tag":"Maybe"}},{"Entity":{"atom":339}},{"Entity":{"atom":3}},{"Str":{"pattern":"Annex"}},{"Entity":{"atom":3}},{"Entity":{"atom":35}},{"Named":{"name":"annex","atom":308}},{"Entity":{"atom":337}},{"Entity":{"atom":323}},{"Entity":{"atom":3}},{"Entity":{"atom":20}},{"Repetition":{"atom":313,"min":1,"max":null,"tag":"Repetition"}},{"Entity":{"atom":26}},{"Entity":{"atom":20}},{"Repetition":{"atom":316,"min":1,"max":null,"tag":"Repetition"}},{"Entity":{"atom":26}},{"Entity":{"atom":20}},{"Repetition":{"atom":319,"min":1,"max":null,"tag":"Repetition"}},{"Sequence":{"atoms":[314,315,317,318,320]}},{"Named":{"name":"annex_edition","atom":321}},{"Sequence":{"atoms":[312,322]}},{"Entity":{"atom":335}},{"Entity":{"atom":3}},{"Str":{"pattern":"("}},{"Str":{"pattern":"19"}},{"Str":{"pattern":"20"}},{"Alternative":{"atoms":[327,328]}},{"Entity":{"atom":20}},{"Repetition":{"atom":330,"min":2,"max":null,"tag":"Repetition"}},{"Sequence":{"atoms":[329,331]}},{"Named":{"name":"annex_year","atom":332}},{"Str":{"pattern":")"}},{"Sequence":{"atoms":[325,326,333,334]}},{"Repetition":{"atom":324,"min":0,"max":1,"tag":"Maybe"}},{"Sequence":{"atoms":[311,336]}},{"Repetition":{"atom":310,"min":0,"max":1,"tag":"Maybe"}},{"Sequence":{"atoms":[305,306,307,309,338]}},{"Repetition":{"atom":304,"min":0,"max":1,"tag":"Maybe"}},{"Entity":{"atom":390}},{"Entity":{"atom":3}},{"Str":{"pattern":"Appendix"}},{"Str":{"pattern":"App"}},{"Str":{"pattern":"Ap."}},{"Alternative":{"atoms":[343,344,345]}},{"Entity":{"atom":3}},{"Entity":{"atom":353}},{"Entity":{"atom":35}},{"Entity":{"atom":20}},{"Repetition":{"atom":350,"min":1,"max":null,"tag":"Repetition"}},{"Alternative":{"atoms":[349,351]}},{"Named":{"name":"appendix","atom":352}},{"Entity":{"atom":359}},{"Entity":{"atom":9}},{"Entity":{"atom":20}},{"Repetition":{"atom":356,"min":1,"max":null,"tag":"Repetition"}},{"Named":{"name":"appendix_subnumber","atom":357}},{"Sequence":{"atoms":[355,358]}},{"Repetition":{"atom":354,"min":0,"max":1,"tag":"Maybe"}},{"Entity":{"atom":388}},{"Entity":{"atom":374}},{"Entity":{"atom":3}},{"Entity":{"atom":20}},{"Repetition":{"atom":364,"min":1,"max":null,"tag":"Repetition"}},{"Entity":{"atom":26}},{"Entity":{"atom":20}},{"Repetition":{"atom":367,"min":1,"max":null,"tag":"Repetition"}},{"Entity":{"atom":26}},{"Entity":{"atom":20}},{"Repetition":{"atom":370,"min":1,"max":null,"tag":"Repetition"}},{"Sequence":{"atoms":[365,366,368,369,371]}},{"Named":{"name":"appendix_edition","atom":372}},{"Sequence":{"atoms":[363,373]}},{"Entity":{"atom":386}},{"Entity":{"atom":3}},{"Str":{"pattern":"("}},{"Str":{"pattern":"19"}},{"Str":{"pattern":"20"}},{"Alternative":{"atoms":[378,379]}},{"Entity":{"atom":20}},{"Repetition":{"atom":381,"min":2,"max":null,"tag":"Repetition"}},{"Sequence":{"atoms":[380,382]}},{"Named":{"name":"appendix_year","atom":383}},{"Str":{"pattern":")"}},{"Sequence":{"atoms":[376,377,384,385]}},{"Repetition":{"atom":375,"min":0,"max":1,"tag":"Maybe"}},{"Sequence":{"atoms":[362,387]}},{"Repetition":{"atom":361,"min":0,"max":1,"tag":"Maybe"}},{"Sequence":{"atoms":[342,346,347,348,360,389]}},{"Repetition":{"atom":341,"min":0,"max":1,"tag":"Maybe"}},{"Entity":{"atom":431}},{"Entity":{"atom":417}},{"Entity":{"atom":3}},{"Str":{"pattern":"Vol."}},{"Entity":{"atom":3}},{"Entity":{"atom":20}},{"Repetition":{"atom":397,"min":1,"max":null,"tag":"Repetition"}},{"Named":{"name":"volume","atom":398}},{"Entity":{"atom":415}},{"Entity":{"atom":3}},{"Str":{"pattern":"Issue"}},{"Entity":{"atom":3}},{"Entity":{"atom":20}},{"Repetition":{"atom":404,"min":1,"max":null,"tag":"Repetition"}},{"Named":{"name":"issue","atom":405}},{"Sequence":{"atoms":[401,402,403,406]}},{"Entity":{"atom":3}},{"Str":{"pattern":"("}},{"Entity":{"atom":20}},{"Repetition":{"atom":410,"min":1,"max":null,"tag":"Repetition"}},{"Named":{"name":"issue","atom":411}},{"Str":{"pattern":")"}},{"Sequence":{"atoms":[408,409,412,413]}},{"Alternative":{"atoms":[407,414]}},{"Repetition":{"atom":400,"min":0,"max":1,"tag":"Maybe"}},{"Sequence":{"atoms":[394,395,396,399,416]}},{"Entity":{"atom":427}},{"Entity":{"atom":3}},{"Str":{"pattern":"19"}},{"Str":{"pattern":"20"}},{"Alternative":{"atoms":[420,421]}},{"Entity":{"atom":20}},{"Repetition":{"atom":423,"min":2,"max":null,"tag":"Repetition"}},{"Sequence":{"atoms":[422,424]}},{"Named":{"name":"volume","atom":425}},{"Sequence":{"atoms":[419,426]}},{"Alternative":{"atoms":[393,418]}},{"Entity":{"atom":130}},{"Repetition":{"atom":429,"min":0,"max":1,"tag":"Maybe"}},{"Sequence":{"atoms":[428,430]}},{"Repetition":{"atom":392,"min":0,"max":1,"tag":"Maybe"}},{"Entity":{"atom":173}},{"Repetition":{"atom":433,"min":0,"max":1,"tag":"Maybe"}},{"Sequence":{"atoms":[46,47,55,56,93,97,133,176,216,298,303,340,391,432,434]}},{"Alternative":{"atoms":[0,42]}}],"root":436},"bindings":[{"capture":"type","path":"type","type":"string","card":null,"preprocess":null},{"capture":"number","path":"number","type":"string","card":null,"preprocess":null},{"capture":"part","path":"part","type":"string","card":null,"preprocess":null},{"capture":"part_edition","path":"part_edition","type":"string","card":null,"preprocess":null},{"capture":"part_year","path":"part_year","type":"string","card":null,"preprocess":null},{"capture":"annex","path":"annex","type":"string","card":null,"preprocess":null},{"capture":"annex_edition","path":"annex_edition","type":"string","card":null,"preprocess":null},{"capture":"annex_year","path":"annex_year","type":"string","card":null,"preprocess":null},{"capture":"appendix","path":"appendix","type":"string","card":null,"preprocess":null},{"capture":"appendix_subnumber","path":"appendix_subnumber","type":"string","card":null,"preprocess":null},{"capture":"appendix_edition","path":"appendix_edition","type":"string","card":null,"preprocess":null},{"capture":"appendix_year","path":"appendix_year","type":"string","card":null,"preprocess":null},{"capture":"supplement","path":"supplement","type":"string","card":null,"preprocess":null},{"capture":"supplement_edition","path":"supplement_edition","type":"string","card":null,"preprocess":null},{"capture":"supplement_year","path":"supplement_year","type":"string","card":null,"preprocess":null},{"capture":"edition","path":"edition","type":"string","card":null,"preprocess":null},{"capture":"edition_shorthand","path":"edition_shorthand","type":"string","card":null,"preprocess":null},{"capture":"year","path":"year","type":"string","card":null,"preprocess":null},{"capture":"volume","path":"volume","type":"string","card":null,"preprocess":null},{"capture":"volume_edition","path":"volume_edition","type":"string","card":null,"preprocess":null},{"capture":"volume_year","path":"volume_year","type":"string","card":null,"preprocess":null},{"capture":"issue","path":"issue","type":"string","card":null,"preprocess":null},{"capture":"spec","path":"spec","type":"string","card":null,"preprocess":null},{"capture":"spec_sub","path":"spec_sub","type":"string","card":null,"preprocess":null},{"capture":"spec_variant","path":"spec_variant","type":"string","card":null,"preprocess":null},{"capture":"spec_part","path":"spec_part","type":"string","card":null,"preprocess":null},{"capture":"spec_section","path":"spec_section","type":"string","card":null,"preprocess":null}]}},"preprocess":{},"tables":{},"lint":{"order_warnings":["rule volume_issue: branches 1 and 2 are order-dependent (shared first bytes; ordered choice is decisive)","rule identifier_entry: branches 1 and 2 are order-dependent (shared first bytes; ordered choice is decisive)"]},"default_entry":"identifier","render":{},"derive":{},"tests":[{"entry":"identifier","kind":"accept","input":"S-5","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO S-5 Appendix 2","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO B-12 3.0.0","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO P-5 2024","expect":{}},{"entry":"identifier","kind":"accept","input":"P-5 2024","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO P-5 Vol. 2024","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO P-5/2024","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO B-7 Vol. 2023","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO P-1 Vol. 30","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO P-1 Vol. 30 (2)","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO P-1 Vol. 30 Issue 2","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO P-1/21","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO P-1/21 1.0.0","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO S-100 5.0.0 Part 2","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO S-98 1.0.0 Part A","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO S-65 1.1.0 Annex A","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO S-122 1.0.0 Appendix D-2","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO S-52 4.0.0 Appendix 1","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO M-2 Sup 1","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO M-2 Suppl 6","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO S-66 2.0.0 Sup 4","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO S-5-B","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO S-100-1","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO S-100-1 1.0.0","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO P-6-3 1.0.0","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO S-5A","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO S-5A 1.0.2","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO S-5 1.0.2 Part A","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO S-100 5.0.0 Part 2 (2024)","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO S-100 v5.1","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO S-100 v1","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO S-100 1.0.0 (2024) Part A","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO S-53 Ap. 1 1.0.0","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO S-98 Part A 1.0.0","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO S-158:100 1.0.0","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO S-158:100 Part 2 1.0.0","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO S-1001","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO S-158 Part S-102 0.2.0","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO S-158-S-102 0.2.0","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO P-6 1.0.0 Vol. 2","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO P-6 Vol. 2 1.0.1","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO S-98 1.0.0 Annex A","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO S-100 5.0.0 Sup 1 2.0.0","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO S-4 B-401","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO S-4 4.10.0 B-401","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO S-4 B-122.1","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO S-4 B-521(I)","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO S-4 B-351.1(I)","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO S-4 B-400","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO S-4 B-170","expect":{}},{"entry":"identifier","kind":"accept","input":"B-401","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO B-401","expect":{}},{"entry":"identifier","kind":"accept","input":"B-122.1","expect":{}},{"entry":"identifier","kind":"accept","input":"B-521(I)","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO S-4 Part B, Section 400","expect":{}},{"entry":"identifier","kind":"accept","input":"S-4 Part B, Section 400","expect":{}},{"entry":"identifier","kind":"accept","input":"IHO S-4 Part B, Section 400, B-401","expect":{}},{"entry":"identifier","kind":"accept","input":"B-12","expect":{}},{"entry":"identifier","kind":"reject","input":"IHO S-4 B-4","expect":{}},{"entry":"identifier","kind":"reject","input":"IHO S-4 B-40","expect":{}},{"entry":"identifier","kind":"reject","input":"IHO S-4 B-800","expect":{}},{"entry":"identifier","kind":"reject","input":"nonsense","expect":{}},{"entry":"identifier","kind":"reject","input":"IHO B-12 3.0","expect":{}},{"entry":"identifier","kind":"reject","input":"IHO P-5 1850","expect":{}}],"docs":{},"source":"# Port of lib/pubid/iho/parser.rb — IHO identifiers: letter series\n# (S/P/M/B/C), a number with an optional suffix, and the full component\n# tail (edition, supplement, part, annex, appendix + subnumber, volume,\n# issue, year qualifier).\n#\n# == Component model (owner rulings, 2026-11-03)\n#\n# Every component below is a first-class semantic component: its own\n# named capture, its own typed binding, independently addressable in\n# the model, URN-encodable and matchable — never a regex/string suffix.\n#\n# component face capture binding type\n# edition x.y.z (bare) edition string\n# edition v1 / v5.1 (alias) edition_shorthand string (parse-only;\n# the builder pads to\n# x.y.0 — official IHO\n# edition is dotted\n# x.y.z WITHOUT a year)\n# supplement Sup N (Suppl N) supplement string\n# part Part X / Part S-102 part string (letter,\n# number, or SERIES\n# REFERENCE)\n# part -X / -S-102 (short) part string (hyphenated)\n# annex Annex A annex string\n# appendix Appendix B appendix string\n# appendix Appendix D-2 appendix_subnumber string (the -2)\n# volume Vol. N volume string\n# volume /N (short) volume string (the slash\n# chain, P-1/21 or\n# P-5/2020)\n# volume N (bare, legacy) volume string (the yearbook\n# year IS a volume —\n# one serial-locator\n# component)\n# issue (N) / Issue N issue string\n# year (2024) year string (the with-year\n# qualifier on\n# standards; NOT a\n# serial locator)\n#\n# == Component-edition duality (owner ruling: \"this can happen with any\n# independently publishable artifacts\")\n#\n# Supplement, part, annex, appendix and volume can be published on\n# their own publication cycle, so EACH carries an optional\n# `<kind>_edition` (+ `<kind>_year` qualifier) of its own, mutually\n# exclusive with the base edition context:\n#\n# within-edition: IHO P-6 1.0.0 Vol. 2 (the volume rides\n# the base's edition)\n# separately-published: IHO P-6 Vol. 2 1.0.1 (the volume carries\n# IHO S-98 Part A 1.0.0 its own edition;\n# IHO S-158 Part S-102 0.2.0 the base is\n# cited edition-less)\n#\n# In the URN the ed- segment attaches to the node it follows, so the\n# same positional slot records both modes.\n#\n# The part has a COMPACT face, hyphenated onto the code — `IHO S-5-B`\n# (lettered part), `IHO S-100-1` (numbered part), `IHO S-158-S-102`\n# (series-reference part) — which both parses and renders; the\n# canonical expanded face stays `IHO S-100 x.y.z Part 1`. Gluing a part\n# onto the code without a separator (S-5A) is DISALLOWED as a form: it\n# cannot extend to numbered parts without ambiguity (S-1001 = series\n# 1001 vs series 100 part 1). The four lettered bases the corpus\n# records (S-5A, S-5B, S-8A, S-8B) are LEGACY data spellings: they\n# still parse as aliases (S-5A == S-5 Part A) but are never rendered;\n# the owner rules later whether to reject them outright.\n#\n# Series-reference parts: a check standard applied to another IHO\n# series cites the applied series as its part — `IHO S-158 0.2.0 Part\n# S-102` (the wild glued `S-158-102` spelling is a legacy alias whose\n# normalization to Part S-102 needs an IHO series table; the syntax\n# alone cannot tell it from S-100-1 = Part 1, so it currently parses\n# as the plain number part).\n#\n# Two main syntaxes per the owner ruling: `IHO S-100 1.0.0` (dated =\n# edition-specific) and `IHO S-100` (undated = edition-non-specific).\n# A year beside an edition is the with-year variant qualifier\n# (`IHO S-100 1.0.0 Part X (2024)`), never a year-keyed docidentifier —\n# year-keyed docidentifiers for edition-keyed products are wrong. The\n# continuously-updated series have ONE serial locator, the volume:\n# P-1 and P-6 are volume-keyed (`IHO P-1 Vol. 30 (1)`), and the\n# yearbook year IS a volume (`IHO P-5 Vol. 2020`) — the bare year\n# (`IHO P-5 2020`) and all year-faced forms are parse-only legacy\n# aliases that bind into the volume component, never rendered.\n#\n# Aliases: \"Suppl\" (canonical face Sup, the M-2 spelling — why abbreviate\n# by two letters when Annex and Appendix stay full-length), \"App\"/\"Ap.\"\n# (canonical face Appendix), the hyphenated compact part face (S-5-B ==\n# S-5 Part B, S-100-1 == S-100 Part 1), the legacy glued lettered bases\n# (S-5A, parse-only), \"S-100 v1..v5.1\" (edition shorthand), \"Issue N\"\n# (canonical (N)), the bare year (canonical Vol. N).\n#\n# == URN segment grammar (positional, containment-ordered)\n#\n# The URN mirrors the containment tree, one semantic atom per segment:\n# Part contains Annexes; Annex contains Appendices; a D-2 subnumber is\n# a child atom of Appendix D. No key.value concatenations — every\n# non-number component is a marker-prefixed segment whose marker is the\n# lowercased human-face token (edition follows ISO's ed- precedent).\n# An S-4 specification is a child of its Part (the citation letter rides\n# the part- atom), with the dotted sub and the parenthesized variant as\n# its own children:\n#\n# urn:iho:<type>:<number>[:ed-<x.y.z>][:year-<yyyy>]\n# [:sup-<n>[:ed-<x.y.z>][:year-<yyyy>]]\n# [:part-<X>[:ed-<x.y.z>][:year-<yyyy>]]\n# [:spec-<n>[:specsub-<n>][:specvar-<X>]]\n# [:annex-<A>[...]]\n# [:appendix-<B>[:<sub>][...]]\n# [:vol-<n>[:issue-<n>][...]]\n# [:year-<yyyy>]\n#\n# position segment value vocabulary containment\n# -------- --------------- -------------------------- ------------------\n# 1 <type> s / p / m / b / c namespace root\n# 2 <number> digits + : suffix; may document code\n# span bare segments until\n# the first marker\n# 3 ed-<x.y.z> dotted a.b.c edition qualifier;\n# 4 year-<yyyy> 19xx/20xx ATTACHES TO THE\n# NODE IT FOLLOWS: the\n# base (no component\n# before it) or the\n# component whose\n# segment precedes\n# 5 sup-<n> 1*digit wraps the base\n# 6 part-<X> letter (case kept), contains annexes\n# digits [*letter], or a and S-4 specs\n# series reference\n# [SPMBC]-<digits>\n# 7 spec-<n> [1-6]dd, only under an child of part (the\n# S-4 anchor (s:4) S-4 leaf; the\n# section is the\n# hundreds digit,\n# derivable, never\n# emitted)\n# 8 specsub-<n> 1*digit, only after spec- child of spec\n# 9 specvar-<X> upper letters, after child of spec\n# spec- or specsub-\n# 10 annex-<A> upper letter (case kept) contains appendices\n# 11 appendix-<B> upper letter or digits contains subnumber\n# 12 <sub> 1*digit, BARE, only child of appendix\n# directly after appendix-\n# 13 vol-<n> 1*digit (incl. yearbook contains issue\n# years, Vol. 2020)\n# 14 issue-<n> 1*digit, only after vol- child of volume\n#\n# The number occupies every leading bare segment up to the first\n# marker, so a colon number (S-158:100) round-trips without escaping;\n# after the markers the only bare segment allowed is the appendix\n# subnumber in its own slot. Both the year qualifier and the volume are\n# marker-tagged so neither can collide with a colon-number segment (the\n# #637 hazard, kept under the positional scheme). Letters are\n# case-preserved: part-A and part-a are distinct documents.\n#\n# Legacy 2.0.x spellings remain decodable but are never emitted: the\n# bare a.b.c segment (edition), the dotted keys part./annex./suppl./\n# ap./appendix./vol./issue. and the single-letter y. year tag (whose\n# value decodes into the volume — the serial-locator unification).\n#\n# == S-4 loose-leaf sections and specifications (issue #691; owner\n# rulings of 2026-11-11)\n#\n# The S-4 loose-leaf publication cites its regulations/specifications as\n# <letter>-<hundreds><seq>: B-401 is Part B, Section 400, item 01. ONE\n# component, not two tiers: the spec number IS the leaf; the SECTION is\n# the hundreds digit, DERIVED (never stored, never emitted). The `00`\n# slot (B-400) IS the section-level citation, so \"S-4 Part B, Section\n# 400\" and \"IHO S-4 B-400\" are one identity, two spellings.\n#\n# capture example role\n# spec B-401 -> \"401\" the leaf number (3 digits,\n# hundreds 1-6: sections 100-600)\n# spec_sub B-122.1 -> \"1\" the dotted sub\n# spec_variant B-521(I) -> \"I\" the parenthesized variant\n# spec_part B-401 -> \"B\" the citation letter (the builder\n# binds it into `part`; a Part-rule\n# capture must agree)\n# spec_section \", Section 400\" -> \"400\" the long form's spelled\n# section (becomes `spec` alone;\n# checked against a citation)\n#\n# Faces: canonical compact \"IHO S-4 B-401\" (dated: \"IHO S-4 4.10.0\n# B-401\"); long \"S-4 Part B, Section 400\" (a normalizing parse; also\n# takes a trailing citation: \"S-4 Part B, Section 400, B-401\", where the\n# spelled section only cross-checks the citation's derived section); bare\n# \"B-401\" (implicit S-4 anchor; B only — bare C-x stays the Circular\n# Letter series). The builder binds the anchor: a citation requires the\n# S-4 anchor (or synthesizes it for the bare form).\n#\n# Reserved numbers (\"NOT CURRENTLY USED\" in the S-4 contents — B-170,\n# B-230, B-305, B-323 in Ed 4.9.0 and 4.10.0) parse and resolve AS\n# RESERVED, never invalid; the edition-keyed registry lives in the pubid\n# gem (data/iho/s4-reserved-specs.yaml).\n#\n# URN atoms: part-<letter>:spec-<n>[:specsub-<n>][:specvar-<X>] — the\n# section is NOT emitted (derivable); the citation letter rides the\n# existing part- atom (case preserved: part-B).\n#\n# Edition 2: ruby#400's capture-flatten keeps text captures over\n# reference-built rules as the matched text, so the v2 tree is the v1\n# tree plus named leaves for non-captured structure.\n\ngrammar PubidIho version \"0.3.0\" edition 2 {\n digit = %x30-39\n upper = %x41-5A\n lower = %x61-7A\n letter = upper / lower\n space = \" \"\n dash = \"-\"\n dot = \".\"\n\n series = (\"S\" / \"P\" / \"M\" / \"B\" / \"C\") as type\n number_suffix = (\":\" 1*digit)\n number = (1*digit [number_suffix]) as number\n # The compact part face, hyphenated onto the code: S-5-B (lettered),\n # S-100-1 (numbered) and S-158-S-102 (series reference) — the dash\n # replaces the old bare-glued suffix, so a number like S-1001 stays a\n # whole number (the dash is what makes the part unambiguous). The\n # dash is an inlined literal: a named dash ref here collides with the\n # sequence's own dash node in the edition-2 tree.\n compact_part = \"-\" (((\"S\" / \"P\" / \"M\" / \"B\" / \"C\") dash (1*digit)) / (1*digit [*letter]) / upper) as part\n # LEGACY glued lettered bases (S-5A, S-5B, S-8A, S-8B in the corpus):\n # parse-only aliases, never rendered. Kept because the records exist;\n # the owner rules later whether to reject them.\n glued = upper as part\n\n # The official edition is the dotted x.y.z; \"v1\"/\"v5.1\" is the S-100\n # shorthand (parse-only, the builder pads to x.y.0).\n edition = space (1*digit dot 1*digit dot 1*digit) as edition\n v_edition = space \"v\" ((1*digit) [\".\" (1*digit)]) as edition_shorthand\n # The with-year qualifier on standards: a parenthesized year beside an\n # edition. This is the ONLY base-level year capture — periodical\n # years are volumes (the serial-locator unification).\n year_qualifier = space \"(\" ((\"19\" / \"20\") 2*digit) as year \")\"\n\n # The series-reference part value: a check standard applied to\n # another IHO series (S-158 checks S-102). Ordered FIRST so \"Part\n # S-102\" takes the series-reference branch, not the lone letter.\n part_series_ref = ((\"S\" / \"P\" / \"M\" / \"B\" / \"C\") dash (1*digit))\n part_value = (part_series_ref / (1*digit [*letter]) / upper) as part\n\n # Component-edition duality: each independently-publishable component\n # may carry its own edition (+ year qualifier), mutually exclusive\n # with the base edition context. The captures are position-scoped\n # (<kind>_edition / <kind>_year) so the model knows which component\n # the edition belongs to and the URN attaches ed- to the node it\n # follows.\n part = space \"Part\" space part_value [part_dated] [part_section_tail]\n part_dated = {\n part_edition_rule\n [part_year_rule]\n }\n part_edition_rule = space (1*digit dot 1*digit dot 1*digit) as part_edition\n part_year_rule = space \"(\" ((\"19\" / \"20\") 2*digit) as part_year \")\"\n\n # --- S-4 loose-leaf sections and specifications (see the header) ---\n # The spec number's vocabulary: the S-4 sections run 100-600 (Part C\n # 100-500), so the leaf number is 3 digits with hundreds digit 1-6 —\n # the same shape the bare citation branch leans on to keep the B\n # Bibliographic series (B-1..B-13 style) distinct from B-4xx specs.\n spec_shape = (\"1\" / \"2\" / \"3\" / \"4\" / \"5\" / \"6\") digit digit\n spec_number = spec_shape as spec\n spec_subnumber = dot (1*digit) as spec_sub\n spec_variant = \"(\" (1*upper) as spec_variant \")\"\n # The citation letter is the spec's part (A/B/C); the builder binds it\n # into `part` and rejects a conflicting Part-rule capture.\n spec_citation_body = (\"A\" / \"B\" / \"C\") as spec_part dash spec_number [spec_subnumber] [spec_variant]\n # The compact anchor form: the citation follows the code after one\n # space (\"IHO S-4 B-401\").\n spec_citation = space spec_citation_body\n # The spelled section long form: \"Part B, Section 400\" — the spelled\n # number becomes the spec (the section-level citation), and a trailing\n # citation (\", Section 400, B-401\") makes it a cross-check only. The\n # commas are inlined literals: named comma refs collide as duplicate\n # edition-2 tree nodes under the entry's alternation (the same node\n # collision the compact_part dash-ref comment documents).\n part_section_tail = {\n \",\" space \"Section\" space (spec_shape as spec_section)\n [\",\" space spec_citation_body]\n }\n\n # The bare citation branch (the entry's FIRST alternative): \"B-401\" /\n # \"IHO B-401\" — implicit S-4 anchor (the builder synthesizes series S\n # number 4). B only: bare C-x stays the Circular Letter series, and the\n # 3-digit [1-6]xx shape keeps the B Bibliographic series (B-12) on the\n # main branch.\n bare_spec_citation = [(\"IHO\" space)] (\"B\" as spec_part) dash spec_number [spec_subnumber] [spec_variant]\n\n supplement = space (\"Suppl\" / \"Sup\") space (1*digit) as supplement [supplement_dated]\n supplement_dated = {\n supplement_edition_rule\n [supplement_year_rule]\n }\n supplement_edition_rule = space (1*digit dot 1*digit dot 1*digit) as supplement_edition\n supplement_year_rule = space \"(\" ((\"19\" / \"20\") 2*digit) as supplement_year \")\"\n\n annex = space \"Annex\" space upper as annex [annex_dated]\n annex_dated = {\n annex_edition_rule\n [annex_year_rule]\n }\n annex_edition_rule = space (1*digit dot 1*digit dot 1*digit) as annex_edition\n annex_year_rule = space \"(\" ((\"19\" / \"20\") 2*digit) as annex_year \")\"\n\n appendix_value = (upper / (1*digit)) as appendix\n appendix_subnumber = dash (1*digit) as appendix_subnumber\n appendix = space (\"Appendix\" / \"App\" / \"Ap.\") space appendix_value [appendix_subnumber] [appendix_dated]\n appendix_dated = {\n appendix_edition_rule\n [appendix_year_rule]\n }\n appendix_edition_rule = space (1*digit dot 1*digit dot 1*digit) as appendix_edition\n appendix_year_rule = space \"(\" ((\"19\" / \"20\") 2*digit) as appendix_year \")\"\n\n volume = space \"Vol.\" space (1*digit) as volume [volume_issue]\n volume_issue = (space \"Issue\" space (1*digit) as issue) / (space \"(\" (1*digit) as issue \")\")\n # The volume's short face — the slash chain (\"IHO P-1/21\",\n # \"IHO P-5/2020\"). The slash no longer joins the number.\n volume_short = \"/\" ((1*digit) as volume) [volume_dated]\n # LEGACY bare year (\"IHO P-5 2024\"): the yearbook year IS a volume,\n # so a bare year binds INTO the volume component. Parse-only alias;\n # the canonical print is \"Vol. N\".\n volume_bare_year = space ((\"19\" / \"20\") 2*digit) as volume\n # The volume's own edition (+ year), shared by the Vol. and slash\n # forms.\n volume_dated = {\n volume_edition_rule\n [volume_year_rule]\n }\n volume_edition_rule = space (1*digit dot 1*digit dot 1*digit) as volume_edition\n volume_year_rule = space \"(\" ((\"19\" / \"20\") 2*digit) as volume_year \")\"\n\n # The edition slot accepts the dotted form or the v-shorthand; the\n # with-year qualifier may sit right after it.\n dated = {\n (edition / v_edition)\n [year_qualifier]\n }\n\n # The serial tail picks exactly one discriminator: the long volume\n # (with its optional issue) or the legacy bare year — both bind the\n # volume component, and both may carry the volume's own edition.\n serial = {\n (volume / volume_bare_year)\n [volume_dated]\n }\n\n identifier = {\n [(\"IHO\" space)]\n series\n dash\n number\n [compact_part]\n [glued]\n [volume_short]\n [dated]\n [supplement]\n [part]\n [spec_citation]\n [annex]\n [appendix]\n [serial]\n [year_qualifier]\n }\n\n # The entry dispatches the bare citation branch first (PEG order): a\n # bare \"B-401\"-shaped input takes the S-4 branch, everything else the\n # main identifier.\n identifier_entry = {\n bare_spec_citation / identifier\n }\n\n entry identifier: identifier_entry\n\n test {\n accept \"S-5\"\n accept \"IHO S-5 Appendix 2\"\n accept \"IHO B-12 3.0.0\"\n accept \"IHO P-5 2024\"\n accept \"P-5 2024\"\n accept \"IHO P-5 Vol. 2024\"\n accept \"IHO P-5/2024\"\n accept \"IHO B-7 Vol. 2023\"\n accept \"IHO P-1 Vol. 30\"\n accept \"IHO P-1 Vol. 30 (2)\"\n accept \"IHO P-1 Vol. 30 Issue 2\"\n accept \"IHO P-1/21\"\n accept \"IHO P-1/21 1.0.0\"\n accept \"IHO S-100 5.0.0 Part 2\"\n accept \"IHO S-98 1.0.0 Part A\"\n accept \"IHO S-65 1.1.0 Annex A\"\n accept \"IHO S-122 1.0.0 Appendix D-2\"\n accept \"IHO S-52 4.0.0 Appendix 1\"\n accept \"IHO M-2 Sup 1\"\n accept \"IHO M-2 Suppl 6\"\n accept \"IHO S-66 2.0.0 Sup 4\"\n accept \"IHO S-5-B\"\n accept \"IHO S-100-1\"\n accept \"IHO S-100-1 1.0.0\"\n accept \"IHO P-6-3 1.0.0\"\n accept \"IHO S-5A\"\n accept \"IHO S-5A 1.0.2\"\n accept \"IHO S-5 1.0.2 Part A\"\n accept \"IHO S-100 5.0.0 Part 2 (2024)\"\n accept \"IHO S-100 v5.1\"\n accept \"IHO S-100 v1\"\n accept \"IHO S-100 1.0.0 (2024) Part A\"\n accept \"IHO S-53 Ap. 1 1.0.0\"\n accept \"IHO S-98 Part A 1.0.0\"\n accept \"IHO S-158:100 1.0.0\"\n accept \"IHO S-158:100 Part 2 1.0.0\"\n accept \"IHO S-1001\"\n accept \"IHO S-158 Part S-102 0.2.0\"\n accept \"IHO S-158-S-102 0.2.0\"\n accept \"IHO P-6 1.0.0 Vol. 2\"\n accept \"IHO P-6 Vol. 2 1.0.1\"\n accept \"IHO S-98 1.0.0 Annex A\"\n accept \"IHO S-100 5.0.0 Sup 1 2.0.0\"\n # --- S-4 loose-leaf sections and specifications ---\n accept \"IHO S-4 B-401\"\n accept \"IHO S-4 4.10.0 B-401\"\n accept \"IHO S-4 B-122.1\"\n accept \"IHO S-4 B-521(I)\"\n accept \"IHO S-4 B-351.1(I)\"\n accept \"IHO S-4 B-400\"\n accept \"IHO S-4 B-170\"\n accept \"B-401\"\n accept \"IHO B-401\"\n accept \"B-122.1\"\n accept \"B-521(I)\"\n accept \"IHO S-4 Part B, Section 400\"\n accept \"S-4 Part B, Section 400\"\n accept \"IHO S-4 Part B, Section 400, B-401\"\n accept \"B-12\"\n reject \"IHO S-4 B-4\"\n reject \"IHO S-4 B-40\"\n reject \"IHO S-4 B-800\"\n reject \"nonsense\"\n reject \"IHO B-12 3.0\"\n reject \"IHO P-5 1850\"\n }\n\n bindings identifier_entry {\n type -> type (string)\n number -> number (string)\n part -> part (string)\n part_edition -> part_edition (string)\n part_year -> part_year (string)\n annex -> annex (string)\n annex_edition -> annex_edition (string)\n annex_year -> annex_year (string)\n appendix -> appendix (string)\n appendix_subnumber -> appendix_subnumber (string)\n appendix_edition -> appendix_edition (string)\n appendix_year -> appendix_year (string)\n supplement -> supplement (string)\n supplement_edition -> supplement_edition (string)\n supplement_year -> supplement_year (string)\n edition -> edition (string)\n edition_shorthand -> edition_shorthand (string)\n year -> year (string)\n volume -> volume (string)\n volume_edition -> volume_edition (string)\n volume_year -> volume_year (string)\n issue -> issue (string)\n spec -> spec (string)\n spec_sub -> spec_sub (string)\n spec_variant -> spec_variant (string)\n spec_part -> spec_part (string)\n spec_section -> spec_section (string)\n }\n}\n","source_hash":"2b9f7e6115555242a774cdeb356401be4085991bca0dc92fc9c8fc31ee36b842","unicode_tables":"onigmo (Ruby 3.4.8)","compiler_version":"1.3.126","edition":2,"semantics_hash":"sha256:eb5104d7afed4e2d261a17380e1c7ea678e354df6889cbfbbd27cd01e0442a77","checksum":"sha256:54b4f297d6fae2c2af954387ba09f87428ca42661eb170197f8791e7e3dd1c94"}
|
package/vendor/parg/jis.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"bindings":null,"version":"0.1.0","grammar":"PubidJis","shape":"parsanol-tree/v2","binding_version":1,"entries":{"identifier":{"root":"identifier","grammar":{"atoms":[{"Entity":{"atom":144}},{"Str":{"pattern":"WES"}},{"Named":{"name":"wes","atom":1}},{"Entity":{"atom":6}},{"Str":{"pattern":" "}},{"Str":{"pattern":" "}},{"Alternative":{"atoms":[4,5]}},{"Entity":{"atom":11}},{"Entity":{"atom":9}},{"Re":{"pattern":"[\\x30-\\x39]"}},{"Repetition":{"atom":8,"min":1,"max":null,"tag":"Repetition"}},{"Named":{"name":"number","atom":10}},{"Entity":{"atom":24}},{"Entity":{"atom":22}},{"Entity":{"atom":18}},{"Str":{"pattern":"-"}},{"Str":{"pattern":"ー"}},{"Alternative":{"atoms":[15,16]}},{"Named":{"name":"dash","atom":17}},{"Entity":{"atom":9}},{"Repetition":{"atom":19,"min":1,"max":null,"tag":"Repetition"}},{"Named":{"name":"part","atom":20}},{"Sequence":{"atoms":[14,21]}},{"Repetition":{"atom":13,"min":0,"max":null,"tag":"Repetition"}},{"Named":{"name":"parts","atom":23}},{"Entity":{"atom":40}},{"Entity":{"atom":29}},{"Str":{"pattern":":"}},{"Str":{"pattern":":"}},{"Alternative":{"atoms":[27,28]}},{"Entity":{"atom":9}},{"Repetition":{"atom":30,"min":1,"max":null,"tag":"Repetition"}},{"Named":{"name":"year","atom":31}},{"Entity":{"atom":38}},{"Str":{"pattern":"R"}},{"Str":{"pattern":"R"}},{"Repetition":{"atom":35,"min":0,"max":null,"tag":"Repetition"}},{"Sequence":{"atoms":[34,36]}},{"Named":{"name":"reaffirmed","atom":37}},{"Repetition":{"atom":33,"min":0,"max":1,"tag":"Maybe"}},{"Sequence":{"atoms":[26,32,39]}},{"Repetition":{"atom":25,"min":0,"max":1,"tag":"Maybe"}},{"Entity":{"atom":53}},{"Str":{"pattern":"("}},{"Str":{"pattern":"("}},{"Alternative":{"atoms":[43,44]}},{"Str":{"pattern":"E"}},{"Str":{"pattern":"J"}},{"Alternative":{"atoms":[46,47]}},{"Named":{"name":"language","atom":48}},{"Str":{"pattern":")"}},{"Str":{"pattern":")"}},{"Alternative":{"atoms":[50,51]}},{"Sequence":{"atoms":[45,49,52]}},{"Repetition":{"atom":42,"min":0,"max":1,"tag":"Maybe"}},{"Entity":{"atom":65}},{"Str":{"pattern":"("}},{"Str":{"pattern":"規格群"}},{"Str":{"pattern":")"}},{"Sequence":{"atoms":[56,57,58]}},{"Str":{"pattern":"("}},{"Str":{"pattern":"規格群"}},{"Str":{"pattern":")"}},{"Sequence":{"atoms":[60,61,62]}},{"Alternative":{"atoms":[59,63]}},{"Named":{"name":"all_parts","atom":64}},{"Repetition":{"atom":55,"min":0,"max":1,"tag":"Maybe"}},{"Entity":{"atom":127}},{"Entity":{"atom":89}},{"Entity":{"atom":70}},{"Str":{"pattern":"/"}},{"Str":{"pattern":"AMENDMENT"}},{"Str":{"pattern":"AMD"}},{"Alternative":{"atoms":[71,72]}},{"Named":{"name":"amd_type","atom":73}},{"Entity":{"atom":6}},{"Entity":{"atom":9}},{"Repetition":{"atom":76,"min":1,"max":null,"tag":"Repetition"}},{"Named":{"name":"amd_number","atom":77}},{"Entity":{"atom":29}},{"Entity":{"atom":9}},{"Repetition":{"atom":80,"min":1,"max":null,"tag":"Repetition"}},{"Named":{"name":"amd_year","atom":81}},{"Str":{"pattern":"R"}},{"Str":{"pattern":"R"}},{"Repetition":{"atom":84,"min":0,"max":null,"tag":"Repetition"}},{"Sequence":{"atoms":[83,85]}},{"Repetition":{"atom":86,"min":0,"max":1,"tag":"Maybe"}},{"Named":{"name":"amd_reaffirmed","atom":87}},{"Sequence":{"atoms":[69,74,75,78,79,82,88]}},{"Named":{"name":"amendment","atom":68}},{"Entity":{"atom":103}},{"Entity":{"atom":70}},{"Str":{"pattern":"EXPLANATION"}},{"Str":{"pattern":"EXPL"}},{"Alternative":{"atoms":[93,94]}},{"Named":{"name":"expl_type","atom":95}},{"Entity":{"atom":6}},{"Entity":{"atom":9}},{"Repetition":{"atom":98,"min":1,"max":null,"tag":"Repetition"}},{"Named":{"name":"expl_number","atom":99}},{"Sequence":{"atoms":[97,100]}},{"Repetition":{"atom":101,"min":0,"max":1,"tag":"Maybe"}},{"Sequence":{"atoms":[92,96,102]}},{"Named":{"name":"explanation","atom":91}},{"Entity":{"atom":125}},{"Entity":{"atom":70}},{"Str":{"pattern":"CORRIGENDUM"}},{"Str":{"pattern":"CORR"}},{"Alternative":{"atoms":[107,108]}},{"Named":{"name":"corr_type","atom":109}},{"Entity":{"atom":6}},{"Entity":{"atom":9}},{"Repetition":{"atom":112,"min":1,"max":null,"tag":"Repetition"}},{"Named":{"name":"corr_number","atom":113}},{"Entity":{"atom":29}},{"Entity":{"atom":9}},{"Repetition":{"atom":116,"min":1,"max":null,"tag":"Repetition"}},{"Named":{"name":"corr_year","atom":117}},{"Str":{"pattern":"R"}},{"Str":{"pattern":"R"}},{"Repetition":{"atom":120,"min":0,"max":null,"tag":"Repetition"}},{"Sequence":{"atoms":[119,121]}},{"Repetition":{"atom":122,"min":0,"max":1,"tag":"Maybe"}},{"Named":{"name":"corr_reaffirmed","atom":123}},{"Sequence":{"atoms":[106,110,111,114,115,118,124]}},{"Named":{"name":"corrigendum","atom":105}},{"Alternative":{"atoms":[90,104,126]}},{"Repetition":{"atom":67,"min":0,"max":1,"tag":"Maybe"}},{"Entity":{"atom":142}},{"Entity":{"atom":6}},{"Str":{"pattern":"SYMBOL"}},{"Named":{"name":"symbol_present","atom":131}},{"Entity":{"atom":6}},{"Entity":{"atom":137}},{"Re":{"pattern":"[\\x01-\\x09]"}},{"Re":{"pattern":"[\\x0b-\\u{10ffff}]"}},{"Alternative":{"atoms":[135,136]}},{"Repetition":{"atom":134,"min":1,"max":null,"tag":"Repetition"}},{"Named":{"name":"symbol_value","atom":138}},{"Sequence":{"atoms":[133,139]}},{"Repetition":{"atom":140,"min":0,"max":1,"tag":"Maybe"}},{"Sequence":{"atoms":[130,132,141]}},{"Repetition":{"atom":129,"min":0,"max":1,"tag":"Maybe"}},{"Sequence":{"atoms":[2,3,7,12,41,54,66,128,143]}},{"Entity":{"atom":182}},{"Str":{"pattern":"JIS"}},{"Entity":{"atom":6}},{"Entity":{"atom":70}},{"Alternative":{"atoms":[147,148]}},{"Repetition":{"atom":149,"min":0,"max":1,"tag":"Maybe"}},{"Sequence":{"atoms":[146,150]}},{"Repetition":{"atom":151,"min":0,"max":1,"tag":"Maybe"}},{"Entity":{"atom":161}},{"Str":{"pattern":"TR"}},{"Str":{"pattern":"TS"}},{"Alternative":{"atoms":[154,155]}},{"Named":{"name":"type","atom":156}},{"Entity":{"atom":6}},{"Entity":{"atom":70}},{"Alternative":{"atoms":[158,159]}},{"Sequence":{"atoms":[157,160]}},{"Repetition":{"atom":153,"min":0,"max":1,"tag":"Maybe"}},{"Entity":{"atom":6}},{"Repetition":{"atom":163,"min":0,"max":1,"tag":"Maybe"}},{"Entity":{"atom":167}},{"Re":{"pattern":"[\\x41-\\x5a]"}},{"Named":{"name":"series","atom":166}},{"Entity":{"atom":6}},{"Repetition":{"atom":168,"min":0,"max":1,"tag":"Maybe"}},{"Entity":{"atom":11}},{"Entity":{"atom":24}},{"Entity":{"atom":40}},{"Repetition":{"atom":172,"min":0,"max":1,"tag":"Maybe"}},{"Entity":{"atom":53}},{"Repetition":{"atom":174,"min":0,"max":1,"tag":"Maybe"}},{"Entity":{"atom":65}},{"Repetition":{"atom":176,"min":0,"max":1,"tag":"Maybe"}},{"Entity":{"atom":127}},{"Repetition":{"atom":178,"min":0,"max":1,"tag":"Maybe"}},{"Entity":{"atom":142}},{"Repetition":{"atom":180,"min":0,"max":1,"tag":"Maybe"}},{"Sequence":{"atoms":[152,162,164,165,169,170,171,173,175,177,179,181]}},{"Alternative":{"atoms":[0,145]}}],"root":183},"bindings":[{"capture":"wes","path":"wes","type":"string","card":null,"preprocess":null},{"capture":"type","path":"type","type":"string","card":null,"preprocess":null},{"capture":"series","path":"series","type":"string","card":null,"preprocess":null},{"capture":"number","path":"number","type":"string","card":null,"preprocess":null},{"capture":"part","path":"parts[].part","type":"string","card":null,"preprocess":null},{"capture":"year","path":"year","type":"string","card":null,"preprocess":null},{"capture":"reaffirmed","path":"reaffirmed","type":"string","card":null,"preprocess":null},{"capture":"language","path":"language","type":"string","card":null,"preprocess":null},{"capture":"all_parts","path":"all_parts","type":"string","card":null,"preprocess":null},{"capture":"amd_type","path":"amd_type","type":"string","card":null,"preprocess":null},{"capture":"amd_number","path":"amd_number","type":"string","card":null,"preprocess":null},{"capture":"amd_year","path":"amd_year","type":"string","card":null,"preprocess":null},{"capture":"amd_reaffirmed","path":"amd_reaffirmed","type":"string","card":null,"preprocess":null},{"capture":"expl_type","path":"expl_type","type":"string","card":null,"preprocess":null},{"capture":"expl_number","path":"expl_number","type":"string","card":null,"preprocess":null},{"capture":"corr_type","path":"corr_type","type":"string","card":null,"preprocess":null},{"capture":"corr_number","path":"corr_number","type":"string","card":null,"preprocess":null},{"capture":"corr_year","path":"corr_year","type":"string","card":null,"preprocess":null},{"capture":"corr_reaffirmed","path":"corr_reaffirmed","type":"string","card":null,"preprocess":null},{"capture":"symbol_present","path":"symbol_present","type":"string","card":null,"preprocess":null},{"capture":"symbol_value","path":"symbol_value","type":"string","card":null,"preprocess":null}]}},"preprocess":{},"tables":{},"lint":{"order_warnings":["rule supplement: branches 1 and 2 are order-dependent (shared first bytes; ordered choice is decisive)","rule supplement: branches 1 and 3 are order-dependent (shared first bytes; ordered choice is decisive)","rule supplement: branches 2 and 3 are order-dependent (shared first bytes; ordered choice is decisive)","rule symbol_value_char: branches 1 and 2 are order-dependent (first set not statically known)","rule identifier: branches 1 and 2 are order-dependent (shared first bytes; ordered choice is decisive)"]},"default_entry":"identifier","render":{},"derive":{},"tests":[{"entry":"identifier","kind":"accept","input":"JIS B 0001","expect":{}},{"entry":"identifier","kind":"accept","input":"JIS X 0208:1997","expect":{}},{"entry":"identifier","kind":"accept","input":"WES 7700-1:2019","expect":{}},{"entry":"identifier","kind":"accept","input":"WES 7301:2020R","expect":{}},{"entry":"identifier","kind":"reject","input":"JIS WES 7700","expect":{}},{"entry":"identifier","kind":"reject","input":"WES X 7700","expect":{}},{"entry":"identifier","kind":"reject","input":"nonsense","expect":{}},{"entry":"identifier","kind":"example","input":"WES 7700-1:2019","expect":{"wes":"WES","number":"7700","year":"2019"}},{"entry":"identifier","kind":"example","input":"WES 7301:2020R","expect":{"wes":"WES","number":"7301","year":"2020","reaffirmed":"R"}},{"entry":"identifier","kind":"example","input":"JIS X 0208:1997","expect":{"series":"X","number":"0208","year":"1997"}},{"entry":"identifier","kind":"example","input":"WES 7700:2019/AMD 1:2020R","expect":{"wes":"WES","number":"7700","amd_type":"AMD","amd_number":"1","amd_year":"2020","amd_reaffirmed":"R"}},{"entry":"identifier","kind":"example","input":"JIS X 0208:1997R","expect":{"series":"X","year":"1997","reaffirmed":"R"}},{"entry":"identifier","kind":"example","input":"JIS X 0208:1997RR","expect":{"series":"X","year":"1997","reaffirmed":"RR"}}],"docs":{},"source":"# Port of lib/pubid/jis/parser.rb — JIS identifiers with the Japanese\n# full-width separator tolerance (ー : ()), TR/TS prefixes, parts,\n# reaffirmed years, (E)/(J) language codes, 規格群 all-parts, AMD/EXPL/\n# CORR supplements, and the SYMBOL clause. WES (Japan Welding Engineering\n# Society) ids share the JIS tail but carry no series letter or JIS prefix.\n\ngrammar PubidJis version \"0.1.0\" edition 2 {\n dash = (\"-\" / \"ー\") as dash\n space = (\" \" / \" \")\n colon = (\":\" / \":\")\n type_prefix = (\"TR\" / \"TS\") as type (space / slash)\n series = %x41-5A as series\n number = (1*digit) as number\n part = dash (1*digit) as part\n parts = (*part) as parts\n reaffirmed = \"R\" (*\"R\")\n year = colon (1*digit) as year [reaffirmed_rule]\n language = (\"(\" / \"(\") (\"E\" / \"J\") as language (\")\" / \")\")\n all_parts = ((\"(\" \"規格群\" \")\") / (\"(\" \"規格群\" \")\")) as all_parts\n amendment = {\n slash (\"AMENDMENT\" / \"AMD\") as amd_type\n space\n (1*digit) as amd_number\n colon (1*digit) as amd_year\n ([\"R\" (*\"R\")]) as amd_reaffirmed\n }\n explanation = {\n slash (\"EXPLANATION\" / \"EXPL\") as expl_type\n ([space (1*digit) as expl_number])\n }\n corrigendum = {\n slash (\"CORRIGENDUM\" / \"CORR\") as corr_type\n space\n (1*digit) as corr_number\n colon (1*digit) as corr_year\n ([\"R\" (*\"R\")]) as corr_reaffirmed\n }\n supplement = {\n (amendment as amendment)\n / (explanation as explanation)\n / (corrigendum as corrigendum)\n }\n symbol_value_char = %x01-09 / %x0B-10FFFF\n symbol_clause = {\n space \"SYMBOL\" as symbol_present\n ([space (1*symbol_value_char) as symbol_value])\n }\n wes_identifier = {\n \"WES\" as wes\n space\n number\n parts\n [year]\n [language]\n [all_parts]\n [supplement]\n [symbol_clause]\n }\n jis_identifier = {\n [\"JIS\" [(space / slash)]]\n [type_prefix]\n [space]\n series\n [space]\n number\n parts\n [year]\n [language]\n [all_parts]\n [supplement]\n [symbol_clause]\n }\n identifier = wes_identifier / jis_identifier\n upper = %x41-5A\n digit = %x30-39\n slash = \"/\"\n reaffirmed_rule = (\"R\" (*\"R\")) as reaffirmed\n entry identifier: identifier\n\n # Typed model bindings: bound captures land on the consumer\n # builder's fields of the same name; repeated parts collect under\n # parts[].part.\n bindings identifier {\n wes -> wes (string)\n type -> type (string)\n series -> series (string)\n number -> number (string)\n part -> parts[].part (string)\n year -> year (string)\n reaffirmed -> reaffirmed (string)\n language -> language (string)\n all_parts -> all_parts (string)\n amd_type -> amd_type (string)\n amd_number -> amd_number (string)\n amd_year -> amd_year (string)\n amd_reaffirmed -> amd_reaffirmed (string)\n expl_type -> expl_type (string)\n expl_number -> expl_number (string)\n corr_type -> corr_type (string)\n corr_number -> corr_number (string)\n corr_year -> corr_year (string)\n corr_reaffirmed -> corr_reaffirmed (string)\n symbol_present -> symbol_present (string)\n symbol_value -> symbol_value (string)\n }\n\n test {\n accept \"JIS B 0001\"\n accept \"JIS X 0208:1997\"\n accept \"WES 7700-1:2019\"\n accept \"WES 7301:2020R\"\n reject \"JIS WES 7700\"\n reject \"WES X 7700\"\n reject \"nonsense\"\n example \"WES 7700-1:2019\" { wes: \"WES\", number: \"7700\", year: \"2019\" }\n example \"WES 7301:2020R\" { wes: \"WES\", number: \"7301\", year: \"2020\", reaffirmed: \"R\" }\n example \"JIS X 0208:1997\" { series: \"X\", number: \"0208\", year: \"1997\" }\n example \"WES 7700:2019/AMD 1:2020R\" { wes: \"WES\", number: \"7700\", amd_type: \"AMD\", amd_number: \"1\", amd_year: \"2020\", amd_reaffirmed: \"R\" }\n example \"JIS X 0208:1997R\" { series: \"X\", year: \"1997\", reaffirmed: \"R\" }\n example \"JIS X 0208:1997RR\" { series: \"X\", year: \"1997\", reaffirmed: \"RR\" }\n }\n}\n","source_hash":"bb68f75e3e1d9b7e79613bd6cff60ccd77f6e2e68ace2569a2fbc968543b1f3d","unicode_tables":"onigmo (Ruby 3.4.8)","compiler_version":"1.3.121","edition":2,"semantics_hash":"sha256:b16cf5d2687fef91bb0c21ce6b417cf9d9dfcf9aec0280169acb246f48d6b22b","checksum":"sha256:156eb10c6a7638055e3ca2556c6bf62ecca6521b432c828269cdcbab080c44be"}
|
|
1
|
+
{"bindings":null,"version":"0.1.0","grammar":"PubidJis","shape":"parsanol-tree/v2","binding_version":1,"entries":{"identifier":{"root":"identifier","grammar":{"atoms":[{"Entity":{"atom":165}},{"Str":{"pattern":"WES"}},{"Named":{"name":"wes","atom":1}},{"Entity":{"atom":6}},{"Str":{"pattern":" "}},{"Str":{"pattern":" "}},{"Alternative":{"atoms":[4,5]}},{"Str":{"pattern":"TR"}},{"Str":{"pattern":"TS"}},{"Alternative":{"atoms":[7,8]}},{"Named":{"name":"wes_type","atom":9}},{"Entity":{"atom":6}},{"Sequence":{"atoms":[10,11]}},{"Repetition":{"atom":12,"min":0,"max":1,"tag":"Maybe"}},{"Entity":{"atom":18}},{"Entity":{"atom":16}},{"Re":{"pattern":"[\\x30-\\x39]"}},{"Repetition":{"atom":15,"min":1,"max":null,"tag":"Repetition"}},{"Named":{"name":"number","atom":17}},{"Entity":{"atom":31}},{"Entity":{"atom":29}},{"Entity":{"atom":25}},{"Str":{"pattern":"-"}},{"Str":{"pattern":"ー"}},{"Alternative":{"atoms":[22,23]}},{"Named":{"name":"dash","atom":24}},{"Entity":{"atom":16}},{"Repetition":{"atom":26,"min":1,"max":null,"tag":"Repetition"}},{"Named":{"name":"part","atom":27}},{"Sequence":{"atoms":[21,28]}},{"Repetition":{"atom":20,"min":0,"max":null,"tag":"Repetition"}},{"Named":{"name":"parts","atom":30}},{"Str":{"pattern":"("}},{"Str":{"pattern":"("}},{"Alternative":{"atoms":[32,33]}},{"Str":{"pattern":"E"}},{"Str":{"pattern":"J"}},{"Alternative":{"atoms":[35,36]}},{"Named":{"name":"wes_language","atom":37}},{"Str":{"pattern":")"}},{"Str":{"pattern":")"}},{"Alternative":{"atoms":[39,40]}},{"Entity":{"atom":45}},{"Str":{"pattern":":"}},{"Str":{"pattern":":"}},{"Alternative":{"atoms":[43,44]}},{"Lookahead":{"atom":42,"positive":true}},{"Sequence":{"atoms":[34,38,41,46]}},{"Repetition":{"atom":47,"min":0,"max":1,"tag":"Maybe"}},{"Entity":{"atom":61}},{"Entity":{"atom":45}},{"Entity":{"atom":16}},{"Repetition":{"atom":51,"min":1,"max":null,"tag":"Repetition"}},{"Named":{"name":"year","atom":52}},{"Entity":{"atom":59}},{"Str":{"pattern":"R"}},{"Str":{"pattern":"R"}},{"Repetition":{"atom":56,"min":0,"max":null,"tag":"Repetition"}},{"Sequence":{"atoms":[55,57]}},{"Named":{"name":"reaffirmed","atom":58}},{"Repetition":{"atom":54,"min":0,"max":1,"tag":"Maybe"}},{"Sequence":{"atoms":[50,53,60]}},{"Repetition":{"atom":49,"min":0,"max":1,"tag":"Maybe"}},{"Entity":{"atom":74}},{"Str":{"pattern":"("}},{"Str":{"pattern":"("}},{"Alternative":{"atoms":[64,65]}},{"Str":{"pattern":"E"}},{"Str":{"pattern":"J"}},{"Alternative":{"atoms":[67,68]}},{"Named":{"name":"language","atom":69}},{"Str":{"pattern":")"}},{"Str":{"pattern":")"}},{"Alternative":{"atoms":[71,72]}},{"Sequence":{"atoms":[66,70,73]}},{"Repetition":{"atom":63,"min":0,"max":1,"tag":"Maybe"}},{"Entity":{"atom":86}},{"Str":{"pattern":"("}},{"Str":{"pattern":"規格群"}},{"Str":{"pattern":")"}},{"Sequence":{"atoms":[77,78,79]}},{"Str":{"pattern":"("}},{"Str":{"pattern":"規格群"}},{"Str":{"pattern":")"}},{"Sequence":{"atoms":[81,82,83]}},{"Alternative":{"atoms":[80,84]}},{"Named":{"name":"all_parts","atom":85}},{"Repetition":{"atom":76,"min":0,"max":1,"tag":"Maybe"}},{"Entity":{"atom":148}},{"Entity":{"atom":110}},{"Entity":{"atom":91}},{"Str":{"pattern":"/"}},{"Str":{"pattern":"AMENDMENT"}},{"Str":{"pattern":"AMD"}},{"Alternative":{"atoms":[92,93]}},{"Named":{"name":"amd_type","atom":94}},{"Entity":{"atom":6}},{"Entity":{"atom":16}},{"Repetition":{"atom":97,"min":1,"max":null,"tag":"Repetition"}},{"Named":{"name":"amd_number","atom":98}},{"Entity":{"atom":45}},{"Entity":{"atom":16}},{"Repetition":{"atom":101,"min":1,"max":null,"tag":"Repetition"}},{"Named":{"name":"amd_year","atom":102}},{"Str":{"pattern":"R"}},{"Str":{"pattern":"R"}},{"Repetition":{"atom":105,"min":0,"max":null,"tag":"Repetition"}},{"Sequence":{"atoms":[104,106]}},{"Named":{"name":"amd_reaffirmed","atom":107}},{"Repetition":{"atom":108,"min":0,"max":1,"tag":"Maybe"}},{"Sequence":{"atoms":[90,95,96,99,100,103,109]}},{"Named":{"name":"amendment","atom":89}},{"Entity":{"atom":124}},{"Entity":{"atom":91}},{"Str":{"pattern":"EXPLANATION"}},{"Str":{"pattern":"EXPL"}},{"Alternative":{"atoms":[114,115]}},{"Named":{"name":"expl_type","atom":116}},{"Entity":{"atom":6}},{"Entity":{"atom":16}},{"Repetition":{"atom":119,"min":1,"max":null,"tag":"Repetition"}},{"Named":{"name":"expl_number","atom":120}},{"Sequence":{"atoms":[118,121]}},{"Repetition":{"atom":122,"min":0,"max":1,"tag":"Maybe"}},{"Sequence":{"atoms":[113,117,123]}},{"Named":{"name":"explanation","atom":112}},{"Entity":{"atom":146}},{"Entity":{"atom":91}},{"Str":{"pattern":"CORRIGENDUM"}},{"Str":{"pattern":"CORR"}},{"Alternative":{"atoms":[128,129]}},{"Named":{"name":"corr_type","atom":130}},{"Entity":{"atom":6}},{"Entity":{"atom":16}},{"Repetition":{"atom":133,"min":1,"max":null,"tag":"Repetition"}},{"Named":{"name":"corr_number","atom":134}},{"Entity":{"atom":45}},{"Entity":{"atom":16}},{"Repetition":{"atom":137,"min":1,"max":null,"tag":"Repetition"}},{"Named":{"name":"corr_year","atom":138}},{"Str":{"pattern":"R"}},{"Str":{"pattern":"R"}},{"Repetition":{"atom":141,"min":0,"max":null,"tag":"Repetition"}},{"Sequence":{"atoms":[140,142]}},{"Named":{"name":"corr_reaffirmed","atom":143}},{"Repetition":{"atom":144,"min":0,"max":1,"tag":"Maybe"}},{"Sequence":{"atoms":[127,131,132,135,136,139,145]}},{"Named":{"name":"corrigendum","atom":126}},{"Alternative":{"atoms":[111,125,147]}},{"Repetition":{"atom":88,"min":0,"max":1,"tag":"Maybe"}},{"Entity":{"atom":163}},{"Entity":{"atom":6}},{"Str":{"pattern":"SYMBOL"}},{"Named":{"name":"symbol_present","atom":152}},{"Entity":{"atom":6}},{"Entity":{"atom":158}},{"Re":{"pattern":"[\\x01-\\x09]"}},{"Re":{"pattern":"[\\x0b-\\u{10ffff}]"}},{"Alternative":{"atoms":[156,157]}},{"Repetition":{"atom":155,"min":1,"max":null,"tag":"Repetition"}},{"Named":{"name":"symbol_value","atom":159}},{"Sequence":{"atoms":[154,160]}},{"Repetition":{"atom":161,"min":0,"max":1,"tag":"Maybe"}},{"Sequence":{"atoms":[151,153,162]}},{"Repetition":{"atom":150,"min":0,"max":1,"tag":"Maybe"}},{"Sequence":{"atoms":[2,3,13,14,19,48,62,75,87,149,164]}},{"Entity":{"atom":203}},{"Str":{"pattern":"JIS"}},{"Entity":{"atom":6}},{"Entity":{"atom":91}},{"Alternative":{"atoms":[168,169]}},{"Repetition":{"atom":170,"min":0,"max":1,"tag":"Maybe"}},{"Sequence":{"atoms":[167,171]}},{"Repetition":{"atom":172,"min":0,"max":1,"tag":"Maybe"}},{"Entity":{"atom":182}},{"Str":{"pattern":"TR"}},{"Str":{"pattern":"TS"}},{"Alternative":{"atoms":[175,176]}},{"Named":{"name":"type","atom":177}},{"Entity":{"atom":6}},{"Entity":{"atom":91}},{"Alternative":{"atoms":[179,180]}},{"Sequence":{"atoms":[178,181]}},{"Repetition":{"atom":174,"min":0,"max":1,"tag":"Maybe"}},{"Entity":{"atom":6}},{"Repetition":{"atom":184,"min":0,"max":1,"tag":"Maybe"}},{"Entity":{"atom":188}},{"Re":{"pattern":"[\\x41-\\x5a]"}},{"Named":{"name":"series","atom":187}},{"Entity":{"atom":6}},{"Repetition":{"atom":189,"min":0,"max":1,"tag":"Maybe"}},{"Entity":{"atom":18}},{"Entity":{"atom":31}},{"Entity":{"atom":61}},{"Repetition":{"atom":193,"min":0,"max":1,"tag":"Maybe"}},{"Entity":{"atom":74}},{"Repetition":{"atom":195,"min":0,"max":1,"tag":"Maybe"}},{"Entity":{"atom":86}},{"Repetition":{"atom":197,"min":0,"max":1,"tag":"Maybe"}},{"Entity":{"atom":148}},{"Repetition":{"atom":199,"min":0,"max":1,"tag":"Maybe"}},{"Entity":{"atom":163}},{"Repetition":{"atom":201,"min":0,"max":1,"tag":"Maybe"}},{"Sequence":{"atoms":[173,183,185,186,190,191,192,194,196,198,200,202]}},{"Alternative":{"atoms":[0,166]}}],"root":204},"bindings":[{"capture":"wes","path":"wes","type":"string","card":null,"preprocess":null},{"capture":"wes_type","path":"wes_type","type":"string","card":null,"preprocess":null},{"capture":"wes_language","path":"wes_language","type":"string","card":null,"preprocess":null},{"capture":"type","path":"type","type":"string","card":null,"preprocess":null},{"capture":"series","path":"series","type":"string","card":null,"preprocess":null},{"capture":"number","path":"number","type":"string","card":null,"preprocess":null},{"capture":"part","path":"parts[].part","type":"string","card":null,"preprocess":null},{"capture":"year","path":"year","type":"string","card":null,"preprocess":null},{"capture":"reaffirmed","path":"reaffirmed","type":"string","card":null,"preprocess":null},{"capture":"language","path":"language","type":"string","card":null,"preprocess":null},{"capture":"all_parts","path":"all_parts","type":"string","card":null,"preprocess":null},{"capture":"amd_type","path":"amd_type","type":"string","card":null,"preprocess":null},{"capture":"amd_number","path":"amd_number","type":"string","card":null,"preprocess":null},{"capture":"amd_year","path":"amd_year","type":"string","card":null,"preprocess":null},{"capture":"amd_reaffirmed","path":"amd_reaffirmed","type":"string","card":null,"preprocess":null},{"capture":"expl_type","path":"expl_type","type":"string","card":null,"preprocess":null},{"capture":"expl_number","path":"expl_number","type":"string","card":null,"preprocess":null},{"capture":"corr_type","path":"corr_type","type":"string","card":null,"preprocess":null},{"capture":"corr_number","path":"corr_number","type":"string","card":null,"preprocess":null},{"capture":"corr_year","path":"corr_year","type":"string","card":null,"preprocess":null},{"capture":"corr_reaffirmed","path":"corr_reaffirmed","type":"string","card":null,"preprocess":null},{"capture":"symbol_present","path":"symbol_present","type":"string","card":null,"preprocess":null},{"capture":"symbol_value","path":"symbol_value","type":"string","card":null,"preprocess":null}]}},"preprocess":{},"tables":{},"lint":{"order_warnings":["rule supplement: branches 1 and 2 are order-dependent (shared first bytes; ordered choice is decisive)","rule supplement: branches 1 and 3 are order-dependent (shared first bytes; ordered choice is decisive)","rule supplement: branches 2 and 3 are order-dependent (shared first bytes; ordered choice is decisive)","rule symbol_value_char: branches 1 and 2 are order-dependent (first set not statically known)","rule identifier: branches 1 and 2 are order-dependent (shared first bytes; ordered choice is decisive)"]},"default_entry":"identifier","render":{},"derive":{},"tests":[{"entry":"identifier","kind":"accept","input":"JIS B 0001","expect":{}},{"entry":"identifier","kind":"accept","input":"JIS X 0208:1997","expect":{}},{"entry":"identifier","kind":"accept","input":"WES 7700-1:2019","expect":{}},{"entry":"identifier","kind":"accept","input":"WES 7301:2020R","expect":{}},{"entry":"identifier","kind":"reject","input":"JIS WES 7700","expect":{}},{"entry":"identifier","kind":"reject","input":"WES X 7700","expect":{}},{"entry":"identifier","kind":"reject","input":"nonsense","expect":{}},{"entry":"identifier","kind":"example","input":"WES 7700-1:2019","expect":{"wes":"WES","number":"7700","year":"2019"}},{"entry":"identifier","kind":"example","input":"WES 7301:2020R","expect":{"wes":"WES","number":"7301","year":"2020","reaffirmed":"R"}},{"entry":"identifier","kind":"example","input":"JIS X 0208:1997","expect":{"series":"X","number":"0208","year":"1997"}},{"entry":"identifier","kind":"example","input":"WES 7700:2019/AMD 1:2020R","expect":{"wes":"WES","number":"7700","amd_type":"AMD","amd_number":"1","amd_year":"2020","amd_reaffirmed":"R"}},{"entry":"identifier","kind":"example","input":"JIS X 0208:1997R","expect":{"series":"X","year":"1997","reaffirmed":"R"}},{"entry":"identifier","kind":"example","input":"JIS X 0208:1997RR","expect":{"series":"X","year":"1997","reaffirmed":"RR"}},{"entry":"identifier","kind":"example","input":"WES 1112(E):2022","expect":{"wes":"WES","number":"1112","wes_language":"E","year":"2022"}},{"entry":"identifier","kind":"example","input":"WES TR 2032:2024","expect":{"wes":"WES","wes_type":"TR","number":"2032","year":"2024"}},{"entry":"identifier","kind":"example","input":"WES TS 2816(E):2015","expect":{"wes":"WES","wes_type":"TS","number":"2816","wes_language":"E","year":"2015"}},{"entry":"identifier","kind":"example","input":"WES TS 2816:2015","expect":{"wes":"WES","wes_type":"TS","number":"2816","year":"2015"}},{"entry":"identifier","kind":"example","input":"WES 3003(E):1995/AMENDMENT 1:2025","expect":{"wes_language":"E","year":"1995","amd_type":"AMENDMENT","amd_number":"1","amd_year":"2025"}},{"entry":"identifier","kind":"example","input":"WES 1112:2022(E)","expect":{"language":"E","year":"2022"}},{"entry":"identifier","kind":"example","input":"WES 1112(E)","expect":{"wes":"WES","number":"1112","language":"E"}},{"entry":"identifier","kind":"example","input":"JIS A 0001:1999/AMD 1:2000","expect":{"series":"A","number":"0001","year":"1999","amd_type":"AMD","amd_number":"1","amd_year":"2000"}},{"entry":"identifier","kind":"example","input":"JIS B 3700-11:1996/CORRIGENDUM 1:2002","expect":{"series":"B","number":"3700","year":"1996","corr_type":"CORRIGENDUM","corr_number":"1","corr_year":"2002"}},{"entry":"identifier","kind":"reject","input":"JIS X 0208(E):1997","expect":{}},{"entry":"identifier","kind":"reject","input":"TR WES 2032","expect":{}},{"entry":"identifier","kind":"reject","input":"JIS TR WES 2032","expect":{}},{"entry":"identifier","kind":"reject","input":"WES TX 2032:2024","expect":{}},{"entry":"identifier","kind":"reject","input":"WES TR X 2032","expect":{}},{"entry":"identifier","kind":"example","input":"WES TR 2032:2024","expect":{"wes":"WES","wes_type":"TR","number":"2032","year":"2024"}},{"entry":"identifier","kind":"example","input":"WES 1112(E):2022","expect":{"wes":"WES","number":"1112","wes_language":"E","year":"2022"}}],"docs":{},"source":"# Port of lib/pubid/jis/parser.rb — JIS identifiers with the Japanese\n# full-width separator tolerance (ー : ()), TR/TS prefixes, parts,\n# reaffirmed years, (E)/(J) language codes, 規格群 all-parts, AMD/EXPL/\n# CORR supplements, and the SYMBOL clause. WES (Japan Welding Engineering\n# Society) ids share the JIS tail but carry no series letter or JIS prefix.\n# A WES id can carry a TR/TS type after the root (`WES TR 2032:2024`) and\n# a language before the year (`WES 1112(E):2022`, bound as wes_language).\n\ngrammar PubidJis version \"0.1.0\" edition 2 {\n dash = (\"-\" / \"ー\") as dash\n space = (\" \" / \" \")\n colon = (\":\" / \":\")\n type_prefix = (\"TR\" / \"TS\") as type (space / slash)\n series = %x41-5A as series\n number = (1*digit) as number\n part = dash (1*digit) as part\n parts = (*part) as parts\n year = colon (1*digit) as year [reaffirmed_rule]\n language = (\"(\" / \"(\") (\"E\" / \"J\") as language (\")\" / \")\")\n all_parts = ((\"(\" \"規格群\" \")\") / (\"(\" \"規格群\" \")\")) as all_parts\n amendment = {\n slash (\"AMENDMENT\" / \"AMD\") as amd_type\n space\n (1*digit) as amd_number\n colon (1*digit) as amd_year\n [(\"R\" (*\"R\")) as amd_reaffirmed]\n }\n explanation = {\n slash (\"EXPLANATION\" / \"EXPL\") as expl_type\n ([space (1*digit) as expl_number])\n }\n corrigendum = {\n slash (\"CORRIGENDUM\" / \"CORR\") as corr_type\n space\n (1*digit) as corr_number\n colon (1*digit) as corr_year\n [(\"R\" (*\"R\")) as corr_reaffirmed]\n }\n supplement = {\n (amendment as amendment)\n / (explanation as explanation)\n / (corrigendum as corrigendum)\n }\n symbol_value_char = %x01-09 / %x0B-10FFFF\n symbol_clause = {\n space \"SYMBOL\" as symbol_present\n ([space (1*symbol_value_char) as symbol_value])\n }\n wes_identifier = {\n \"WES\" as wes\n space\n [(\"TR\" / \"TS\") as wes_type space]\n number\n parts\n [(\"(\" / \"(\") (\"E\" / \"J\") as wes_language (\")\" / \")\") &colon]\n [year]\n [language]\n [all_parts]\n [supplement]\n [symbol_clause]\n }\n jis_identifier = {\n [\"JIS\" [(space / slash)]]\n [type_prefix]\n [space]\n series\n [space]\n number\n parts\n [year]\n [language]\n [all_parts]\n [supplement]\n [symbol_clause]\n }\n identifier = wes_identifier / jis_identifier\n upper = %x41-5A\n digit = %x30-39\n slash = \"/\"\n reaffirmed_rule = (\"R\" (*\"R\")) as reaffirmed\n entry identifier: identifier\n\n # Typed model bindings: bound captures land on the consumer\n # builder's fields of the same name; repeated parts collect under\n # parts[].part.\n bindings identifier {\n wes -> wes (string)\n wes_type -> wes_type (string)\n wes_language -> wes_language (string)\n type -> type (string)\n series -> series (string)\n number -> number (string)\n part -> parts[].part (string)\n year -> year (string)\n reaffirmed -> reaffirmed (string)\n language -> language (string)\n all_parts -> all_parts (string)\n amd_type -> amd_type (string)\n amd_number -> amd_number (string)\n amd_year -> amd_year (string)\n amd_reaffirmed -> amd_reaffirmed (string)\n expl_type -> expl_type (string)\n expl_number -> expl_number (string)\n corr_type -> corr_type (string)\n corr_number -> corr_number (string)\n corr_year -> corr_year (string)\n corr_reaffirmed -> corr_reaffirmed (string)\n symbol_present -> symbol_present (string)\n symbol_value -> symbol_value (string)\n }\n\n test {\n accept \"JIS B 0001\"\n accept \"JIS X 0208:1997\"\n accept \"WES 7700-1:2019\"\n accept \"WES 7301:2020R\"\n reject \"JIS WES 7700\"\n reject \"WES X 7700\"\n reject \"nonsense\"\n example \"WES 7700-1:2019\" { wes: \"WES\", number: \"7700\", year: \"2019\" }\n example \"WES 7301:2020R\" { wes: \"WES\", number: \"7301\", year: \"2020\", reaffirmed: \"R\" }\n example \"JIS X 0208:1997\" { series: \"X\", number: \"0208\", year: \"1997\" }\n example \"WES 7700:2019/AMD 1:2020R\" { wes: \"WES\", number: \"7700\", amd_type: \"AMD\", amd_number: \"1\", amd_year: \"2020\", amd_reaffirmed: \"R\" }\n example \"JIS X 0208:1997R\" { series: \"X\", year: \"1997\", reaffirmed: \"R\" }\n example \"JIS X 0208:1997RR\" { series: \"X\", year: \"1997\", reaffirmed: \"RR\" }\n example \"WES 1112(E):2022\" { wes: \"WES\", number: \"1112\", wes_language: \"E\", year: \"2022\" }\n example \"WES TR 2032:2024\" { wes: \"WES\", wes_type: \"TR\", number: \"2032\", year: \"2024\" }\n example \"WES TS 2816(E):2015\" { wes: \"WES\", wes_type: \"TS\", number: \"2816\", wes_language: \"E\", year: \"2015\" }\n example \"WES TS 2816:2015\" { wes: \"WES\", wes_type: \"TS\", number: \"2816\", year: \"2015\" }\n example \"WES 3003(E):1995/AMENDMENT 1:2025\" { wes_language: \"E\", year: \"1995\", amd_type: \"AMENDMENT\", amd_number: \"1\", amd_year: \"2025\" }\n example \"WES 1112:2022(E)\" { language: \"E\", year: \"2022\" }\n example \"WES 1112(E)\" { wes: \"WES\", number: \"1112\", language: \"E\" }\n example \"JIS A 0001:1999/AMD 1:2000\" { series: \"A\", number: \"0001\", year: \"1999\", amd_type: \"AMD\", amd_number: \"1\", amd_year: \"2000\" }\n example \"JIS B 3700-11:1996/CORRIGENDUM 1:2002\" { series: \"B\", number: \"3700\", year: \"1996\", corr_type: \"CORRIGENDUM\", corr_number: \"1\", corr_year: \"2002\" }\n reject \"JIS X 0208(E):1997\"\n reject \"TR WES 2032\"\n reject \"JIS TR WES 2032\"\n reject \"WES TX 2032:2024\"\n reject \"WES TR X 2032\"\n example \"WES TR 2032:2024\" { wes: \"WES\", wes_type: \"TR\", number: \"2032\", year: \"2024\" }\n example \"WES 1112(E):2022\" { wes: \"WES\", number: \"1112\", wes_language: \"E\", year: \"2022\" }\n }\n}\n","source_hash":"890e9d76109dd798047c6a1515901e6819cd80f1fa3eb1308e80afcfd6b272c9","unicode_tables":"onigmo (Ruby 3.4.8)","compiler_version":"1.3.126","edition":2,"semantics_hash":"sha256:7c4b170d64be52fae49eecbfab26897487ef87a66a25bf11d935d6a4d1e54f87","checksum":"sha256:34056972f729be65f8874efeaf5e72cc5f9d2ce2466a1447e4fcd6adaa6ccbae"}
|