pubid 2.0.1 → 2.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (185) hide show
  1. checksums.yaml +4 -4
  2. data/data/parg/adobe.json +1 -1
  3. data/data/parg/amca.json +1 -1
  4. data/data/parg/ansi.json +1 -1
  5. data/data/parg/api.json +1 -1
  6. data/data/parg/ashrae.json +1 -1
  7. data/data/parg/asme.json +1 -1
  8. data/data/parg/astm.json +1 -1
  9. data/data/parg/bipm.json +1 -1
  10. data/data/parg/bsi.json +1 -1
  11. data/data/parg/ccsds.json +1 -1
  12. data/data/parg/cen_cenelec.json +1 -1
  13. data/data/parg/cie.json +1 -1
  14. data/data/parg/csa.json +1 -1
  15. data/data/parg/ecma.json +1 -1
  16. data/data/parg/etsi.json +1 -1
  17. data/data/parg/evs.json +1 -1
  18. data/data/parg/gost.json +1 -1
  19. data/data/parg/iana.json +1 -1
  20. data/data/parg/idf.json +1 -1
  21. data/data/parg/iec.json +1 -1
  22. data/data/parg/iho.json +1 -0
  23. data/data/parg/isbn.json +1 -1
  24. data/data/parg/itu.json +1 -1
  25. data/data/parg/jcgm.json +1 -1
  26. data/data/parg/jis.json +1 -1
  27. data/data/parg/nist.json +1 -1
  28. data/data/parg/oiml.json +1 -1
  29. data/data/parg/omg.json +1 -1
  30. data/data/parg/plateau.json +1 -1
  31. data/data/parg/tgpp.json +1 -1
  32. data/data/parg/un.json +1 -1
  33. data/lib/pubid/adobe/identifier.rb +1 -1
  34. data/lib/pubid/adobe/parser.rb +2 -113
  35. data/lib/pubid/amca/identifiers/base.rb +1 -1
  36. data/lib/pubid/amca/parser.rb +1 -145
  37. data/lib/pubid/ansi/identifier.rb +1 -1
  38. data/lib/pubid/ansi/parser.rb +1 -82
  39. data/lib/pubid/api/builder.rb +32 -1
  40. data/lib/pubid/api/identifier.rb +1 -1
  41. data/lib/pubid/api/parser.rb +1 -131
  42. data/lib/pubid/ashrae/identifiers/base.rb +1 -1
  43. data/lib/pubid/ashrae/parser.rb +3 -710
  44. data/lib/pubid/asme/builder.rb +6 -4
  45. data/lib/pubid/asme/identifier.rb +1 -2
  46. data/lib/pubid/asme/parser.rb +1 -328
  47. data/lib/pubid/astm/builder.rb +12 -3
  48. data/lib/pubid/astm/identifier.rb +1 -2
  49. data/lib/pubid/astm/parser.rb +1 -227
  50. data/lib/pubid/bipm/identifier.rb +8 -1
  51. data/lib/pubid/bipm/parser.rb +2 -224
  52. data/lib/pubid/bsi/builder.rb +2 -4
  53. data/lib/pubid/bsi/parser.rb +1 -666
  54. data/lib/pubid/bsi/single_identifier.rb +38 -1
  55. data/lib/pubid/calconnect/parser.rb +2 -40
  56. data/lib/pubid/ccsds/identifier.rb +1 -1
  57. data/lib/pubid/ccsds/parser.rb +1 -66
  58. data/lib/pubid/cen_cenelec/identifier.rb +16 -1
  59. data/lib/pubid/cen_cenelec/parser.rb +3 -136
  60. data/lib/pubid/cie/identifier.rb +1 -1
  61. data/lib/pubid/cie/parser.rb +3 -378
  62. data/lib/pubid/conformance.rb +1 -1
  63. data/lib/pubid/csa/builder.rb +41 -18
  64. data/lib/pubid/csa/identifier.rb +12 -4
  65. data/lib/pubid/csa/identifiers/amendment.rb +28 -0
  66. data/lib/pubid/csa/identifiers.rb +1 -0
  67. data/lib/pubid/csa/parser.rb +16 -397
  68. data/lib/pubid/doi/parser.rb +2 -37
  69. data/lib/pubid/easc/builder.rb +1 -1
  70. data/lib/pubid/easc/parser.rb +2 -70
  71. data/lib/pubid/ecma/CLAUDE.md +8 -1
  72. data/lib/pubid/ecma/identifier.rb +13 -8
  73. data/lib/pubid/ecma/parser.rb +2 -54
  74. data/lib/pubid/ecma/renderer.rb +3 -7
  75. data/lib/pubid/errors.rb +18 -13
  76. data/lib/pubid/etsi/builder.rb +8 -5
  77. data/lib/pubid/etsi/identifiers/base.rb +1 -1
  78. data/lib/pubid/etsi/parser.rb +1 -132
  79. data/lib/pubid/evs/identifier.rb +7 -0
  80. data/lib/pubid/evs/parser.rb +1 -8
  81. data/lib/pubid/evs.rb +1 -1
  82. data/lib/pubid/gb/identifier.rb +6 -0
  83. data/lib/pubid/gb/parser.rb +2 -51
  84. data/lib/pubid/gost/identifier.rb +9 -1
  85. data/lib/pubid/gost/parser.rb +4 -81
  86. data/lib/pubid/iala/parser.rb +2 -121
  87. data/lib/pubid/iana/identifier.rb +1 -1
  88. data/lib/pubid/iana/parser.rb +2 -24
  89. data/lib/pubid/identifier.rb +78 -1
  90. data/lib/pubid/idf/builder.rb +42 -0
  91. data/lib/pubid/idf/identifier.rb +1 -1
  92. data/lib/pubid/idf/parser.rb +1 -137
  93. data/lib/pubid/idf.rb +1 -2
  94. data/lib/pubid/iec/builder.rb +158 -50
  95. data/lib/pubid/iec/identifier.rb +1 -1
  96. data/lib/pubid/iec/parser.rb +3 -430
  97. data/lib/pubid/ieee/aiee/identifier.rb +2 -1
  98. data/lib/pubid/ieee/aiee.rb +0 -1
  99. data/lib/pubid/ieee/builder.rb +2 -2
  100. data/lib/pubid/ieee/identifiers/base.rb +1 -1
  101. data/lib/pubid/ieee/ire/identifier.rb +2 -1
  102. data/lib/pubid/ieee/ire.rb +0 -1
  103. data/lib/pubid/ieee/nesc.rb +0 -1
  104. data/lib/pubid/ieee/parser.rb +1 -1257
  105. data/lib/pubid/ietf/identifiers/base.rb +17 -1
  106. data/lib/pubid/ietf/parser.rb +2 -47
  107. data/lib/pubid/ietf/renderer.rb +17 -2
  108. data/lib/pubid/iho/CLAUDE.md +89 -0
  109. data/lib/pubid/iho/builder.rb +4 -1
  110. data/lib/pubid/iho/identifiers/base.rb +28 -2
  111. data/lib/pubid/iho/renderer.rb +8 -0
  112. data/lib/pubid/iho/urn_generator.rb +11 -1
  113. data/lib/pubid/iho/urn_parser.rb +21 -11
  114. data/lib/pubid/iho.rb +0 -1
  115. data/lib/pubid/isbn/identifier.rb +1 -1
  116. data/lib/pubid/isbn/parser.rb +2 -31
  117. data/lib/pubid/iso/builder.rb +1 -1
  118. data/lib/pubid/iso/identifiers/directives.rb +6 -3
  119. data/lib/pubid/iso/identifiers/guide.rb +6 -3
  120. data/lib/pubid/iso/identifiers/international_workshop_agreement.rb +6 -3
  121. data/lib/pubid/iso/normalizer.rb +1 -1
  122. data/lib/pubid/iso/parser.rb +1 -539
  123. data/lib/pubid/iso/supplement_identifier.rb +6 -3
  124. data/lib/pubid/iso/utilities.rb +4 -5
  125. data/lib/pubid/iso.rb +1 -19
  126. data/lib/pubid/itu/builder.rb +36 -20
  127. data/lib/pubid/itu/identifiers/base.rb +15 -2
  128. data/lib/pubid/itu/parser.rb +1 -775
  129. data/lib/pubid/jcgm/builder.rb +35 -0
  130. data/lib/pubid/jcgm/parser.rb +1 -151
  131. data/lib/pubid/jcgm.rb +1 -2
  132. data/lib/pubid/jis/builder.rb +18 -29
  133. data/lib/pubid/jis/identifier.rb +1 -1
  134. data/lib/pubid/jis/parser.rb +1 -128
  135. data/lib/pubid/nist/builder.rb +5 -1
  136. data/lib/pubid/nist/caster.rb +13 -3
  137. data/lib/pubid/nist/identifiers/base.rb +37 -2
  138. data/lib/pubid/nist/identifiers/circular.rb +2 -2
  139. data/lib/pubid/nist/identifiers/circular_supplement.rb +2 -2
  140. data/lib/pubid/nist/identifiers/commercial_standards_monthly.rb +2 -2
  141. data/lib/pubid/nist/identifiers/crpl_report.rb +2 -2
  142. data/lib/pubid/nist/identifiers/handbook.rb +2 -2
  143. data/lib/pubid/nist/identifiers/internal_report.rb +2 -2
  144. data/lib/pubid/nist/identifiers/miscellaneous_publication.rb +2 -2
  145. data/lib/pubid/nist/identifiers/monograph.rb +2 -2
  146. data/lib/pubid/nist/identifiers/report.rb +2 -2
  147. data/lib/pubid/nist/parser.rb +19 -775
  148. data/lib/pubid/nist/router.rb +4 -1
  149. data/lib/pubid/nist/supplement_identifier.rb +2 -2
  150. data/lib/pubid/oasis/parser.rb +2 -16
  151. data/lib/pubid/ogc/parser.rb +2 -26
  152. data/lib/pubid/oiml/identifiers/certification_system.rb +7 -0
  153. data/lib/pubid/oiml/identifiers/dual_published.rb +2 -2
  154. data/lib/pubid/oiml/parser.rb +1 -303
  155. data/lib/pubid/oiml.rb +1 -2
  156. data/lib/pubid/omg/identifier.rb +6 -1
  157. data/lib/pubid/omg/parser.rb +2 -76
  158. data/lib/pubid/parser.rb +5 -4
  159. data/lib/pubid/parsers/mr_string.rb +1 -1
  160. data/lib/pubid/plateau/parser.rb +1 -66
  161. data/lib/pubid/plateau.rb +1 -2
  162. data/lib/pubid/renderers/directives_renderer.rb +1 -1
  163. data/lib/pubid/renderers/iwa_renderer.rb +1 -1
  164. data/lib/pubid/renderers/publisher_stripper.rb +82 -0
  165. data/lib/pubid/renderers/supplement_renderer.rb +1 -1
  166. data/lib/pubid/renderers.rb +1 -0
  167. data/lib/pubid/sae/parser.rb +1 -48
  168. data/lib/pubid/tgpp/identifier.rb +1 -1
  169. data/lib/pubid/tgpp/parser.rb +2 -59
  170. data/lib/pubid/un/identifier.rb +1 -1
  171. data/lib/pubid/un/parser.rb +1 -18
  172. data/lib/pubid/version.rb +1 -1
  173. data/lib/pubid/w3c/parser.rb +2 -27
  174. data/lib/pubid/xsf/identifier.rb +10 -6
  175. data/lib/pubid/xsf/parser.rb +3 -31
  176. data/lib/pubid/xsf/renderer.rb +2 -4
  177. data/lib/pubid.rb +8 -9
  178. metadata +6 -23
  179. data/lib/pubid/ieee/aiee/parser.rb +0 -130
  180. data/lib/pubid/ieee/ire/parser.rb +0 -109
  181. data/lib/pubid/ieee/nesc/parser.rb +0 -155
  182. data/lib/pubid/iho/parser.rb +0 -68
  183. data/lib/pubid/parser/common_parse_methods.rb +0 -13
  184. data/lib/pubid/parser/common_parse_rules.rb +0 -56
  185. data/lib/pubid/parser/grammar.rb +0 -96
