pubid 2.0.0 → 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 (214) hide show
  1. checksums.yaml +4 -4
  2. data/data/parg/adobe.json +1 -1
  3. data/data/parg/aiee.json +1 -1
  4. data/data/parg/amca.json +1 -1
  5. data/data/parg/ansi.json +1 -1
  6. data/data/parg/api.json +1 -1
  7. data/data/parg/ashrae.json +1 -1
  8. data/data/parg/asme.json +1 -1
  9. data/data/parg/astm.json +1 -1
  10. data/data/parg/bipm.json +1 -1
  11. data/data/parg/bsi.json +1 -1
  12. data/data/parg/calconnect.json +1 -1
  13. data/data/parg/ccsds.json +1 -1
  14. data/data/parg/cen_cenelec.json +1 -1
  15. data/data/parg/cie.json +1 -1
  16. data/data/parg/csa.json +1 -1
  17. data/data/parg/doi.json +1 -1
  18. data/data/parg/easc.json +1 -1
  19. data/data/parg/ecma.json +1 -1
  20. data/data/parg/etsi.json +1 -1
  21. data/data/parg/evs.json +1 -1
  22. data/data/parg/gb.json +1 -1
  23. data/data/parg/gost.json +1 -1
  24. data/data/parg/iala.json +1 -1
  25. data/data/parg/iana.json +1 -1
  26. data/data/parg/idf.json +1 -1
  27. data/data/parg/iec.json +1 -1
  28. data/data/parg/ieee.json +1 -29571
  29. data/data/parg/ietf.json +1 -1
  30. data/data/parg/iho.json +1 -0
  31. data/data/parg/ire.json +1 -1
  32. data/data/parg/isbn.json +1 -1
  33. data/data/parg/iso.json +1 -8510
  34. data/data/parg/itu.json +1 -1
  35. data/data/parg/jcgm.json +1 -1
  36. data/data/parg/jis.json +1 -1
  37. data/data/parg/nesc.json +1 -1
  38. data/data/parg/nist.json +1 -9588
  39. data/data/parg/oasis.json +1 -1
  40. data/data/parg/ogc.json +1 -1
  41. data/data/parg/oiml.json +1 -1
  42. data/data/parg/omg.json +1 -1
  43. data/data/parg/parg.json +1 -1
  44. data/data/parg/plateau.json +1 -1
  45. data/data/parg/sae.json +1 -1
  46. data/data/parg/tables/typed_stages.yaml +1 -0
  47. data/data/parg/tgpp.json +1 -1
  48. data/data/parg/un.json +1 -1
  49. data/data/parg/w3c.json +1 -1
  50. data/data/parg/xsf.json +1 -1
  51. data/lib/pubid/adobe/identifier.rb +1 -1
  52. data/lib/pubid/adobe/parser.rb +2 -113
  53. data/lib/pubid/amca/identifiers/base.rb +1 -1
  54. data/lib/pubid/amca/parser.rb +1 -145
  55. data/lib/pubid/ansi/identifier.rb +1 -1
  56. data/lib/pubid/ansi/parser.rb +1 -82
  57. data/lib/pubid/api/builder.rb +32 -1
  58. data/lib/pubid/api/identifier.rb +1 -1
  59. data/lib/pubid/api/parser.rb +1 -131
  60. data/lib/pubid/ashrae/identifiers/base.rb +1 -1
  61. data/lib/pubid/ashrae/parser.rb +3 -710
  62. data/lib/pubid/asme/builder.rb +6 -4
  63. data/lib/pubid/asme/identifier.rb +1 -2
  64. data/lib/pubid/asme/parser.rb +1 -328
  65. data/lib/pubid/astm/builder.rb +12 -3
  66. data/lib/pubid/astm/identifier.rb +1 -2
  67. data/lib/pubid/astm/parser.rb +1 -227
  68. data/lib/pubid/bipm/identifier.rb +8 -1
  69. data/lib/pubid/bipm/parser.rb +2 -224
  70. data/lib/pubid/bsi/builder.rb +2 -4
  71. data/lib/pubid/bsi/parser.rb +1 -666
  72. data/lib/pubid/bsi/single_identifier.rb +38 -1
  73. data/lib/pubid/calconnect/identifier.rb +1 -1
  74. data/lib/pubid/calconnect/parser.rb +2 -40
  75. data/lib/pubid/ccsds/identifier.rb +1 -1
  76. data/lib/pubid/ccsds/parser.rb +1 -66
  77. data/lib/pubid/cen_cenelec/identifier.rb +16 -1
  78. data/lib/pubid/cen_cenelec/parser.rb +3 -136
  79. data/lib/pubid/cie/identifier.rb +1 -1
  80. data/lib/pubid/cie/parser.rb +3 -378
  81. data/lib/pubid/conformance.rb +1 -1
  82. data/lib/pubid/csa/builder.rb +41 -18
  83. data/lib/pubid/csa/identifier.rb +12 -4
  84. data/lib/pubid/csa/identifiers/amendment.rb +28 -0
  85. data/lib/pubid/csa/identifiers.rb +1 -0
  86. data/lib/pubid/csa/parser.rb +16 -397
  87. data/lib/pubid/doi/identifier.rb +1 -1
  88. data/lib/pubid/doi/parser.rb +2 -37
  89. data/lib/pubid/easc/builder.rb +1 -1
  90. data/lib/pubid/easc/identifier.rb +1 -1
  91. data/lib/pubid/easc/parser.rb +2 -70
  92. data/lib/pubid/ecma/CLAUDE.md +8 -1
  93. data/lib/pubid/ecma/identifier.rb +13 -8
  94. data/lib/pubid/ecma/parser.rb +2 -54
  95. data/lib/pubid/ecma/renderer.rb +3 -7
  96. data/lib/pubid/errors.rb +18 -13
  97. data/lib/pubid/etsi/builder.rb +8 -5
  98. data/lib/pubid/etsi/identifiers/base.rb +1 -1
  99. data/lib/pubid/etsi/parser.rb +1 -132
  100. data/lib/pubid/evs/identifier.rb +7 -0
  101. data/lib/pubid/evs/parser.rb +1 -8
  102. data/lib/pubid/evs.rb +1 -1
  103. data/lib/pubid/gb/identifier.rb +7 -1
  104. data/lib/pubid/gb/parser.rb +2 -51
  105. data/lib/pubid/gost/identifier.rb +9 -1
  106. data/lib/pubid/gost/parser.rb +4 -81
  107. data/lib/pubid/iala/parser.rb +2 -121
  108. data/lib/pubid/iana/identifier.rb +1 -1
  109. data/lib/pubid/iana/parser.rb +2 -24
  110. data/lib/pubid/identifier.rb +78 -1
  111. data/lib/pubid/idf/builder.rb +42 -0
  112. data/lib/pubid/idf/identifier.rb +1 -1
  113. data/lib/pubid/idf/parser.rb +1 -137
  114. data/lib/pubid/idf.rb +1 -2
  115. data/lib/pubid/iec/builder.rb +158 -50
  116. data/lib/pubid/iec/identifier.rb +1 -1
  117. data/lib/pubid/iec/parser.rb +3 -430
  118. data/lib/pubid/ieee/aiee/identifier.rb +2 -1
  119. data/lib/pubid/ieee/aiee.rb +0 -1
  120. data/lib/pubid/ieee/builder.rb +2 -2
  121. data/lib/pubid/ieee/identifiers/base.rb +1 -1
  122. data/lib/pubid/ieee/ire/identifier.rb +2 -1
  123. data/lib/pubid/ieee/ire.rb +0 -1
  124. data/lib/pubid/ieee/nesc.rb +0 -1
  125. data/lib/pubid/ieee/parser.rb +1 -1257
  126. data/lib/pubid/ietf/identifiers/base.rb +17 -1
  127. data/lib/pubid/ietf/parser.rb +2 -47
  128. data/lib/pubid/ietf/renderer.rb +17 -2
  129. data/lib/pubid/iho/CLAUDE.md +89 -0
  130. data/lib/pubid/iho/builder.rb +4 -1
  131. data/lib/pubid/iho/identifiers/base.rb +28 -2
  132. data/lib/pubid/iho/renderer.rb +8 -0
  133. data/lib/pubid/iho/urn_generator.rb +11 -1
  134. data/lib/pubid/iho/urn_parser.rb +21 -11
  135. data/lib/pubid/iho.rb +0 -1
  136. data/lib/pubid/isbn/identifier.rb +1 -1
  137. data/lib/pubid/isbn/parser.rb +2 -31
  138. data/lib/pubid/iso/builder.rb +1 -1
  139. data/lib/pubid/iso/identifiers/directives.rb +6 -3
  140. data/lib/pubid/iso/identifiers/guide.rb +6 -3
  141. data/lib/pubid/iso/identifiers/international_standard.rb +3 -1
  142. data/lib/pubid/iso/identifiers/international_workshop_agreement.rb +6 -3
  143. data/lib/pubid/iso/normalizer.rb +1 -1
  144. data/lib/pubid/iso/parser.rb +1 -539
  145. data/lib/pubid/iso/supplement_identifier.rb +6 -3
  146. data/lib/pubid/iso/utilities.rb +4 -5
  147. data/lib/pubid/iso.rb +1 -19
  148. data/lib/pubid/itu/builder.rb +36 -20
  149. data/lib/pubid/itu/identifiers/base.rb +15 -2
  150. data/lib/pubid/itu/parser.rb +1 -775
  151. data/lib/pubid/jcgm/builder.rb +35 -0
  152. data/lib/pubid/jcgm/parser.rb +1 -151
  153. data/lib/pubid/jcgm.rb +1 -2
  154. data/lib/pubid/jis/builder.rb +18 -29
  155. data/lib/pubid/jis/identifier.rb +1 -1
  156. data/lib/pubid/jis/parser.rb +1 -128
  157. data/lib/pubid/nist/builder.rb +5 -1
  158. data/lib/pubid/nist/caster.rb +13 -3
  159. data/lib/pubid/nist/identifiers/base.rb +37 -2
  160. data/lib/pubid/nist/identifiers/circular.rb +2 -2
  161. data/lib/pubid/nist/identifiers/circular_supplement.rb +2 -2
  162. data/lib/pubid/nist/identifiers/commercial_standards_monthly.rb +2 -2
  163. data/lib/pubid/nist/identifiers/crpl_report.rb +2 -2
  164. data/lib/pubid/nist/identifiers/handbook.rb +2 -2
  165. data/lib/pubid/nist/identifiers/internal_report.rb +2 -2
  166. data/lib/pubid/nist/identifiers/miscellaneous_publication.rb +2 -2
  167. data/lib/pubid/nist/identifiers/monograph.rb +2 -2
  168. data/lib/pubid/nist/identifiers/report.rb +2 -2
  169. data/lib/pubid/nist/parser.rb +19 -775
  170. data/lib/pubid/nist/router.rb +4 -1
  171. data/lib/pubid/nist/supplement_identifier.rb +2 -2
  172. data/lib/pubid/oasis/identifier.rb +1 -1
  173. data/lib/pubid/oasis/parser.rb +2 -16
  174. data/lib/pubid/ogc/identifier.rb +1 -1
  175. data/lib/pubid/ogc/parser.rb +2 -26
  176. data/lib/pubid/oiml/identifiers/certification_system.rb +7 -0
  177. data/lib/pubid/oiml/identifiers/dual_published.rb +2 -2
  178. data/lib/pubid/oiml/parser.rb +1 -303
  179. data/lib/pubid/oiml.rb +1 -2
  180. data/lib/pubid/omg/identifier.rb +6 -1
  181. data/lib/pubid/omg/parser.rb +2 -76
  182. data/lib/pubid/parg/artifact.rb +22 -3
  183. data/lib/pubid/parg/model.rb +98 -0
  184. data/lib/pubid/parg.rb +1 -0
  185. data/lib/pubid/parser.rb +5 -4
  186. data/lib/pubid/parsers/mr_string.rb +1 -1
  187. data/lib/pubid/plateau/parser.rb +1 -66
  188. data/lib/pubid/plateau.rb +1 -2
  189. data/lib/pubid/renderers/directives_renderer.rb +1 -1
  190. data/lib/pubid/renderers/iwa_renderer.rb +1 -1
  191. data/lib/pubid/renderers/publisher_stripper.rb +82 -0
  192. data/lib/pubid/renderers/supplement_renderer.rb +1 -1
  193. data/lib/pubid/renderers.rb +1 -0
  194. data/lib/pubid/sae/identifiers/base.rb +1 -1
  195. data/lib/pubid/sae/parser.rb +1 -48
  196. data/lib/pubid/tgpp/identifier.rb +1 -1
  197. data/lib/pubid/tgpp/parser.rb +2 -59
  198. data/lib/pubid/un/identifier.rb +1 -1
  199. data/lib/pubid/un/parser.rb +1 -18
  200. data/lib/pubid/version.rb +1 -1
  201. data/lib/pubid/w3c/identifier.rb +1 -1
  202. data/lib/pubid/w3c/parser.rb +2 -27
  203. data/lib/pubid/xsf/identifier.rb +11 -7
  204. data/lib/pubid/xsf/parser.rb +3 -31
  205. data/lib/pubid/xsf/renderer.rb +2 -4
  206. data/lib/pubid.rb +8 -9
  207. metadata +15 -25
  208. data/lib/pubid/ieee/aiee/parser.rb +0 -130
  209. data/lib/pubid/ieee/ire/parser.rb +0 -109
  210. data/lib/pubid/ieee/nesc/parser.rb +0 -155
  211. data/lib/pubid/iho/parser.rb +0 -68
  212. data/lib/pubid/parser/common_parse_methods.rb +0 -13
  213. data/lib/pubid/parser/common_parse_rules.rb +0 -56
  214. data/lib/pubid/parser/grammar.rb +0 -96
