pubid 2.0.3 → 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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 88bef3bd9d8e7bd7ef466bf6bc0d6ddf5d3a52d00778f98644b3530ff401f3c2
4
- data.tar.gz: 500430f50d0f0c52449d1f0ea4d6c28bf690257c5c240d23aceedf7b8c9fcb41
3
+ metadata.gz: bb0eb2441f1733fb2498a35955d3840cf1058c1cc2a0da5222633b80451258b2
4
+ data.tar.gz: 110f3275bbef45f8b5d956193ae4aee6647bb9ca57ff51b383451b1f575c964e
5
5
  SHA512:
6
- metadata.gz: 6e24987d7bbdf5477fcc064b4fbfc04c7f754aac4134ce417baeeacff785ec261d07ae482350b1c2f4d8ac21d4768bd56921bafa5860a85b681e08fffabbebc2
7
- data.tar.gz: 9a6e85627162ed1e86e749d6a05529eb83948e70ad7e467db29abf1339be597175958f61d0630b7a8f40b6fbc4e95e31c86d0cab11dcf10288d7f714ba32a25e
6
+ metadata.gz: 270e7d940a329eeb409bd65dc14dd325318ab11b81f702fc45e3c5186fd6d39d40cae0f0c286ab454900928d009dcf8073ddfcb4a6d803181223f6608c5d85c2
7
+ data.tar.gz: fd28a2998a2bb92a7812b7a435d5965e95991ad5f666d5c6f2d13e1171b8d4edaa6905e32b2b15124052816d0ee2873446d73c125e1b3d6ef26ca6d6b3e851a2
@@ -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"}
@@ -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
+ }