@@ -1,547 +1,9 @@
1
- require "parslet"
2
1
  # frozen_string_literal: true
3
2
 
4
3
  module Pubid
5
4
  module Iso
6
- class Parser < ::Pubid::Parser::Grammar
7
- include ::Pubid::Parser::CommonParseRules
8
- include ::Pubid::Parser::CommonParseMethods
9
-
5
+ class Parser
10
6
  DASH_CHARS = ["-", "‑", "‐"].freeze
11
-
12
- # Supplement identifier type keys (kept as a hard-coded list to match
13
- # the previous identifier split; only the base identifier registry
14
- # is auto-discovered from the Identifiers namespace).
15
- SUPPLEMENT_TYPE_KEYS = %i[amd cor suppl ext add].freeze
16
-
17
- # We need to sort by length to match longest first because that's how Parslet works
18
- TYPED_STAGES = Pubid::Iso.identifier_types
19
- .reject { |k| SUPPLEMENT_TYPE_KEYS.include?(k.type[:key]) }
20
- .flat_map { |k| k.const_defined?(:TYPED_STAGES) ? k.const_get(:TYPED_STAGES) : [] }
21
- .map(&:abbr).flatten.sort_by(&:length).reverse
22
- TYPED_STAGES_SUPPLEMENTS = Pubid::Iso.identifier_types
23
- .select { |k| SUPPLEMENT_TYPE_KEYS.include?(k.type[:key]) }
24
- .flat_map { |k| k.const_defined?(:TYPED_STAGES) ? k.const_get(:TYPED_STAGES) : [] }
25
- .map(&:abbr).flatten.sort_by(&:length).reverse
26
-
27
- root :identifier
28
-
29
- # TC documents must come first since they start with "ISO/"
30
- # and we need to distinguish them from regular ISO/IEC identifiers
31
- rule(:identifier) do
32
- bare_tc_document |
33
- nsb_iso_identifier |
34
- tc_document |
35
- directives_identifiers |
36
- jcgm_identifier |
37
- iso_r_supplement_identifier |
38
- iso_r_identifier |
39
- supplement_supplement_supplement_identifier |
40
- supplement_supplement_identifier |
41
- supplement_identifier |
42
- joint_identifier |
43
- identifier_copublishers
44
- end
45
-
46
- # JCGM identifiers (Joint Committee for Guides in Metrology)
47
- # JCGM 200:2008(F)
48
- rule(:jcgm_identifier) do
49
- str("JCGM").as(:publisher) >> space >>
50
- second_part >> third_part
51
- end
52
-
53
- # TC Document: ISO/TC 184/SC 4/WG 3 N 123
54
- # ISO/TC 184 N 100
55
- # ISO/JTC 1 N 456
56
- # ISO/TC 184/SC 4 N 789 (TC and SC only, no WG)
57
- rule(:tc_document) do
58
- # Accept either "ISO/TC 184…" or the lenient space form "ISO TC 184…"
59
- # (the latter was valid in pubid 1.x via an optional slash).
60
- prefix_sole_publisher >> (str("/") | space) >> tc_type >> space >> tc_number.as(:tc_number) >>
61
- tc_subcommittee_part.maybe >>
62
- space >> str("N") >> space? >> digits.as(:number) >>
63
- (str(":") >> year_digits.as(:year)).maybe
64
- end
65
-
66
- # Bare TC document reference (pubid-iso#285): "184/SC 4/WG 12 N10291"
67
- # — the ISO/TC route without the ORIGINATOR prefix; the builder
68
- # canonicalizes the publisher to ISO. The SC segment is required so
69
- # bare numbers cannot leak into the route.
70
- rule(:bare_tc_document) do
71
- digits.as(:tc_number) >>
72
- str("/") >> sc_type >> space >> digits.as(:sc_number) >>
73
- (str("/") >> wg_type >> space >> digits.as(:wg_number)).maybe >>
74
- space >> str("N") >> space? >> digits.as(:number) >>
75
- (str(":") >> year_digits.as(:year)).maybe
76
- end
77
-
78
- rule(:tc_subcommittee_part) do
79
- # Full path: TC/SC 4/WG 3
80
- (str("/") >> sc_type >> space >> digits.as(:sc_number) >> str("/") >>
81
- wg_type >> space >> digits.as(:wg_number)) |
82
- # TC and SC only: TC/SC 4 N 789
83
- (str("/") >> sc_type >> space >> digits.as(:sc_number))
84
- end
85
-
86
- rule(:tc_type) do
87
- array_to_str(Identifiers::TcDocument::TC_TYPES).as(:tc_type)
88
- end
89
-
90
- rule(:sc_type) do
91
- # "SC" plus the "SC/QC" quality-committee variant
92
- # (e.g. ISO/TC 184/SC/QC 4 N 246). Longest first for Parslet.
93
- (str("SC/QC") | str("SC")).as(:sc_type)
94
- end
95
-
96
- rule(:wg_type) do
97
- array_to_str(Identifiers::TcDocument::WG_TYPES).as(:wg_type)
98
- end
99
-
100
- rule(:tc_number) do
101
- digits
102
- end
103
-
104
- # ISO/R 947:1969 (legacy Recommendation without supplement)
105
- rule(:iso_r_identifier) do
106
- str("ISO/R").as(:iso_r_prefix) >> space >>
107
- iso_r_second_part >> third_part
108
- end
109
-
110
- # ISO/R 947:1969/Add 1:1969 (legacy Recommendation with supplement)
111
- # Also handles: ISO/R 91-1970 — Addendum 1 (dash for year, em-dash + word)
112
- rule(:iso_r_supplement_identifier) do
113
- (
114
- str("ISO/R").as(:iso_r_prefix) >> space >> iso_r_second_part
115
- ).as(:base) >>
116
- iso_r_supplement_separator >>
117
- supplement_type_with_stage >>
118
- space? >> second_part >> third_part
119
- end
120
-
121
- # ISO/R supplements can use "/" or em-dash "—" or " - " as separator
122
- rule(:iso_r_supplement_separator) do
123
- str("/") | (space? >> str("—") >> space?) | (space >> str("-") >> space)
124
- end
125
-
126
- # Special second_part for ISO/R that treats dash as date separator only
127
- rule(:iso_r_second_part) do
128
- number.as(:number_with_part) >>
129
- stage_iteration.maybe >>
130
- space? >> date.maybe
131
- end
132
-
133
- # ISO 8601-1:2019
134
- # ISO/R 947:1969 (legacy Recommendation format)
135
- rule(:prefix_sole_publisher) do
136
- (str("ISO") | str("IEC")).as(:publisher)
137
- end
138
-
139
- # ISO/SAE PAS 22736:2021
140
- # ISO/R 947:1969 (legacy Recommendation - special handling)
141
- rule(:prefix_with_copublishers) do
142
- # Try ISO/R first (must be followed by space + number to avoid confusion with copublishers)
143
- (str("ISO/R").as(:iso_r_prefix) >> space) |
144
- # Otherwise normal publisher with optional copublishers
145
- (prefix_sole_publisher >> space? >> copublishers.maybe)
146
- end
147
-
148
- ORGANIZATIONS = %w[
149
- ISO IEC IEEE CIW SAE CIE ASME ASTM OECD ISO HL7 CEI UNDP
150
- ].freeze
151
- rule(:copublishers) do
152
- (str("/") >> space? >> array_to_str(ORGANIZATIONS).as(:copublisher)).repeat.as(:copublishers)
153
- end
154
-
155
- rule(:number_with_part) do
156
- (number >> part_and_subpart.maybe).as(:number_with_part)
157
- end
158
-
159
- rule(:number) do
160
- match('\d').repeat(1, 5)
161
- end
162
-
163
- rule(:date) do
164
- # :2005-02 or :-- (undated reference — ISO/IEC undated-reference form,
165
- # e.g. ISO 16634:--, also accepted as the em-dash variant ISO 16634:—)
166
- (str(":") | dash) >>
167
- (
168
- (str("--") | str("—")).as(:undated_marker) |
169
- (year_digits >>
170
- (dash >> month_digits).maybe >>
171
- (dash >> day_digits).maybe
172
- ).as(:date)
173
- ).maybe
174
- end
175
-
176
- rule(:part_and_subpart) do
177
- # Modern parts
178
- # ISO 105-A01:1989
179
- # ISO/IEC/IEEE 8802-1AB
180
- # ISO/IEC TR 29110-5-1-1
181
-
182
- # Legacy parts
183
- # ISO 31/0-1974
184
- # ISO 105/F (also known as ISO 105-F)
185
- # ISO 5843/6 (also known as ISO 5843-6)
186
-
187
- # Modern parts can have subparts using dash
188
- # the "space?" needed to handle "ISO/TS 10303- 1751:2014"
189
- (
190
- dash >> space? >>
191
- # matches a part
192
- match('\w').repeat(1) >>
193
- # matches a subpart, e.g. "A01" or "1-2" (yes we treat {5}-{1-1} as part and subpart)
194
- (dash >> match('\w').repeat(1)).repeat.maybe
195
- ) |
196
- # Legacy parts do not have subparts
197
- # the "/" to handle old style parts: "ISO 5843/6"
198
- # Guard: don't match supplement type names (Amd, Cor, Sup, etc.)
199
- (
200
- str("/") >> space? >>
201
- supplement_type_with_stage.absent? >>
202
- # matches a part
203
- match('\w').repeat(1)
204
- )
205
- end
206
-
207
- rule(:all_parts) do
208
- str("(all parts)").as(:all_parts)
209
- end
210
-
211
- rule(:type_with_stage) do
212
- # "DTR"
213
- # "PRF PAS"
214
- # "PRF"
215
- # "PAS"
216
- array_to_str(TYPED_STAGES).as(:type_with_stage) >>
217
- (match('\d').as(:stage_iteration) >> space).maybe
218
- end
219
-
220
- rule(:language) do
221
- # ISO 8601-1:2019(en,fr)
222
- # ISO 8601-1:2019(E/F)
223
- str("(") >>
224
- (
225
- # parse 2-char language codes: ru,en,fr,de,ar,es
226
- (match["a-z"].repeat(1) >> str(",").maybe) |
227
- # parse single language codes: R/E/F or R,E,F
228
- (match["EFARDS"] >> (str("/") | str(",")).maybe)
229
- ).repeat.as(:languages) >>
230
- str(")")
231
- end
232
-
233
- EDITION_STRINGS = %w[Edition Ed. ED Ed].freeze
234
- rule(:edition) do
235
- # Capture the entire edition text for exact reproduction
236
- (array_to_str(EDITION_STRINGS) >> space? >> digits.maybe).as(:edition)
237
- end
238
-
239
- rule(:stage_iteration) do
240
- # "ISO 11243.1"
241
- str(".") >> match('\d').as(:stage_iteration)
242
- end
243
-
244
- # Modern identifiers use ':' as year identifier, e.g. "ISO 8601-1:2019"
245
- # Legacy identifiers use '-' as year identifier, e.g. "ISO 31/0-1974"
246
- rule(:second_part) do
247
- number_with_part >>
248
- stage_iteration.maybe >>
249
- space? >> date.maybe
250
- end
251
-
252
- rule(:third_part_edition) do
253
- space? >> edition.maybe
254
- end
255
-
256
- rule(:third_part) do
257
- # End of the identifier, we can have language, edition, or all parts
258
- third_part_edition >> language.maybe >> space? >> all_parts.maybe
259
- end
260
-
261
- # prefix sole or copublishers with type and stage
262
- # ISO/WD TR 23642
263
- # ISO/NP TS 20594-1
264
- # ISO/PRF PAS 22596
265
- # ISO/ASTM DTR 52905
266
- # ISO/IEC WD TS 25025
267
- #
268
- ## SUPPORTED ABERRATION: ISO TR 16401-2
269
- ## SUPPORTED ABERRATION: ISO/IEC/TS 24192-1
270
- rule(:identifier_copublishers) do
271
- identifier_copublishers_no_third >> third_part
272
- end
273
-
274
- # TODO: Support parsing Russian style identifiers
275
- rule(:guide_prefix) do
276
- str("Guide") | str("GUIDE") # | str("Руководство") | str("Руководства")
277
- end
278
-
279
- rule(:identifier_copublishers_no_third) do
280
- # Guide ISO/CEI 51:1999
281
- (guide_prefix.as(:type_with_stage_fr) >> space).maybe >>
282
- # maybe prefix_with_copublishers to handle IWA
283
- prefix_with_copublishers.maybe >> space? >> str("/").maybe >>
284
- type_with_stage.maybe >>
285
- space.maybe >>
286
- second_part >> third_part_edition
287
- end
288
-
289
- # For joint identifiers, we do not treat it as a supplementary identifier
290
- # (hence not a base)
291
- # ISO only supports IDF in joint identifiers
292
- # ISO 5537|IDF 26
293
- # ISO 17678|IDF 202:2010
294
- # ISO/TS 4985:2023 | IDF/RM 255
295
- # ISO 4214:2022 | IDF 254:2022
296
- rule(:joint_identifier) do
297
- identifier_copublishers_no_third.as(:base) >>
298
- space? >> str("|") >> space? >>
299
- scope { idf_identifier }.as(:joint_identifier)
300
- end
301
-
302
- rule(:idf_identifier) do
303
- Idf::Parser.new.identifier
304
- end
305
-
306
- # NSB ISO identifiers - National Body prefixed ISO identifiers
307
- # FprISO 105-A03
308
- # FprISO/IEC 17029
309
- # WD/ISO 10360-2
310
- # WD/ISO 10360-5:2000
311
- rule(:nsb_iso_identifier) do
312
- # FprISO, FprISO/IEC - stage prefix directly attached to publisher
313
- (str("Fpr").as(:nsb_stage) >>
314
- prefix_sole_publisher >> space? >> copublishers.maybe >>
315
- space.maybe >>
316
- type_with_stage.maybe >>
317
- space.maybe >>
318
- second_part >> third_part) |
319
- # WD/ISO - stage prefix with slash before publisher
320
- (str("WD").as(:nsb_stage) >> str("/") >>
321
- prefix_sole_publisher >> space? >> copublishers.maybe >>
322
- space.maybe >>
323
- type_with_stage.maybe >>
324
- space.maybe >>
325
- second_part >> third_part)
326
- end
327
-
328
- # TODO: Do something with NSB ISO identifiers like "FprISO", "WD/ISO"
329
- # Guide ISO/CEI 51:1999
330
- # FprISO 105-A03
331
- # FprISO/IEC 17029
332
- # WD/ISO 10360-5:2000
333
- # ISO 4918:2016+A1:2018
334
- # rule(:nsb_iso_identifier) do
335
- # str("Fpr").as(:stage).maybe >>
336
- # # Withdrawn e.g: WD/ISO 10360-5:2000
337
- # str("WD/").maybe >>
338
- # # for French and Russian PubIDs starting with Guide type
339
- # (guide_prefix.as(:type) >> space).maybe >>
340
- # (stage.as(:stage) >> space).maybe >>
341
- # (typed_stage.as(:stage) >> space).maybe >>
342
- # (originator >> (space | str("/"))).maybe >>
343
- # (tc_document_body | std_document_body | (dir_document_body >>
344
- # (str(" + ") >> (originator >> space >> dir_document_body).as(:dir_joint_document)).maybe))
345
- # end
346
-
347
- rule(:supplement_type_with_stage) do
348
- # "DAM"
349
- # "NP Amd"
350
- array_to_str(TYPED_STAGES_SUPPLEMENTS).as(:type_with_stage)
351
- end
352
-
353
- # ISO 8601-1:2019/Amd 2:2024
354
- # ISO/IEC 10646-1:1993/pDCOR.2 (legacy dot-prefixed format)
355
- rule(:supplement_identifier_no_third) do
356
- identifier_copublishers_no_third.as(:base) >>
357
- str("/") >> supplement_type_with_stage >>
358
- # The trailing number/date is optional: some draft supplements have no
359
- # number yet, e.g. "ISO/IEC 9579/WD Amd".
360
- ((space? >> second_part) | (str(".") >> digits.as(:number)) | (space? >> date)).maybe
361
- end
362
-
363
- rule(:supplement_identifier) do
364
- supplement_identifier_no_third >> third_part
365
- end
366
-
367
- # ISO/IEC 13818-1:2015/Amd 3:2016/Cor 1:2017
368
- # ISO/IEC 19794-7:2014/Amd 1:2015/CD Cor 1
369
- # ISO/IEC 10646-1:1993/pDCOR.2 (legacy dot-prefixed format)
370
- rule(:supplement_supplement_identifier) do
371
- supplement_identifier_no_third.as(:base) >>
372
- str("/") >> supplement_type_with_stage >>
373
- ((space? >> second_part >> third_part) | (str(".") >> digits.as(:number) >> third_part))
374
- end
375
-
376
- # ISO 12345:2020/Amd 1:2021/Cor 1:2022/Amd 2:2023 (three-level supplement)
377
- rule(:supplement_supplement_supplement_identifier) do
378
- supplement_supplement_identifier.as(:base) >>
379
- str("/") >> supplement_type_with_stage >>
380
- ((space? >> second_part >> third_part) | (str(".") >> digits.as(:number) >> third_part))
381
- end
382
-
383
- # ISO/IEC DIR
384
- # ISO/IEC DIR 1
385
- # ISO/IEC DIR 2:2022
386
- rule(:directives_identifier) do
387
- directives_identifier_no_third >> third_part.maybe >> space? >> date.maybe
388
- end
389
-
390
- # ISO/IEC JTC 1 DIR (JTC 1 Directives)
391
- rule(:directives_publisher_subgroup) do
392
- str("JTC 1").as(:subgroup)
393
- end
394
-
395
- # Special number_with_part rule for Directives to handle variants
396
- # We treat the variant as `part` of the number_with_part
397
- rule(:directives_number_with_part) do
398
- (number >> directives_part_and_subpart.maybe).as(:number_with_part)
399
- end
400
-
401
- # ISO/IEC DIR 1 IEC (IEC version of the ISO/IEC DIR 1)
402
- # ISO/IEC DIR 2 ISO:2022 (ISO version of the ISO/IEC DIR 2)
403
- # But NOT: ISO/IEC DIR 1 ISO SUP:2022 (ISO is supplement publisher)
404
- # "1 IEC"
405
- # "2 ISO"
406
- rule(:directives_part_and_subpart) do
407
- # Only match ISO/IEC if NOT followed by "/" (dual publisher) or supplement keywords
408
- space >> (str("ISO") | str("IEC")) >> str("/").absent? >> (space >> str("SUP")).absent?
409
- end
410
-
411
- DIRECTIVES_TYPED_STAGES = Identifiers::Directives::TYPED_STAGES.map(&:abbr).flatten.sort_by(&:length).reverse
412
- rule(:directives_identifier_no_third) do
413
- prefix_with_copublishers >> space? >>
414
- (directives_publisher_subgroup >> space).maybe >>
415
- array_to_str(DIRECTIVES_TYPED_STAGES).as(:type_with_stage) >>
416
- # The subgroup may also follow the type, e.g. "ISO/IEC DIR JTC 1"
417
- # (canonical form is "ISO/IEC JTC 1 DIR"). Guard against a trailing
418
- # supplement, where "JTC 1" is the supplement publisher instead
419
- # (e.g. "ISO/IEC DIR JTC 1 SUP").
420
- (space >> directives_publisher_subgroup >> (space >> str("SUP")).absent?).maybe >>
421
- (
422
- (space >> directives_number_with_part).maybe >>
423
- (str(":") >> date).maybe
424
- ).maybe
425
- end
426
-
427
- rule(:directives_supplement_identifier) do
428
- directives_identifier_no_third.as(:base) >> space? >> directives_supplement_part
429
- end
430
-
431
- DIRECTIVES_SUPPLEMENTS_TYPED_STAGES = Identifiers::DirectivesSupplement::TYPED_STAGES.map(&:abbr).flatten.sort_by(&:length).reverse
432
-
433
- rule(:directives_supplement_part_no_third) do
434
- # ISO/IEC DIR 1 ISO SUP
435
- # ISO/IEC DIR 2 ISO SUP:2022
436
- # ISO/IEC DIR JTC 1 SUP:2021
437
- # ISO/IEC Directives, Part 1 -- Consolidated ISO Supplement
438
- (space? >> str("--") >> space? >> str("Consolidated") >> space).maybe >>
439
- (str("ISO/IEC") | str("ISO") | str("IEC") | str("JTC 1")).as(:publisher) >>
440
- (space >> array_to_str(DIRECTIVES_SUPPLEMENTS_TYPED_STAGES).as(:type_with_stage)) >>
441
- date.maybe
442
- end
443
-
444
- rule(:directives_supplement_part) do
445
- directives_supplement_part_no_third >> third_part.maybe
446
- end
447
-
448
- # ISO/IEC DIR 1 + IEC SUP:2016-05
449
- # ISO/IEC DIR 1:2022 + IEC SUP:2022
450
- rule(:directives_bundled_identifier) do
451
- (
452
- directives_identifier_no_third >>
453
- (third_part >> space?).maybe >>
454
- (date >> space?).maybe
455
- ).as(:base_document) >>
456
- (
457
- str("+ ") >>
458
- directives_supplement_part_no_third.as(:supplement)
459
- ).repeat(1).as(:supplements)
460
- end
461
-
462
- rule(:directives_identifiers) do
463
- directives_bundled_identifier |
464
- directives_supplement_identifier |
465
- directives_identifier
466
- end
467
-
468
- rule(:dash) do
469
- DASH_CHARS.map { |char| str(char) }.reduce(:|)
470
- end
471
-
472
- # rule(:tctype) do
473
- # # tc-types
474
- # array_to_str(TCTYPES)
475
- # end
476
-
477
- # rule(:sctype) do
478
- # str("SC")
479
- # end
480
-
481
- # rule(:wgtype) do
482
- # array_to_str(WGTYPES)
483
- # end
484
-
485
- # rule(:roman_numerals) do
486
- # str("CD").absent? >> array_to_str(%w[I V X L C D M]).repeat(1).as(:roman_numerals)
487
- # end
488
-
489
- # rule(:part_matcher) do
490
- # year_digits.absent? >>
491
- # supplements.absent? >>
492
- # staged_addenda.absent? >> ((roman_numerals >> digits.absent?) | match['[\dA-Z]'].repeat(1)).as(:part)
493
- # end
494
-
495
- # rule(:supplement) do
496
- # ((str("/") | space).maybe >>
497
- # (((stage.as(:typed_stage) >> space).maybe >> supplements.as(:type)) |
498
- # staged_supplement.as(:typed_stage)) >>
499
- # (space | str(".")).repeat(1).maybe >>
500
- # digits.as(:number).maybe >>
501
- # (str(".") >> digits.as(:iteration)).maybe >>
502
- # ((str(":") | dash) >> digits.as(:year)).maybe).repeat(1).as(:supplements)
503
- # end
504
-
505
- # # Parse technical committee documents
506
- # rule(:tc_document_body) do
507
- # (tctype.as(:tctype) >> str("/").maybe).repeat >> space >> digits.as(:tcnumber) >>
508
- # (str("/") >> (
509
- # ((sctype.as(:sctype) >> space >> digits.as(:scnumber) >> str("/")).maybe >>
510
- # wgtype.as(:wgtype) >> space >> digits.as(:wgnumber)) |
511
- # (sctype.as(:sctype) >> (space | str("/") >> wgtype.as(:wgtype) >> space) >> digits.as(:scnumber))
512
- # )).maybe >>
513
- # space >> str("N") >> space? >> digits.as(:number)
514
- # end
515
-
516
- # rule(:dir_supplement_edition) do
517
- # space >> (str("Edition") | str("Ed")) >> space >> digits.as(:edition)
518
- # end
519
-
520
- # rule(:dir_document_body) do
521
- # ((str("DIR") | str("Directives Part") | str("Directives, Part") | str("Directives,")).as(:type) >> space).maybe >>
522
- # (str("JTC").as(:dirtype) >> space).maybe >>
523
- # (digits.as(:number) >> (str(":") >> year).maybe).maybe >>
524
- # (space >> str("DIR").as(:jtc_dir) >> (str(":") >> year).maybe).maybe >>
525
- # (str(" -- Consolidated").maybe >> (str("").as(:mark) >> space? >>
526
- # (organization.as(:publisher) >> space?).maybe >>
527
- # array_to_str(DIR_SUPPLEMENTS) >> (str(":") >> (year >> (dash >> month_digits.as(:month)).maybe)).maybe >>
528
- # dir_supplement_edition.maybe).repeat(1).as(:supplements)).maybe >>
529
- # # parse identifiers with publisher at the end, e.g. "ISO/IEC DIR 2 ISO"
530
- # (space >> organization.as(:publisher) >> (str(":") >> year).maybe).as(:edition).maybe
531
- # end
532
-
533
- # rule(:identifier) do
534
- # str("Fpr").as(:stage).maybe >>
535
- # # Withdrawn e.g: WD/ISO 10360-5:2000
536
- # str("WD/").maybe >>
537
- # # for French and Russian PubIDs starting with Guide type
538
- # (guide_prefix.as(:type) >> space).maybe >>
539
- # (stage.as(:stage) >> space).maybe >>
540
- # (typed_stage.as(:stage) >> space).maybe >>
541
- # (originator >> (space | str("/"))).maybe >>
542
- # (tc_document_body | std_document_body | (dir_document_body >>
543
- # (str(" + ") >> (originator >> space >> dir_document_body).as(:dir_joint_document)).maybe))
544
- # end
545
7
  end