@@ -1,437 +1,14 @@
1
- require "parslet"
2
1
  # frozen_string_literal: true
3
2
 
4
3
  module Pubid
5
4
  module Iec
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
7
 
12
- # We need to sort by length to match longest first because that's how Parslet works
13
- TYPED_STAGES = Pubid::Iec.all_typed_stages
14
- .map(&:abbr).flatten.sort_by(&:length).reverse
15
- TYPED_STAGES_SUPPLEMENTS = TYPED_STAGES
16
-
17
- root :identifier
18
-
19
- rule(:identifier) do
20
- working_programme |
21
- technical_group |
22
- working_document |
23
- sheet_supplement_identifier |
24
- sheet_identifier |
25
- supplement_supplement_identifier |
26
- standalone_supplement |
27
- supplement_identifier |
28
- joint_identifier |
29
- identifier_copublishers
30
- end
31
-
32
- # Technical Group identifier — names a committee rather than a document.
33
- # Examples: "IEC TC 1", "ISO/IEC JTC 1", "ISO/IEC JTC 1/SC 7",
34
- # "IEC SC 100A", "CISPR", "CIS/A".
35
- rule(:technical_group) do
36
- technical_group_with_publisher | technical_group_bare
37
- end
38
-
39
- rule(:technical_group_with_publisher) do
40
- prefix_sole_publisher >> copublishers.maybe >> space >>
41
- tc_body.as(:technical_committee) >>
42
- (str("/") >> space? >> sc_body).as(:subcommittee).maybe
43
- end
44
-
45
- rule(:technical_group_bare) do
46
- # CISPR / CIS-letter forms and bare TYPE NUMBER forms both default
47
- # publisher to "IEC" via the Base class default.
48
- tc_body.as(:technical_committee) >>
49
- (str("/") >> space? >> sc_body).as(:subcommittee).maybe
50
- end
51
-
52
- # Committee body forms accepted by the parser. Order matters: longer
53
- # or more specific patterns first so they win the ordered choice.
54
- rule(:tc_body) do
55
- str("CISPR") |
56
- (str("CIS") >> str("/") >> match("[A-Z]")) |
57
- (tc_type >> space >> digits >> match("[A-Z]").maybe)
58
- end
59
-
60
- rule(:sc_body) do
61
- str("SC") >> space >> digits >> match("[A-Z]").maybe
62
- end
63
-
64
- rule(:tc_type) do
65
- str("JTC") | str("JPC") | str("TC") | str("SC") | str("PC")
66
- end
67
-
68
- # Working Programme format: [PWI|PNW] [TR] number edition
69
- # Examples: "PWI TR 100-36 ED1", "PWI 100-44 ED1", "PNW 65-915 ED1"
70
- # TC-style names: "PWI TR SYCSMARTENERGY-1", "PWI SyCLVDC-1 ED1"
71
- rule(:working_programme) do
72
- (str("PWI") | str("PNW")).as(:wp_stage) >>
73
- space >>
74
- (
75
- (str("TR") >> space) |
76
- (str("TS") >> space) |
77
- (str("SRD") >> space)
78
- ).maybe.as(:wp_type) >>
79
- wp_number >>
80
- (space >> edition).maybe
81
- end
82
-
83
- # Working programme numbers can be digits or TC names
84
- rule(:wp_number) do
85
- # TC-style: SYCSMARTENERGY-1, SyCLVDC-125
86
- (match("[A-Za-z]").repeat(1) >> match('[A-Za-z\d]').repeat >> (dash >> match('\d').repeat(1)).maybe).as(:number_with_part) |
87
- # Regular numeric: 100-36
88
- number_with_part
89
- end
90
-
91
- # Working Document format: TC/number/stage
92
- # TC can be: slashes (CIS/D), hyphens (JTC1-SC41), simple (100, 86B, ACEA, SyCSmartEnergy)
93
- # Examples: "CIS/D/468A/CC", "JTC1-SC41/251/FDIS", "100/3705(F)/FDIS", "86B/4347A/CC"
94
- rule(:working_document) do
95
- # TC patterns: digits (100), letters (ACEA), letters/letters (CIS/D), or complex (JTC1-SC41)
96
- (
97
- # Try specific patterns first
98
- (str("JTC1-SC") >> match('\d').repeat(1)) | # JTC1-SC41
99
- (match("[A-Z]").repeat(1) >> str("/") >> match("[A-Z]").repeat(1)) | # CIS/D
100
- match('[A-Za-z\d]').repeat(1) # Simple: 100, 86B, ACEA, SyCSmartEnergy
101
- ).as(:technical_committee) >>
102
- str("/") >>
103
- match('[A-Za-z\d]').repeat(1).as(:wd_number) >>
104
- (str("(") >> match("[A-Z]").as(:wd_language) >> str(")")).maybe >>
105
- (str("/") >> match("[A-Z]").repeat(1).as(:wd_stage)).maybe
106
- end
107
-
108
- # IEC 60038:2009
109
- # ISO/IEC 17025:2017
110
- # CISPR 11:2015 (special IEC publisher)
111
- # IECQ 080000:2017 (special IEC publisher)
112
- # IECEE (IEC System for Conformity Assessment)
113
- # IECEx (IEC System for Certification to Standards)
114
- # IEC CA (IEC Conformity Assessment)
115
- # IECQ CS (IECQ Component Specifications)
116
- # IECQ OD (IECQ Operational Documents)
117
- rule(:prefix_sole_publisher) do
118
- (
119
- str("IECQ OD") |
120
- str("IECQ CS") |
121
- str("IEC CAB") |
122
- str("IEC CA") |
123
- str("IECRE") |
124
- str("CISPR") |
125
- str("IECEE") |
126
- str("IECEx") |
127
- str("IECQ") |
128
- str("IEC") |
129
- str("ISO")
130
- ).as(:publisher)
131
- end
132
-
133
- # ISO/IEC or IEC
134
- rule(:prefix_with_copublishers) do
135
- prefix_sole_publisher >> space? >> copublishers.maybe
136
- end
137
-
138
- ORGANIZATIONS = %w[
139
- IEC ISO IEEE CIW SAE CIE ASME ASTM OECD HL7 CEI UNDP
140
- ].freeze
141
- rule(:copublishers) do
142
- (str("/") >> space? >> array_to_str(ORGANIZATIONS).as(:copublisher)).repeat.as(:copublishers)
143
- end
144
-
145
- rule(:number_with_part) do
146
- (number >> part_and_subpart.maybe).as(:number_with_part)
147
- end
148
-
149
- # For TRF with organization prefix: "CISPR 14-1G" where CISPR is part of the number
150
- rule(:trf_org_number) do
151
- (str("CISPR") >> space).as(:trf_org) >> number_with_part
152
- end
153
-
154
- rule(:number) do
155
- # ISO/IEC Directives: "DIR", "DIR 1", "DIR 1 IEC SUP", "DIR 2 IEC", "DIR IEC SUP"
156
- # Captured as a flat number (no part/subpart) so it round-trips to the input
157
- # and class-matches the IEC index. Must come before the IECEE [A-Z]{2,4} branch,
158
- # which would otherwise match "DIR" alone and leave the trailing tokens unconsumed.
159
- (str("DIR") >> (space >> match('[A-Z\d]').repeat(1)).repeat) |
160
- # Special case for VIM publication
161
- str("VIM") |
162
- # Special case for SYMBOL publication
163
- str("SYMBOL") |
164
- # IECEx TRF version notation: 62784v1a_ds, 62784v1A
165
- (match('\d').repeat(1,
166
- 6) >> str("v") >> match('\d').repeat(1) >> match("[a-zA-Z]").repeat >> (str("_") >> match("[a-zA-Z]").repeat).maybe) |
167
- # IECEE letter-based numbers: AD-001, GD-2053, OD-1000, CAB-G01, 01-S
168
- # Pattern: 2-4 letter prefix followed by optional dash and number
169
- # The suffix uses [A-Z\d] but not space to properly separate from edition
170
- (match("[A-Z]").repeat(2, 4) >> (
171
- dash >> match('\d').repeat(1)
172
- ).maybe >> match('[A-Z\d]').repeat) |
173
- # Can be 5-6 digits for TRF: 60065, 610091
174
- # Can have letter suffix: 60065N, 610091A
175
- # Can have letter + underscore + letters: 61215F_SE
176
- (match('\d').repeat(1, 6) >> (
177
- match("[a-zA-Z]") >> (str("_") >> match("[a-zA-Z]").repeat).maybe
178
- ).maybe)
179
- end
180
-
181
- rule(:date) do
182
- # :2005-02 or :-- (undated reference — ISO/IEC undated-reference form,
183
- # e.g. IEC 60050:--, also accepted as the em-dash variant IEC 60050:—)
184
- (str(":") | dash) >>
185
- (
186
- (str("--") | str("—")).as(:undated_marker) |
187
- (year_digits >>
188
- (dash >> month_digits).maybe >>
189
- (dash >> day_digits).maybe
190
- ).as(:date)
191
- )
192
- end
193
-
194
- rule(:part_and_subpart) do
195
- # Parts can have:
196
- # - Dashes: 60038-1
197
- # - Complex: 29110-5-1-1
198
- # - TRF ampersand: 60086-1&2A
199
- # - TRF underscore: 60127-2-IA_I, 61215F_SE
200
- # - TRF lowercase: 60127-2-iD_I
201
- # - TRF commas: 60309-1,2G or 60335-1-14,15G
202
-
203
- # the "space?" needed to handle potential spaces
204
- (dash | str(",")) >> space? >>
205
- # matches a part with special TRF characters including commas
206
- match('[\w&_,]').repeat >>
207
- # matches subparts
208
- ((dash | str(",")) >> match('[\w&_,]').repeat).repeat.maybe
209
- end
210
-
211
- rule(:all_parts) do
212
- str("(all parts)").as(:all_parts)
213
- end
214
-
215
- rule(:type_with_stage) do
216
- # "DTR"
217
- # "TS"
218
- # "Guide"
219
- # Also includes supplement stages like "CDCor" for standalone draft corrigenda
220
- array_to_str(TYPED_STAGES + TYPED_STAGES_SUPPLEMENTS).as(:type_with_stage) >>
221
- (match('\d').as(:stage_iteration) >> space).maybe
222
- end
223
-
224
- rule(:language) do
225
- # IEC 60038:2009(en,fr)
226
- # IEC 60038:2009(en-fr) (house style, pubid#491)
227
- # IEC 60038:2009(E/F)
228
- str("(") >>
229
- (
230
- # parse 2-char language codes: ru,en,fr,de,ar,es
231
- (match["a-z"].repeat(1) >> (str(",") | str("-")).maybe) |
232
- # parse single language codes: R/E/F
233
- (match["EFARDS"] >> str("/").maybe)
234
- ).repeat.as(:languages) >>
235
- str(")")
236
- end
237
-
238
- EDITION_STRINGS = %w[Edition Ed. ED Ed].freeze
239
- rule(:edition) do
240
- # We ignore the case where there is "Ed" but no number
241
- # Handle decimal editions like ED1.2
242
- array_to_str(EDITION_STRINGS) >> space? >>
243
- (digits >> (str(".") >> digits).maybe).maybe.as(:edition)
244
- end
245
-
246
- rule(:stage_iteration) do
247
- # "IEC 11243.1"
248
- str(".") >> match('\d').as(:stage_iteration)
249
- end
250
-
251
- # Sheet notation: /1:1994 (sheet 1 from year 1994)
252
- # IEC 60695-2-1/1:1994
253
- rule(:sheet_notation) do
254
- str("/") >>
255
- match('\d').repeat(1).as(:sheet_number) >>
256
- str(":") >>
257
- year_digits.as(:sheet_year)
258
- end
259
-
260
- # Sheet notation without year: /1 (sheet 1 without year)
261
- # IEC 60695-2-1/1
262
- rule(:sheet_notation_no_year) do
263
- str("/") >>
264
- match('\d').repeat(1).as(:sheet_number)
265
- end
266
-
267
- # Fragment notation: /FRAG2 or /FRAGC1 (fragment of amendment/corrigendum)
268
- # IEC 60050-191/AMD2/FRAG2
269
- # IEC 60050-191/COR1/FRAGC1
270
- rule(:fragment_notation) do
271
- str("/") >>
272
- (str("FRAGC") | str("FRAG")).as(:fragment_type) >>
273
- match('\d').repeat(1).as(:fragment_number)
274
- end
275
-
276
- # Sheet identifier: base identifier followed by /N:YEAR
277
- # IEC 60695-2-1/1:1994 (sheet 1 from year 1994)
278
- # IEC 60695-2-1/1 (sheet 1 without year)
279
- rule(:sheet_identifier) do
280
- identifier_copublishers_no_third.as(:base) >>
281
- (sheet_notation | sheet_notation_no_year)
282
- end
283
-
284
- # Sheet identifier followed by supplement: base/sheet/supplement
285
- # IEC 60695-2-1/1:1994/COR1:1995
286
- rule(:sheet_supplement_identifier) do
287
- identifier_copublishers_no_third.as(:base) >>
288
- sheet_notation >>
289
- str("/") >> supplement_type_with_stage >>
290
- space? >> second_part >> third_part
291
- end
292
-
293
- # VAP suffix for consolidated/version types
294
- # CSV = Consolidated version (with Supplements)
295
- # CMV = Commented Version
296
- # RLV = Redline Version (shows changes)
297
- # SER = Serial version
298
- # EXV = Example version
299
- # PAC = Package
300
- # PRV = Preview version
301
- # Internal helper (no `.as`): a single VAP code. The capture key stays
302
- # :vap_suffix below; this rule just lets the suffix be one or more codes.
303
- rule(:vap_code) do
304
- str("CSV") |
305
- str("CMV") |
306
- str("RLV") |
307
- str("SER") |
308
- str("EXV") |
309
- str("PAC") |
310
- str("PRV")
311
- end
312
-
313
- # One or more VAP codes joined by "-", captured whole, e.g. "CSV" or
314
- # "EXV-CMV"; the builder splits it into the VapIdentifier `vap` array.
315
- rule(:vap_suffix) do
316
- space >> (vap_code >> (str("-") >> vap_code).repeat).as(:vap_suffix)
317
- end
318
-
319
- # Database suffix: " DB"
320
- # IEC 60617:2012 DB
321
- rule(:database_suffix) do
322
- space >> str("DB").as(:database)
323
- end
324
-
325
- # Consolidated amendments: +AMD1:2016+AMD2:2019
326
- # Also supports without dates: +AMD1+AMD2
327
- # Creates ConsolidatedIdentifier with array of amendments
328
- rule(:consolidated_supplement) do
329
- str("+") >>
330
- (str("AMD") | str("COR")).as(:supplement_type) >>
331
- match('\d').repeat(1).as(:supplement_number) >>
332
- (str(":") >> year_digits.as(:supplement_year)).maybe
333
- end
334
-
335
- rule(:consolidated_supplements) do
336
- consolidated_supplement.repeat(1).as(:consolidated_supplements)
337
- end
338
-
339
- rule(:second_part) do
340
- # Try TRF organization number first, fallback to regular number
341
- (trf_org_number | number_with_part) >>
342
- stage_iteration.maybe >>
343
- (space? >> date).maybe >>
344
- consolidated_supplements.maybe >>
345
- (vap_suffix | database_suffix).maybe
346
- end
347
-
348
- rule(:third_part_edition) do
349
- space? >> edition.maybe
350
- end
351
-
352
- rule(:third_part) do
353
- # End of the identifier, we can have language, edition, fragment, or all parts
354
- third_part_edition >> language.maybe >> fragment_notation.maybe >> all_parts.maybe
355
- end
356
-
357
- # prefix sole or copublishers with type and stage
358
- # IEC/TR 60038
359
- # ISO/IEC TS 20594-1
360
- # IEC/FDIS 60038
361
- rule(:identifier_copublishers) do
362
- identifier_copublishers_no_third >> third_part
363
- end
364
-
365
- rule(:guide_prefix) do
366
- str("Guide") | str("GUIDE")
367
- end
368
-
369
- rule(:identifier_copublishers_no_third) do
370
- # Guide IEC 51:1999
371
- (guide_prefix.as(:type_with_stage_fr) >> space).maybe >>
372
- prefix_with_copublishers.maybe >> space? >> str("/").maybe >>
373
- type_with_stage.maybe >>
374
- space.maybe >>
375
- second_part >> third_part_edition
376
- end
377
-
378
- # For joint identifiers (ISO/IEC)
379
- # ISO/IEC 17025:2017 handles copublisher in copublishers rule
380
- # We handle this in identifier_copublishers already
381
- rule(:joint_identifier) do
382
- identifier_copublishers_no_third.as(:base) >>
383
- space? >> str("|") >> space? >>
384
- scope { iso_identifier }.as(:joint_identifier)
385
- end
386
-
387
- rule(:iso_identifier) do
388
- Pubid::Iso.joint_grammar_atom(:identifier)
389
- end
390
-
391
- rule(:supplement_type_with_stage) do
392
- # "DAM"
393
- # "Amd"
394
- # "FRAG" (fragments of amendments)
395
- # "FRAGC" (fragments of corrigenda)
396
- (array_to_str(TYPED_STAGES_SUPPLEMENTS) | str("FRAGC") | str("FRAG")).as(:type_with_stage)
397
- end
398
-
399
- # Standalone draft supplement (no base identifier)
400
- # IEC/FDAM 60038-1
401
- # IEC/FDCOR 12345
402
- rule(:standalone_supplement) do
403
- prefix_with_copublishers >> str("/") >>
404
- supplement_type_with_stage >>
405
- space >> second_part >> third_part
406
- end
407
-
408
- # IEC 60038:2009/Amd 1:2011
409
- rule(:supplement_identifier_no_third) do
410
- identifier_copublishers_no_third.as(:base) >>
411
- str("/") >> supplement_type_with_stage >>
412
- space? >> second_part
413
- end
414
-
415
- rule(:supplement_identifier) do
416
- supplement_identifier_no_third >> third_part
417
- end
418
-
419
- # IEC 60038:2009/Amd 1:2011/Cor 1:2012
420
- rule(:supplement_supplement_identifier) do
421
- supplement_identifier_no_third.as(:base) >>
422
- str("/") >> supplement_type_with_stage >>
423
- space? >> second_part >> third_part
424
- end
425
-
426
- rule(:dash) do
427
- DASH_CHARS.map { |char| str(char) }.reduce(:|)
428
- end
429
-
430
8
  IEV_SHORTHAND = /\AIEV(?=\z|[\s-])/
