pubid 2.0.4 → 2.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/data/bipm/update_codes.yaml +14 -0
- data/data/parg/iho.json +1 -1
- data/data/parg/iho.parg +358 -0
- data/data/parg/jis.json +1 -1
- data/data/parg/parg.json +1 -1
- data/data/parg/parg.parg +118 -0
- data/lib/pubid/bipm/CLAUDE.md +2 -0
- data/lib/pubid/bipm.rb +10 -4
- data/lib/pubid/bsi/CLAUDE.md +4 -0
- data/lib/pubid/bsi/single_identifier.rb +10 -1
- data/lib/pubid/ieee/builder.rb +6 -1
- data/lib/pubid/ietf/CLAUDE.md +2 -0
- data/lib/pubid/ietf.rb +5 -2
- data/lib/pubid/iho/CLAUDE.md +157 -81
- data/lib/pubid/iho/builder.rb +61 -16
- data/lib/pubid/iho/identifier.rb +2 -2
- data/lib/pubid/iho/identifiers/base.rb +134 -37
- data/lib/pubid/iho/renderer.rb +44 -22
- data/lib/pubid/iho/urn_generator.rb +56 -19
- data/lib/pubid/iho/urn_parser.rb +211 -40
- data/lib/pubid/iso/CLAUDE.md +32 -0
- data/lib/pubid/iso/urn_parser.rb +63 -6
- data/lib/pubid/jis/CLAUDE.md +9 -4
- data/lib/pubid/parg/backend.rb +1 -1
- data/lib/pubid/parg/model.rb +7 -2
- data/lib/pubid/parg.rb +13 -0
- data/lib/pubid/tgpp/CLAUDE.md +2 -0
- data/lib/pubid/tgpp.rb +11 -0
- data/lib/pubid/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: bb0eb2441f1733fb2498a35955d3840cf1058c1cc2a0da5222633b80451258b2
|
|
4
|
+
data.tar.gz: 110f3275bbef45f8b5d956193ae4aee6647bb9ca57ff51b383451b1f575c964e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 270e7d940a329eeb409bd65dc14dd325318ab11b81f702fc45e3c5186fd6d39d40cae0f0c286ab454900928d009dcf8073ddfcb4a6d803181223f6608c5d85c2
|
|
7
|
+
data.tar.gz: fd28a2998a2bb92a7812b7a435d5965e95991ad5f666d5c6f2d13e1171b8d4edaa6905e32b2b15124052816d0ee2873446d73c125e1b3d6ef26ca6d6b3e851a2
|
data/data/bipm/update_codes.yaml
CHANGED
|
@@ -7,3 +7,17 @@
|
|
|
7
7
|
# the docnumber and docidentifier spellings map onto the bare "CIPM 2005-06" form.
|
|
8
8
|
"CIPM/2005-06(REV)": CIPM 2005-06
|
|
9
9
|
"CIPM 2005-06(REV)": CIPM 2005-06
|
|
10
|
+
|
|
11
|
+
# The SI Brochure cited by its title: the brochure IS "The International
|
|
12
|
+
# System of Units", and external references cite it in quotes (pubid#644).
|
|
13
|
+
# Map the quoted-title spelling onto the parseable "BIPM SI Brochure" section
|
|
14
|
+
# form — a partial reference with no edition, so it wildcards every edition
|
|
15
|
+
# under the matching primitives, exactly like "SI Brochure Part 1". A
|
|
16
|
+
# normalizing parse like the CIPM MRA ones above: never a byte-exact fixture
|
|
17
|
+
# (see spec/pubid/bipm/loose_consumer_forms_spec.rb).
|
|
18
|
+
#
|
|
19
|
+
# The French title is deliberately NOT mapped: it names the F-language record
|
|
20
|
+
# specifically, and mapping it would silently drop language information the
|
|
21
|
+
# user typed (the loose-forms rule). English is language-neutral, so it stays.
|
|
22
|
+
/^BIPM "The International System of Units"$/: BIPM SI Brochure
|
|
23
|
+
/^"The International System of Units"$/: SI Brochure
|
data/data/parg/iho.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"bindings":null,"version":"0.1.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":37}},{"Entity":{"atom":17}},{"Re":{"pattern":"[\\x30-\\x39]"}},{"Repetition":{"atom":16,"min":1,"max":null,"tag":"Repetition"}},{"Entity":{"atom":34}},{"Str":{"pattern":":"}},{"Entity":{"atom":17}},{"Repetition":{"atom":21,"min":1,"max":null,"tag":"Repetition"}},{"Sequence":{"atoms":[20,22]}},{"Str":{"pattern":"/"}},{"Entity":{"atom":17}},{"Repetition":{"atom":25,"min":1,"max":null,"tag":"Repetition"}},{"Sequence":{"atoms":[24,26]}},{"Entity":{"atom":14}},{"Entity":{"atom":17}},{"Repetition":{"atom":29,"min":1,"max":null,"tag":"Repetition"}},{"Sequence":{"atoms":[28,30]}},{"Entity":{"atom":33}},{"Re":{"pattern":"[\\x41-\\x5a]"}},{"Alternative":{"atoms":[23,27,31,32]}},{"Repetition":{"atom":19,"min":0,"max":1,"tag":"Maybe"}},{"Sequence":{"atoms":[18,35]}},{"Named":{"name":"number","atom":36}},{"Entity":{"atom":54}},{"Entity":{"atom":2}},{"Str":{"pattern":"Appendix"}},{"Str":{"pattern":"Ap."}},{"Alternative":{"atoms":[40,41]}},{"Entity":{"atom":2}},{"Entity":{"atom":33}},{"Entity":{"atom":14}},{"Entity":{"atom":17}},{"Repetition":{"atom":46,"min":1,"max":null,"tag":"Repetition"}},{"Sequence":{"atoms":[44,45,47]}},{"Entity":{"atom":17}},{"Repetition":{"atom":49,"min":1,"max":null,"tag":"Repetition"}},{"Entity":{"atom":33}},{"Alternative":{"atoms":[48,50,51]}},{"Named":{"name":"appendix","atom":52}},{"Sequence":{"atoms":[39,42,43,53]}},{"Repetition":{"atom":38,"min":0,"max":1,"tag":"Maybe"}},{"Entity":{"atom":72}},{"Entity":{"atom":2}},{"Str":{"pattern":"Part"}},{"Entity":{"atom":2}},{"Entity":{"atom":17}},{"Repetition":{"atom":60,"min":1,"max":null,"tag":"Repetition"}},{"Entity":{"atom":66}},{"Entity":{"atom":33}},{"Entity":{"atom":65}},{"Re":{"pattern":"[\\x61-\\x7a]"}},{"Alternative":{"atoms":[63,64]}},{"Repetition":{"atom":62,"min":0,"max":null,"tag":"Repetition"}},{"Sequence":{"atoms":[61,67]}},{"Entity":{"atom":33}},{"Alternative":{"atoms":[68,69]}},{"Named":{"name":"part","atom":70}},{"Sequence":{"atoms":[57,58,59,71]}},{"Repetition":{"atom":56,"min":0,"max":1,"tag":"Maybe"}},{"Entity":{"atom":80}},{"Entity":{"atom":2}},{"Str":{"pattern":"Annex"}},{"Entity":{"atom":2}},{"Entity":{"atom":33}},{"Named":{"name":"annex","atom":78}},{"Sequence":{"atoms":[75,76,77,79]}},{"Repetition":{"atom":74,"min":0,"max":1,"tag":"Maybe"}},{"Entity":{"atom":89}},{"Entity":{"atom":2}},{"Str":{"pattern":"Suppl"}},{"Entity":{"atom":2}},{"Entity":{"atom":17}},{"Repetition":{"atom":86,"min":1,"max":null,"tag":"Repetition"}},{"Named":{"name":"supplement","atom":87}},{"Sequence":{"atoms":[83,84,85,88]}},{"Repetition":{"atom":82,"min":0,"max":1,"tag":"Maybe"}},{"Entity":{"atom":135}},{"Entity":{"atom":2}},{"Entity":{"atom":17}},{"Repetition":{"atom":93,"min":1,"max":null,"tag":"Repetition"}},{"Entity":{"atom":96}},{"Str":{"pattern":"."}},{"Entity":{"atom":17}},{"Repetition":{"atom":97,"min":1,"max":null,"tag":"Repetition"}},{"Entity":{"atom":96}},{"Entity":{"atom":17}},{"Repetition":{"atom":100,"min":1,"max":null,"tag":"Repetition"}},{"Sequence":{"atoms":[94,95,98,99,101]}},{"Named":{"name":"version","atom":102}},{"Str":{"pattern":"19"}},{"Str":{"pattern":"20"}},{"Alternative":{"atoms":[104,105]}},{"Entity":{"atom":17}},{"Repetition":{"atom":107,"min":2,"max":null,"tag":"Repetition"}},{"Sequence":{"atoms":[106,108]}},{"Named":{"name":"year","atom":109}},{"Str":{"pattern":"Vol."}},{"Entity":{"atom":2}},{"Entity":{"atom":17}},{"Repetition":{"atom":113,"min":1,"max":null,"tag":"Repetition"}},{"Named":{"name":"volume","atom":114}},{"Sequence":{"atoms":[111,112,115]}},{"Entity":{"atom":2}},{"Str":{"pattern":"Issue"}},{"Entity":{"atom":2}},{"Entity":{"atom":17}},{"Repetition":{"atom":120,"min":1,"max":null,"tag":"Repetition"}},{"Named":{"name":"issue","atom":121}},{"Sequence":{"atoms":[117,118,119,122]}},{"Entity":{"atom":2}},{"Str":{"pattern":"("}},{"Entity":{"atom":17}},{"Repetition":{"atom":126,"min":1,"max":null,"tag":"Repetition"}},{"Named":{"name":"issue","atom":127}},{"Str":{"pattern":")"}},{"Sequence":{"atoms":[124,125,128,129]}},{"Alternative":{"atoms":[123,130]}},{"Repetition":{"atom":131,"min":0,"max":1,"tag":"Maybe"}},{"Sequence":{"atoms":[116,132]}},{"Alternative":{"atoms":[103,110,133]}},{"Sequence":{"atoms":[92,134]}},{"Repetition":{"atom":91,"min":0,"max":1,"tag":"Maybe"}},{"Sequence":{"atoms":[4,5,13,15,55,73,81,90,136]}}],"root":137},"bindings":[{"capture":"year","path":"year","type":"string","card":null,"preprocess":null},{"capture":"volume","path":"volume","type":"string","card":null,"preprocess":null},{"capture":"issue","path":"issue","type":"string","card":null,"preprocess":null}]}},"preprocess":{},"tables":{},"lint":{"order_warnings":[]},"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 B-7 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":"reject","input":"nonsense","expect":{}},{"entry":"identifier","kind":"reject","input":"IHO B-12 3.0","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 appendix, part,\n# annex, supplement and version tails.\n#\n# The trailing component of a series form is a discriminator chosen\n# from:\n# - the dotted version a.b.c (unchanged — the historical placeholder\n# and the real S/M/B/C editions, e.g. \"B-12 3.0.0\");\n# - a 4-digit year 19xx/20xx (\"P-5 2024\", \"B-7 2023\") — the identity\n# form for the year-identified series (relaton#407: B-7, P-5, P-6\n# are identified by year, not by a placeholder edition);\n# - a volume \"Vol. N\" with an optional issue (\"P-1 Vol. 30\",\n# \"P-1 Vol. 30 (2)\"). The issue is captured as the bare number and\n# prints in parentheses. The \"Issue N\" spelling is accepted as an\n# input alias; the parenthesized form is the canonical print.\n# DECISION FLAG for the IHO-agreement step: real IHR issue\n# spellings vary (\"No. N\" is also seen) — only \"(N)\" and\n# \"Issue N\" are accepted until the spelling is agreed.\n# A two-segment version (\"B-12 3.0\") is deliberately NOT supported:\n# no IHO series carries one in the corpus, and neither new rule\n# swallows it (a year needs all four digits of 19xx/20xx; a dotted\n# version needs all three segments).\n#\n# The grammar stays edition v1: the v1 tree inlines rule references\n# inside a captured body (the v2 tree materializes them as named\n# nodes), which the builder's string fold over :number/:type expects.\n# The tail rule uses only raw terms, so nothing in it needs v2.\n\ngrammar PubidIho version \"0.1.0\" edition 1 {\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) / (\"/\" 1*digit) / (dash 1*digit) / upper)\n number = (1*digit [number_suffix]) as number\n appendix = {\n space (\"Appendix\" / \"Ap.\") space\n ((upper dash 1*digit) / (1*digit) / upper) as appendix\n }\n part = {\n space \"Part\" space\n ((1*digit *letter) / upper) as part\n }\n annex = space \"Annex\" space upper as annex\n supplement = space \"Suppl\" space (1*digit) as supplement\n tail = {\n space\n (\n (1*digit dot 1*digit dot 1*digit) as version\n / ((\"19\" / \"20\") 2*digit) as year\n / (\n (\"Vol.\" space (1*digit) as volume)\n [\n (space \"Issue\" space (1*digit) as issue)\n / (space \"(\" (1*digit) as issue \")\")\n ]\n )\n )\n }\n\n identifier = {\n [(\"IHO\" space)]\n series\n dash\n number\n [appendix]\n [part]\n [annex]\n [supplement]\n [tail]\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 B-7 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 reject \"nonsense\"\n reject \"IHO B-12 3.0\"\n }\n\n bindings identifier {\n year -> year (string)\n volume -> volume (string)\n issue -> issue (string)\n }\n}\n","source_hash":"8d0d31907c36e5a398b7af8e11b434afb75588f6252e79cd975cb2c10a10ad8a","unicode_tables":"onigmo (Ruby 3.4.8)","compiler_version":"1.3.114","edition":1,"checksum":"sha256:52f91157a4d75ed1eef5cddd14789fcd907ec721384f88f5d3df77548dc307b9"}
|
|
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"}
|
data/data/parg/iho.parg
ADDED
|
@@ -0,0 +1,358 @@
|
|
|
1
|
+
# Port of lib/pubid/iho/parser.rb — IHO identifiers: letter series
|
|
2
|
+
# (S/P/M/B/C), a number with an optional suffix, and the full component
|
|
3
|
+
# tail (edition, supplement, part, annex, appendix + subnumber, volume,
|
|
4
|
+
# issue, year qualifier).
|
|
5
|
+
#
|
|
6
|
+
# == Component model (owner rulings, 2026-11-03)
|
|
7
|
+
#
|
|
8
|
+
# Every component below is a first-class semantic component: its own
|
|
9
|
+
# named capture, its own typed binding, independently addressable in
|
|
10
|
+
# the model, URN-encodable and matchable — never a regex/string suffix.
|
|
11
|
+
#
|
|
12
|
+
# component face capture binding type
|
|
13
|
+
# edition x.y.z (bare) edition string
|
|
14
|
+
# edition v1 / v5.1 (alias) edition_shorthand string (parse-only;
|
|
15
|
+
# the builder pads to
|
|
16
|
+
# x.y.0 — official IHO
|
|
17
|
+
# edition is dotted
|
|
18
|
+
# x.y.z WITHOUT a year)
|
|
19
|
+
# supplement Sup N (Suppl N) supplement string
|
|
20
|
+
# part Part X / Part S-102 part string (letter,
|
|
21
|
+
# number, or SERIES
|
|
22
|
+
# REFERENCE)
|
|
23
|
+
# part -X / -S-102 (short) part string (hyphenated)
|
|
24
|
+
# annex Annex A annex string
|
|
25
|
+
# appendix Appendix B appendix string
|
|
26
|
+
# appendix Appendix D-2 appendix_subnumber string (the -2)
|
|
27
|
+
# volume Vol. N volume string
|
|
28
|
+
# volume /N (short) volume string (the slash
|
|
29
|
+
# chain, P-1/21 or
|
|
30
|
+
# P-5/2020)
|
|
31
|
+
# volume N (bare, legacy) volume string (the yearbook
|
|
32
|
+
# year IS a volume —
|
|
33
|
+
# one serial-locator
|
|
34
|
+
# component)
|
|
35
|
+
# issue (N) / Issue N issue string
|
|
36
|
+
# year (2024) year string (the with-year
|
|
37
|
+
# qualifier on
|
|
38
|
+
# standards; NOT a
|
|
39
|
+
# serial locator)
|
|
40
|
+
#
|
|
41
|
+
# == Component-edition duality (owner ruling: "this can happen with any
|
|
42
|
+
# independently publishable artifacts")
|
|
43
|
+
#
|
|
44
|
+
# Supplement, part, annex, appendix and volume can be published on
|
|
45
|
+
# their own publication cycle, so EACH carries an optional
|
|
46
|
+
# `<kind>_edition` (+ `<kind>_year` qualifier) of its own, mutually
|
|
47
|
+
# exclusive with the base edition context:
|
|
48
|
+
#
|
|
49
|
+
# within-edition: IHO P-6 1.0.0 Vol. 2 (the volume rides
|
|
50
|
+
# the base's edition)
|
|
51
|
+
# separately-published: IHO P-6 Vol. 2 1.0.1 (the volume carries
|
|
52
|
+
# IHO S-98 Part A 1.0.0 its own edition;
|
|
53
|
+
# IHO S-158 Part S-102 0.2.0 the base is
|
|
54
|
+
# cited edition-less)
|
|
55
|
+
#
|
|
56
|
+
# In the URN the ed- segment attaches to the node it follows, so the
|
|
57
|
+
# same positional slot records both modes.
|
|
58
|
+
#
|
|
59
|
+
# The part has a COMPACT face, hyphenated onto the code — `IHO S-5-B`
|
|
60
|
+
# (lettered part), `IHO S-100-1` (numbered part), `IHO S-158-S-102`
|
|
61
|
+
# (series-reference part) — which both parses and renders; the
|
|
62
|
+
# canonical expanded face stays `IHO S-100 x.y.z Part 1`. Gluing a part
|
|
63
|
+
# onto the code without a separator (S-5A) is DISALLOWED as a form: it
|
|
64
|
+
# cannot extend to numbered parts without ambiguity (S-1001 = series
|
|
65
|
+
# 1001 vs series 100 part 1). The four lettered bases the corpus
|
|
66
|
+
# records (S-5A, S-5B, S-8A, S-8B) are LEGACY data spellings: they
|
|
67
|
+
# still parse as aliases (S-5A == S-5 Part A) but are never rendered;
|
|
68
|
+
# the owner rules later whether to reject them outright.
|
|
69
|
+
#
|
|
70
|
+
# Series-reference parts: a check standard applied to another IHO
|
|
71
|
+
# series cites the applied series as its part — `IHO S-158 0.2.0 Part
|
|
72
|
+
# S-102` (the wild glued `S-158-102` spelling is a legacy alias whose
|
|
73
|
+
# normalization to Part S-102 needs an IHO series table; the syntax
|
|
74
|
+
# alone cannot tell it from S-100-1 = Part 1, so it currently parses
|
|
75
|
+
# as the plain number part).
|
|
76
|
+
#
|
|
77
|
+
# Two main syntaxes per the owner ruling: `IHO S-100 1.0.0` (dated =
|
|
78
|
+
# edition-specific) and `IHO S-100` (undated = edition-non-specific).
|
|
79
|
+
# A year beside an edition is the with-year variant qualifier
|
|
80
|
+
# (`IHO S-100 1.0.0 Part X (2024)`), never a year-keyed docidentifier —
|
|
81
|
+
# year-keyed docidentifiers for edition-keyed products are wrong. The
|
|
82
|
+
# continuously-updated series have ONE serial locator, the volume:
|
|
83
|
+
# P-1 and P-6 are volume-keyed (`IHO P-1 Vol. 30 (1)`), and the
|
|
84
|
+
# yearbook year IS a volume (`IHO P-5 Vol. 2020`) — the bare year
|
|
85
|
+
# (`IHO P-5 2020`) and all year-faced forms are parse-only legacy
|
|
86
|
+
# aliases that bind into the volume component, never rendered.
|
|
87
|
+
#
|
|
88
|
+
# Aliases: "Suppl" (canonical face Sup, the M-2 spelling — why abbreviate
|
|
89
|
+
# by two letters when Annex and Appendix stay full-length), "App"/"Ap."
|
|
90
|
+
# (canonical face Appendix), the hyphenated compact part face (S-5-B ==
|
|
91
|
+
# S-5 Part B, S-100-1 == S-100 Part 1), the legacy glued lettered bases
|
|
92
|
+
# (S-5A, parse-only), "S-100 v1..v5.1" (edition shorthand), "Issue N"
|
|
93
|
+
# (canonical (N)), the bare year (canonical Vol. N).
|
|
94
|
+
#
|
|
95
|
+
# == URN segment grammar (positional, containment-ordered)
|
|
96
|
+
#
|
|
97
|
+
# The URN mirrors the containment tree, one semantic atom per segment:
|
|
98
|
+
# Part contains Annexes; Annex contains Appendices; a D-2 subnumber is
|
|
99
|
+
# a child atom of Appendix D. No key.value concatenations — every
|
|
100
|
+
# non-number component is a marker-prefixed segment whose marker is the
|
|
101
|
+
# lowercased human-face token (edition follows ISO's ed- precedent):
|
|
102
|
+
#
|
|
103
|
+
# urn:iho:<type>:<number>[:ed-<x.y.z>][:year-<yyyy>]
|
|
104
|
+
# [:sup-<n>[:ed-<x.y.z>][:year-<yyyy>]]
|
|
105
|
+
# [:part-<X>[:ed-<x.y.z>][:year-<yyyy>]]
|
|
106
|
+
# [:annex-<A>[...]]
|
|
107
|
+
# [:appendix-<B>[:<sub>][...]]
|
|
108
|
+
# [:vol-<n>[:issue-<n>][...]]
|
|
109
|
+
# [:year-<yyyy>]
|
|
110
|
+
#
|
|
111
|
+
# position segment value vocabulary containment
|
|
112
|
+
# -------- --------------- -------------------------- ------------------
|
|
113
|
+
# 1 <type> s / p / m / b / c namespace root
|
|
114
|
+
# 2 <number> digits + : suffix; may document code
|
|
115
|
+
# span bare segments until
|
|
116
|
+
# the first marker
|
|
117
|
+
# 3 ed-<x.y.z> dotted a.b.c edition qualifier;
|
|
118
|
+
# 4 year-<yyyy> 19xx/20xx ATTACHES TO THE
|
|
119
|
+
# NODE IT FOLLOWS: the
|
|
120
|
+
# base (no component
|
|
121
|
+
# before it) or the
|
|
122
|
+
# component whose
|
|
123
|
+
# segment precedes
|
|
124
|
+
# 5 sup-<n> 1*digit wraps the base
|
|
125
|
+
# 6 part-<X> letter (case kept), contains annexes
|
|
126
|
+
# digits [*letter], or a
|
|
127
|
+
# series reference
|
|
128
|
+
# [SPMBC]-<digits>
|
|
129
|
+
# 7 annex-<A> upper letter (case kept) contains appendices
|
|
130
|
+
# 8 appendix-<B> upper letter or digits contains subnumber
|
|
131
|
+
# 9 <sub> 1*digit, BARE, only child of appendix
|
|
132
|
+
# directly after appendix-
|
|
133
|
+
# 10 vol-<n> 1*digit (incl. yearbook contains issue
|
|
134
|
+
# years, Vol. 2020)
|
|
135
|
+
# 11 issue-<n> 1*digit, only after vol- child of volume
|
|
136
|
+
#
|
|
137
|
+
# The number occupies every leading bare segment up to the first
|
|
138
|
+
# marker, so a colon number (S-158:100) round-trips without escaping;
|
|
139
|
+
# after the markers the only bare segment allowed is the appendix
|
|
140
|
+
# subnumber in its own slot. Both the year qualifier and the volume are
|
|
141
|
+
# marker-tagged so neither can collide with a colon-number segment (the
|
|
142
|
+
# #637 hazard, kept under the positional scheme). Letters are
|
|
143
|
+
# case-preserved: part-A and part-a are distinct documents.
|
|
144
|
+
#
|
|
145
|
+
# Legacy 2.0.x spellings remain decodable but are never emitted: the
|
|
146
|
+
# bare a.b.c segment (edition), the dotted keys part./annex./suppl./
|
|
147
|
+
# ap./appendix./vol./issue. and the single-letter y. year tag (whose
|
|
148
|
+
# value decodes into the volume — the serial-locator unification).
|
|
149
|
+
#
|
|
150
|
+
# Edition 2: ruby#400's capture-flatten keeps text captures over
|
|
151
|
+
# reference-built rules as the matched text, so the v2 tree is the v1
|
|
152
|
+
# tree plus named leaves for non-captured structure.
|
|
153
|
+
|
|
154
|
+
grammar PubidIho version "0.2.0" edition 2 {
|
|
155
|
+
digit = %x30-39
|
|
156
|
+
upper = %x41-5A
|
|
157
|
+
lower = %x61-7A
|
|
158
|
+
letter = upper / lower
|
|
159
|
+
space = " "
|
|
160
|
+
dash = "-"
|
|
161
|
+
dot = "."
|
|
162
|
+
|
|
163
|
+
series = ("S" / "P" / "M" / "B" / "C") as type
|
|
164
|
+
number_suffix = (":" 1*digit)
|
|
165
|
+
number = (1*digit [number_suffix]) as number
|
|
166
|
+
# The compact part face, hyphenated onto the code: S-5-B (lettered),
|
|
167
|
+
# S-100-1 (numbered) and S-158-S-102 (series reference) — the dash
|
|
168
|
+
# replaces the old bare-glued suffix, so a number like S-1001 stays a
|
|
169
|
+
# whole number (the dash is what makes the part unambiguous). The
|
|
170
|
+
# dash is an inlined literal: a named dash ref here collides with the
|
|
171
|
+
# sequence's own dash node in the edition-2 tree.
|
|
172
|
+
compact_part = "-" ((("S" / "P" / "M" / "B" / "C") dash (1*digit)) / (1*digit [*letter]) / upper) as part
|
|
173
|
+
# LEGACY glued lettered bases (S-5A, S-5B, S-8A, S-8B in the corpus):
|
|
174
|
+
# parse-only aliases, never rendered. Kept because the records exist;
|
|
175
|
+
# the owner rules later whether to reject them.
|
|
176
|
+
glued = upper as part
|
|
177
|
+
|
|
178
|
+
# The official edition is the dotted x.y.z; "v1"/"v5.1" is the S-100
|
|
179
|
+
# shorthand (parse-only, the builder pads to x.y.0).
|
|
180
|
+
edition = space (1*digit dot 1*digit dot 1*digit) as edition
|
|
181
|
+
v_edition = space "v" ((1*digit) ["." (1*digit)]) as edition_shorthand
|
|
182
|
+
# The with-year qualifier on standards: a parenthesized year beside an
|
|
183
|
+
# edition. This is the ONLY base-level year capture — periodical
|
|
184
|
+
# years are volumes (the serial-locator unification).
|
|
185
|
+
year_qualifier = space "(" (("19" / "20") 2*digit) as year ")"
|
|
186
|
+
|
|
187
|
+
# The series-reference part value: a check standard applied to
|
|
188
|
+
# another IHO series (S-158 checks S-102). Ordered FIRST so "Part
|
|
189
|
+
# S-102" takes the series-reference branch, not the lone letter.
|
|
190
|
+
part_series_ref = (("S" / "P" / "M" / "B" / "C") dash (1*digit))
|
|
191
|
+
part_value = (part_series_ref / (1*digit [*letter]) / upper) as part
|
|
192
|
+
|
|
193
|
+
# Component-edition duality: each independently-publishable component
|
|
194
|
+
# may carry its own edition (+ year qualifier), mutually exclusive
|
|
195
|
+
# with the base edition context. The captures are position-scoped
|
|
196
|
+
# (<kind>_edition / <kind>_year) so the model knows which component
|
|
197
|
+
# the edition belongs to and the URN attaches ed- to the node it
|
|
198
|
+
# follows.
|
|
199
|
+
part = space "Part" space part_value [part_dated]
|
|
200
|
+
part_dated = {
|
|
201
|
+
part_edition_rule
|
|
202
|
+
[part_year_rule]
|
|
203
|
+
}
|
|
204
|
+
part_edition_rule = space (1*digit dot 1*digit dot 1*digit) as part_edition
|
|
205
|
+
part_year_rule = space "(" (("19" / "20") 2*digit) as part_year ")"
|
|
206
|
+
|
|
207
|
+
supplement = space ("Suppl" / "Sup") space (1*digit) as supplement [supplement_dated]
|
|
208
|
+
supplement_dated = {
|
|
209
|
+
supplement_edition_rule
|
|
210
|
+
[supplement_year_rule]
|
|
211
|
+
}
|
|
212
|
+
supplement_edition_rule = space (1*digit dot 1*digit dot 1*digit) as supplement_edition
|
|
213
|
+
supplement_year_rule = space "(" (("19" / "20") 2*digit) as supplement_year ")"
|
|
214
|
+
|
|
215
|
+
annex = space "Annex" space upper as annex [annex_dated]
|
|
216
|
+
annex_dated = {
|
|
217
|
+
annex_edition_rule
|
|
218
|
+
[annex_year_rule]
|
|
219
|
+
}
|
|
220
|
+
annex_edition_rule = space (1*digit dot 1*digit dot 1*digit) as annex_edition
|
|
221
|
+
annex_year_rule = space "(" (("19" / "20") 2*digit) as annex_year ")"
|
|
222
|
+
|
|
223
|
+
appendix_value = (upper / (1*digit)) as appendix
|
|
224
|
+
appendix_subnumber = dash (1*digit) as appendix_subnumber
|
|
225
|
+
appendix = space ("Appendix" / "App" / "Ap.") space appendix_value [appendix_subnumber] [appendix_dated]
|
|
226
|
+
appendix_dated = {
|
|
227
|
+
appendix_edition_rule
|
|
228
|
+
[appendix_year_rule]
|
|
229
|
+
}
|
|
230
|
+
appendix_edition_rule = space (1*digit dot 1*digit dot 1*digit) as appendix_edition
|
|
231
|
+
appendix_year_rule = space "(" (("19" / "20") 2*digit) as appendix_year ")"
|
|
232
|
+
|
|
233
|
+
volume = space "Vol." space (1*digit) as volume [volume_issue]
|
|
234
|
+
volume_issue = (space "Issue" space (1*digit) as issue) / (space "(" (1*digit) as issue ")")
|
|
235
|
+
# The volume's short face — the slash chain ("IHO P-1/21",
|
|
236
|
+
# "IHO P-5/2020"). The slash no longer joins the number.
|
|
237
|
+
volume_short = "/" ((1*digit) as volume) [volume_dated]
|
|
238
|
+
# LEGACY bare year ("IHO P-5 2024"): the yearbook year IS a volume,
|
|
239
|
+
# so a bare year binds INTO the volume component. Parse-only alias;
|
|
240
|
+
# the canonical print is "Vol. N".
|
|
241
|
+
volume_bare_year = space (("19" / "20") 2*digit) as volume
|
|
242
|
+
# The volume's own edition (+ year), shared by the Vol. and slash
|
|
243
|
+
# forms.
|
|
244
|
+
volume_dated = {
|
|
245
|
+
volume_edition_rule
|
|
246
|
+
[volume_year_rule]
|
|
247
|
+
}
|
|
248
|
+
volume_edition_rule = space (1*digit dot 1*digit dot 1*digit) as volume_edition
|
|
249
|
+
volume_year_rule = space "(" (("19" / "20") 2*digit) as volume_year ")"
|
|
250
|
+
|
|
251
|
+
# The edition slot accepts the dotted form or the v-shorthand; the
|
|
252
|
+
# with-year qualifier may sit right after it.
|
|
253
|
+
dated = {
|
|
254
|
+
(edition / v_edition)
|
|
255
|
+
[year_qualifier]
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
# The serial tail picks exactly one discriminator: the long volume
|
|
259
|
+
# (with its optional issue) or the legacy bare year — both bind the
|
|
260
|
+
# volume component, and both may carry the volume's own edition.
|
|
261
|
+
serial = {
|
|
262
|
+
(volume / volume_bare_year)
|
|
263
|
+
[volume_dated]
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
identifier = {
|
|
267
|
+
[("IHO" space)]
|
|
268
|
+
series
|
|
269
|
+
dash
|
|
270
|
+
number
|
|
271
|
+
[compact_part]
|
|
272
|
+
[glued]
|
|
273
|
+
[volume_short]
|
|
274
|
+
[dated]
|
|
275
|
+
[supplement]
|
|
276
|
+
[part]
|
|
277
|
+
[annex]
|
|
278
|
+
[appendix]
|
|
279
|
+
[serial]
|
|
280
|
+
[year_qualifier]
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
entry identifier: identifier
|
|
284
|
+
|
|
285
|
+
test {
|
|
286
|
+
accept "S-5"
|
|
287
|
+
accept "IHO S-5 Appendix 2"
|
|
288
|
+
accept "IHO B-12 3.0.0"
|
|
289
|
+
accept "IHO P-5 2024"
|
|
290
|
+
accept "P-5 2024"
|
|
291
|
+
accept "IHO P-5 Vol. 2024"
|
|
292
|
+
accept "IHO P-5/2024"
|
|
293
|
+
accept "IHO B-7 Vol. 2023"
|
|
294
|
+
accept "IHO P-1 Vol. 30"
|
|
295
|
+
accept "IHO P-1 Vol. 30 (2)"
|
|
296
|
+
accept "IHO P-1 Vol. 30 Issue 2"
|
|
297
|
+
accept "IHO P-1/21"
|
|
298
|
+
accept "IHO P-1/21 1.0.0"
|
|
299
|
+
accept "IHO S-100 5.0.0 Part 2"
|
|
300
|
+
accept "IHO S-98 1.0.0 Part A"
|
|
301
|
+
accept "IHO S-65 1.1.0 Annex A"
|
|
302
|
+
accept "IHO S-122 1.0.0 Appendix D-2"
|
|
303
|
+
accept "IHO S-52 4.0.0 Appendix 1"
|
|
304
|
+
accept "IHO M-2 Sup 1"
|
|
305
|
+
accept "IHO M-2 Suppl 6"
|
|
306
|
+
accept "IHO S-66 2.0.0 Sup 4"
|
|
307
|
+
accept "IHO S-5-B"
|
|
308
|
+
accept "IHO S-100-1"
|
|
309
|
+
accept "IHO S-100-1 1.0.0"
|
|
310
|
+
accept "IHO P-6-3 1.0.0"
|
|
311
|
+
accept "IHO S-5A"
|
|
312
|
+
accept "IHO S-5A 1.0.2"
|
|
313
|
+
accept "IHO S-5 1.0.2 Part A"
|
|
314
|
+
accept "IHO S-100 5.0.0 Part 2 (2024)"
|
|
315
|
+
accept "IHO S-100 v5.1"
|
|
316
|
+
accept "IHO S-100 v1"
|
|
317
|
+
accept "IHO S-100 1.0.0 (2024) Part A"
|
|
318
|
+
accept "IHO S-53 Ap. 1 1.0.0"
|
|
319
|
+
accept "IHO S-98 Part A 1.0.0"
|
|
320
|
+
accept "IHO S-158:100 1.0.0"
|
|
321
|
+
accept "IHO S-158:100 Part 2 1.0.0"
|
|
322
|
+
accept "IHO S-1001"
|
|
323
|
+
accept "IHO S-158 Part S-102 0.2.0"
|
|
324
|
+
accept "IHO S-158-S-102 0.2.0"
|
|
325
|
+
accept "IHO P-6 1.0.0 Vol. 2"
|
|
326
|
+
accept "IHO P-6 Vol. 2 1.0.1"
|
|
327
|
+
accept "IHO S-98 1.0.0 Annex A"
|
|
328
|
+
accept "IHO S-100 5.0.0 Sup 1 2.0.0"
|
|
329
|
+
reject "nonsense"
|
|
330
|
+
reject "IHO B-12 3.0"
|
|
331
|
+
reject "IHO P-5 1850"
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
bindings identifier {
|
|
335
|
+
type -> type (string)
|
|
336
|
+
number -> number (string)
|
|
337
|
+
part -> part (string)
|
|
338
|
+
part_edition -> part_edition (string)
|
|
339
|
+
part_year -> part_year (string)
|
|
340
|
+
annex -> annex (string)
|
|
341
|
+
annex_edition -> annex_edition (string)
|
|
342
|
+
annex_year -> annex_year (string)
|
|
343
|
+
appendix -> appendix (string)
|
|
344
|
+
appendix_subnumber -> appendix_subnumber (string)
|
|
345
|
+
appendix_edition -> appendix_edition (string)
|
|
346
|
+
appendix_year -> appendix_year (string)
|
|
347
|
+
supplement -> supplement (string)
|
|
348
|
+
supplement_edition -> supplement_edition (string)
|
|
349
|
+
supplement_year -> supplement_year (string)
|
|
350
|
+
edition -> edition (string)
|
|
351
|
+
edition_shorthand -> edition_shorthand (string)
|
|
352
|
+
year -> year (string)
|
|
353
|
+
volume -> volume (string)
|
|
354
|
+
volume_edition -> volume_edition (string)
|
|
355
|
+
volume_year -> volume_year (string)
|
|
356
|
+
issue -> issue (string)
|
|
357
|
+
}
|
|
358
|
+
}
|