546
8
  end
547
9
  end
@@ -56,9 +56,12 @@ module Pubid
56
56
  def to_s(**opts)
57
57
  return super if opts[:format] && opts[:format] != :human
58
58
 
59
- context = build_rendering_context(nil, format: :human, **opts)
60
- Pubid::Renderers::SupplementRenderer.new(self).render(context:,
61
- **opts.slice(:with_edition))
59
+ context = build_rendering_context(
60
+ nil, format: :human, **opts.except(:with_publisher)
61
+ )
62
+ rendered = Pubid::Renderers::SupplementRenderer.new(self)
63
+ .render(context:, **opts.slice(:with_edition))
64
+ apply_with_publisher(rendered, :human, opts[:with_publisher])
62
65
  end
63
66
 
64
67
  # MR supplement suffix: `/{type}.{number}.{year}` (e.g. "/amd.1.2020").
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "parslet"
4
3
 
5
4
  module Pubid
6
5
  module Iso
@@ -28,7 +27,7 @@ module Pubid
28
27
  candidate = match[1]
29
28
  begin
30
29
  return Pubid::Iso.parse(candidate)
31
- rescue Parslet::ParseFailed
30
+ rescue Pubid::Errors::ParseError
32
31
  # Continue to next method
33
32
  end
34
33
  end