431
9
 
432
- # Pre-parse ingestion normalizations (R2): every parse path —
433
- # parslet and PG artifact alike — feeds the grammar the same
434
- # normalized string.
10
+ # Pre-parse ingestion normalizations (R2): every parse path feeds
11
+ # the grammar the same normalized string.
435
12
  def self.normalize_input(input)
436
13
  # Normalize tab-separated editions: "IECEE AD-001\tED1.6" -> "IECEE AD-001 ED1.6"
437
14
  normalized = input.gsub("\t", " ")
@@ -440,10 +17,6 @@ module Pubid
440
17
  # Expand IEV shorthand: "IEV" / "IEV-351" -> "IEC 60050" / "IEC 60050-351"
441
18
  normalized.sub(IEV_SHORTHAND, "IEC 60050")
442
19
  end
443
-
444
- def parse(input)
445
- super(self.class.normalize_input(input))
446
- end
447
20
  end
448
21
  end
449
22
  end
@@ -35,7 +35,8 @@ module Pubid
35
35
 
36
36
  # Parse AIEE identifier string
37
37
  def self.parse(input)
38
- parsed = Parser.new.parse(input)
38
+ parsed = Pubid::Parg::Backend.parse(:aiee, input,
39
+ entry: "aiee_identifier")
39
40
  Builder.new.build(parsed)
40
41
  end
41
42
 
@@ -5,7 +5,6 @@ module Pubid
5
5
  module Aiee
6
6
  autoload :Builder, "#{__dir__}/aiee/builder"
7
7
  autoload :Identifier, "#{__dir__}/aiee/identifier"
8
- autoload :Parser, "#{__dir__}/aiee/parser"
9
8
  end
10
9
  end
11
10
  end
@@ -146,7 +146,7 @@ module Pubid
146
146
  related =
147
147
  begin
148
148
  Identifier.parse(m[1])
149
- rescue Parslet::ParseFailed
149
+ rescue Pubid::Errors::ParseError
150
150
  Identifier.new(parenthetical_content: m[1])
151
151
  end
152
152
  relationships = [Components::Relationship.new(
@@ -2278,7 +2278,7 @@ module Pubid
2278
2278
  id_strings.map do |id_str|
2279
2279
  # Use Identifier.parse for recursive parsing
2280
2280
  Identifier.parse(id_str)
2281
- rescue Parslet::ParseFailed
2281
+ rescue Pubid::Errors::ParseError
2282
2282
  # If parsing fails, create minimal identifier with just the string
2283
2283
  # This maintains graceful degradation
2284
2284
  Identifier.new(parenthetical_content: id_str)
@@ -312,7 +312,7 @@ module Pubid
312
312
  else
313
313
  parse_single(result.input)
314
314
  end
315
- rescue Parslet::ParseFailed
315
+ rescue Pubid::Errors::ParseError
316
316
  parse_single(input)
317
317
  end
318
318
 
@@ -39,7 +39,8 @@ module Pubid
39
39
 
40
40
  # Parse IRE identifier string
41
41
  def self.parse(input)
42
- parsed = Parser.new.parse(input)
42
+ parsed = Pubid::Parg::Backend.parse(:ire, input,
43
+ entry: "ire_identifier")
43
44
  builder = Builder.new
44
45
  builder.build(parsed)
45
46
  end
@@ -5,7 +5,6 @@ module Pubid
5
5
  module Ire
6
6
  autoload :Builder, "#{__dir__}/ire/builder"
7
7
  autoload :Identifier, "#{__dir__}/ire/identifier"
8
- autoload :Parser, "#{__dir__}/ire/parser"
9
8
  end
10
9
  end
11
10
  end
@@ -4,7 +4,6 @@ module Pubid
4
4
  module Ieee
5
5
  module Nesc
6
6
  autoload :Builder, "#{__dir__}/nesc/builder"
7
- autoload :Parser, "#{__dir__}/nesc/parser"
8
7
  end
9
8
  end
10
9
  end