@@ -52,7 +51,7 @@ module Pubid
52
51
  end
53
52
  matches.each do |m|
54
53
  return Pubid::Iso.parse(m[0].strip)
55
- rescue Parslet::ParseFailed
54
+ rescue Pubid::Errors::ParseError
56
55
  # Try next match
57
56
  end
58
57
 
@@ -62,7 +61,7 @@ module Pubid
62
61
  candidate = words[-count..].join(" ")
63
62
  begin
64
63
  return Pubid::Iso.parse(candidate)
65
- rescue Parslet::ParseFailed
64
+ rescue Pubid::Errors::ParseError
66
65
  # Try with fewer words
67
66
  end
68
67
  end
@@ -74,7 +73,7 @@ module Pubid
74
73
 
75
74
  begin
76
75
  return Pubid::Iso.parse(part.strip)
77
- rescue Parslet::ParseFailed
76
+ rescue Pubid::Errors::ParseError
78
77
  # Try next part
79
78
  end
80
79
  end
data/lib/pubid/iso.rb CHANGED
@@ -130,7 +130,7 @@ module Pubid
130
130
  UrnParser.parse(urn)
131
131
  end
132
132
 
133
- # Build an ISO identifier from a Parslet parse-tree hash (used by other
133
+ # Build an ISO identifier from a parg parse-tree hash (used by other
134
134
  # flavors when parsing joint identifiers, e.g. IEC's `IEC … | ISO …` form).
135
135
  #
136
136
  # This is the public seam: callers should never reach into
@@ -142,18 +142,6 @@ module Pubid
142
142
  builder.build(hash)
143
143
  end
144
144
 
145
- # Return the named Parslet rule atom from the ISO parser, for embedding in
146
- # another flavor's grammar (e.g. IEC joint identifiers).
147
- #
148
- # This is the public seam: callers should never instantiate
149
- # `Pubid::Iso::Parser` directly.
150
- #
151
- # @param rule_name [Symbol] the parser rule to expose
152
- # @return [Parslet::Atoms::Base]
153
- def self.joint_grammar_atom(rule_name)
154
- parser.public_send(rule_name)
155
- end
156
-
157
145
  # Auto-discover all identifier types from the Identifiers namespace
158
146
  # @return [Array<Class>] identifier classes that define a self.type Hash
159
147
  def self.identifier_types
@@ -181,12 +169,6 @@ module Pubid
181
169
  @builder ||= Builder.new
182
170
  end
183
171
 
184
- # Memoized parser instance used by Normalizer
185
- # @return [Pubid::Iso::Parser]
186
- def self.parser
187
- @parser ||= Parser.new
188
- end
189
-
190
172
  # Lookup: type code -> identifier class
191
173
  # @param code [String, Symbol] the type key to find
192
174
  # @return [Class, nil] the matching identifier class