pubid 1.15.21 → 2.0.0.alpha.10

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 (863) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +1 -1
  3. data/README.adoc +2044 -53
  4. data/archived-gems/pubid-ccsds/update_codes.yaml +1 -0
  5. data/archived-gems/pubid-iec/stages.yaml +129 -0
  6. data/archived-gems/pubid-iec/update_codes.yaml +67 -0
  7. data/archived-gems/pubid-ieee/update_codes.yaml +104 -0
  8. data/archived-gems/pubid-iso/stages.yaml +106 -0
  9. data/archived-gems/pubid-iso/update_codes.yaml +4 -0
  10. data/archived-gems/pubid-itu/i18n.yaml +13 -0
  11. data/archived-gems/pubid-itu/series.yaml +42 -0
  12. data/archived-gems/pubid-nist/publishers.yaml +6 -0
  13. data/archived-gems/pubid-nist/series.yaml +121 -0
  14. data/archived-gems/pubid-nist/stages.yaml +16 -0
  15. data/archived-gems/pubid-nist/update_codes.yaml +93 -0
  16. data/archived-gems/pubid-plateau/update_codes.yaml +6 -0
  17. data/data/bipm/update_codes.yaml +9 -0
  18. data/data/ccsds/update_codes.yaml +1 -0
  19. data/data/iec/update_codes.yaml +70 -0
  20. data/data/ieee/update_codes.yaml +210 -0
  21. data/data/iso/update_codes.yaml +21 -0
  22. data/data/nist/series.yaml +155 -0
  23. data/data/nist/update_codes.yaml +122 -0
  24. data/data/plateau/update_codes.yaml +6 -0
  25. data/lib/pubid/adobe/builder.rb +52 -0
  26. data/lib/pubid/adobe/identifier.rb +47 -0
  27. data/lib/pubid/adobe/identifiers/publication.rb +31 -0
  28. data/lib/pubid/adobe/identifiers/tech_note.rb +32 -0
  29. data/lib/pubid/adobe/identifiers.rb +10 -0
  30. data/lib/pubid/adobe/parser.rb +136 -0
  31. data/lib/pubid/adobe/renderer.rb +39 -0
  32. data/lib/pubid/adobe/urn_generator.rb +42 -0
  33. data/lib/pubid/adobe/urn_parser.rb +69 -0
  34. data/lib/pubid/adobe.rb +60 -0
  35. data/lib/pubid/amca/builder.rb +176 -0
  36. data/lib/pubid/amca/identifier.rb +4 -0
  37. data/lib/pubid/amca/identifiers/base.rb +92 -0
  38. data/lib/pubid/amca/identifiers/interpretation.rb +38 -0
  39. data/lib/pubid/amca/identifiers/publication.rb +34 -0
  40. data/lib/pubid/amca/identifiers/standard.rb +20 -0
  41. data/lib/pubid/amca/identifiers.rb +11 -0
  42. data/lib/pubid/amca/parser.rb +153 -0
  43. data/lib/pubid/amca/renderer.rb +82 -0
  44. data/lib/pubid/amca/single_identifier.rb +10 -0
  45. data/lib/pubid/amca/urn_generator.rb +51 -0
  46. data/lib/pubid/amca/urn_parser.rb +28 -0
  47. data/lib/pubid/amca.rb +73 -0
  48. data/lib/pubid/ansi/builder.rb +54 -0
  49. data/lib/pubid/ansi/identifier.rb +31 -0
  50. data/lib/pubid/ansi/identifiers/american_national_standard.rb +13 -0
  51. data/lib/pubid/ansi/identifiers/standard.rb +15 -0
  52. data/lib/pubid/ansi/identifiers.rb +11 -0
  53. data/lib/pubid/ansi/parser.rb +91 -0
  54. data/lib/pubid/ansi/renderer.rb +53 -0
  55. data/lib/pubid/ansi/single_identifier.rb +16 -0
  56. data/lib/pubid/ansi/urn_generator.rb +41 -0
  57. data/lib/pubid/ansi/urn_parser.rb +23 -0
  58. data/lib/pubid/ansi.rb +68 -0
  59. data/lib/pubid/api/builder.rb +58 -0
  60. data/lib/pubid/api/components/code.rb +9 -0
  61. data/lib/pubid/api/identifier.rb +42 -0
  62. data/lib/pubid/api/identifiers/base.rb +12 -0
  63. data/lib/pubid/api/identifiers/bulletin.rb +13 -0
  64. data/lib/pubid/api/identifiers/continuous_operations_standard.rb +13 -0
  65. data/lib/pubid/api/identifiers/mpms.rb +26 -0
  66. data/lib/pubid/api/identifiers/publication.rb +13 -0
  67. data/lib/pubid/api/identifiers/recommended_practice.rb +13 -0
  68. data/lib/pubid/api/identifiers/specification.rb +13 -0
  69. data/lib/pubid/api/identifiers/standard.rb +13 -0
  70. data/lib/pubid/api/identifiers/technical_report.rb +13 -0
  71. data/lib/pubid/api/identifiers/typeless_standard.rb +11 -0
  72. data/lib/pubid/api/identifiers.rb +18 -0
  73. data/lib/pubid/api/parser.rb +140 -0
  74. data/lib/pubid/api/renderer.rb +98 -0
  75. data/lib/pubid/api/single_identifier.rb +24 -0
  76. data/lib/pubid/api/urn_generator.rb +23 -0
  77. data/lib/pubid/api/urn_parser.rb +35 -0
  78. data/lib/pubid/api.rb +68 -0
  79. data/lib/pubid/ashrae/builder.rb +519 -0
  80. data/lib/pubid/ashrae/identifier.rb +8 -0
  81. data/lib/pubid/ashrae/identifiers/addenda_package.rb +42 -0
  82. data/lib/pubid/ashrae/identifiers/addendum.rb +44 -0
  83. data/lib/pubid/ashrae/identifiers/base.rb +119 -0
  84. data/lib/pubid/ashrae/identifiers/combined_addenda.rb +43 -0
  85. data/lib/pubid/ashrae/identifiers/errata.rb +39 -0
  86. data/lib/pubid/ashrae/identifiers/guideline.rb +41 -0
  87. data/lib/pubid/ashrae/identifiers/interpretation.rb +45 -0
  88. data/lib/pubid/ashrae/identifiers/standard.rb +41 -0
  89. data/lib/pubid/ashrae/identifiers.rb +15 -0
  90. data/lib/pubid/ashrae/parser.rb +748 -0
  91. data/lib/pubid/ashrae/renderer.rb +117 -0
  92. data/lib/pubid/ashrae/single_identifier.rb +10 -0
  93. data/lib/pubid/ashrae/supplement_identifier.rb +38 -0
  94. data/lib/pubid/ashrae/urn_generator.rb +57 -0
  95. data/lib/pubid/ashrae/urn_parser.rb +27 -0
  96. data/lib/pubid/ashrae.rb +77 -0
  97. data/lib/pubid/asme/builder.rb +162 -0
  98. data/lib/pubid/asme/components/code.rb +26 -0
  99. data/lib/pubid/asme/identifier.rb +24 -0
  100. data/lib/pubid/asme/identifiers/base.rb +10 -0
  101. data/lib/pubid/asme/identifiers/standard.rb +96 -0
  102. data/lib/pubid/asme/identifiers.rb +10 -0
  103. data/lib/pubid/asme/parser.rb +308 -0
  104. data/lib/pubid/asme/renderer.rb +66 -0
  105. data/lib/pubid/asme/single_identifier.rb +38 -0
  106. data/lib/pubid/asme/urn_generator.rb +133 -0
  107. data/lib/pubid/asme/urn_parser.rb +31 -0
  108. data/lib/pubid/asme.rb +67 -0
  109. data/lib/pubid/astm/builder.rb +166 -0
  110. data/lib/pubid/astm/components/code.rb +42 -0
  111. data/lib/pubid/astm/components.rb +9 -0
  112. data/lib/pubid/astm/identifier.rb +24 -0
  113. data/lib/pubid/astm/identifiers/adjunct.rb +28 -0
  114. data/lib/pubid/astm/identifiers/base.rb +13 -0
  115. data/lib/pubid/astm/identifiers/code_number.rb +81 -0
  116. data/lib/pubid/astm/identifiers/data_series.rb +13 -0
  117. data/lib/pubid/astm/identifiers/iso_dual_published.rb +65 -0
  118. data/lib/pubid/astm/identifiers/manual.rb +23 -0
  119. data/lib/pubid/astm/identifiers/monograph.rb +13 -0
  120. data/lib/pubid/astm/identifiers/research_report.rb +21 -0
  121. data/lib/pubid/astm/identifiers/standard.rb +23 -0
  122. data/lib/pubid/astm/identifiers/technical_report.rb +12 -0
  123. data/lib/pubid/astm/identifiers/work_in_progress.rb +12 -0
  124. data/lib/pubid/astm/identifiers.rb +19 -0
  125. data/lib/pubid/astm/parser.rb +244 -0
  126. data/lib/pubid/astm/renderer.rb +172 -0
  127. data/lib/pubid/astm/single_identifier.rb +47 -0
  128. data/lib/pubid/astm/urn_generator.rb +101 -0
  129. data/lib/pubid/astm/urn_parser.rb +30 -0
  130. data/lib/pubid/astm.rb +55 -0
  131. data/lib/pubid/bipm/builder.rb +163 -0
  132. data/lib/pubid/bipm/identifier.rb +285 -0
  133. data/lib/pubid/bipm/identifiers/committee_document.rb +36 -0
  134. data/lib/pubid/bipm/identifiers/guide.rb +35 -0
  135. data/lib/pubid/bipm/identifiers/meeting.rb +53 -0
  136. data/lib/pubid/bipm/identifiers/mep.rb +33 -0
  137. data/lib/pubid/bipm/identifiers/metrologia_article.rb +48 -0
  138. data/lib/pubid/bipm/identifiers/si_brochure.rb +33 -0
  139. data/lib/pubid/bipm/identifiers.rb +15 -0
  140. data/lib/pubid/bipm/parser.rb +237 -0
  141. data/lib/pubid/bipm/renderer.rb +118 -0
  142. data/lib/pubid/bipm/urn_generator.rb +58 -0
  143. data/lib/pubid/bipm/urn_parser.rb +60 -0
  144. data/lib/pubid/bipm.rb +91 -0
  145. data/lib/pubid/bsi/builder.rb +1495 -0
  146. data/lib/pubid/bsi/components/code.rb +11 -0
  147. data/lib/pubid/bsi/components/date.rb +11 -0
  148. data/lib/pubid/bsi/components/publisher.rb +11 -0
  149. data/lib/pubid/bsi/components/type.rb +11 -0
  150. data/lib/pubid/bsi/identifier.rb +6 -0
  151. data/lib/pubid/bsi/identifiers/addendum_document.rb +30 -0
  152. data/lib/pubid/bsi/identifiers/adopted_european_norm.rb +67 -0
  153. data/lib/pubid/bsi/identifiers/adopted_international_standard.rb +51 -0
  154. data/lib/pubid/bsi/identifiers/aerospace_standard.rb +65 -0
  155. data/lib/pubid/bsi/identifiers/amendment.rb +48 -0
  156. data/lib/pubid/bsi/identifiers/british_industrial_practice.rb +21 -0
  157. data/lib/pubid/bsi/identifiers/british_standard.rb +34 -0
  158. data/lib/pubid/bsi/identifiers/bundled_identifier.rb +40 -0
  159. data/lib/pubid/bsi/identifiers/committee_document.rb +44 -0
  160. data/lib/pubid/bsi/identifiers/consolidated_identifier.rb +84 -0
  161. data/lib/pubid/bsi/identifiers/corrigendum.rb +44 -0
  162. data/lib/pubid/bsi/identifiers/detailed_specification.rb +33 -0
  163. data/lib/pubid/bsi/identifiers/disc.rb +27 -0
  164. data/lib/pubid/bsi/identifiers/draft_document.rb +27 -0
  165. data/lib/pubid/bsi/identifiers/electronic_book.rb +16 -0
  166. data/lib/pubid/bsi/identifiers/expert_commentary.rb +36 -0
  167. data/lib/pubid/bsi/identifiers/explanatory_supplement.rb +35 -0
  168. data/lib/pubid/bsi/identifiers/flex.rb +30 -0
  169. data/lib/pubid/bsi/identifiers/handbook.rb +23 -0
  170. data/lib/pubid/bsi/identifiers/index.rb +30 -0
  171. data/lib/pubid/bsi/identifiers/method.rb +35 -0
  172. data/lib/pubid/bsi/identifiers/national_annex.rb +48 -0
  173. data/lib/pubid/bsi/identifiers/practice_guide.rb +21 -0
  174. data/lib/pubid/bsi/identifiers/publicly_available_specification.rb +27 -0
  175. data/lib/pubid/bsi/identifiers/published_document.rb +27 -0
  176. data/lib/pubid/bsi/identifiers/section.rb +32 -0
  177. data/lib/pubid/bsi/identifiers/set.rb +40 -0
  178. data/lib/pubid/bsi/identifiers/standalone_amendment.rb +40 -0
  179. data/lib/pubid/bsi/identifiers/supplement_document.rb +29 -0
  180. data/lib/pubid/bsi/identifiers/supplementary_index.rb +35 -0
  181. data/lib/pubid/bsi/identifiers/technical_specification.rb +34 -0
  182. data/lib/pubid/bsi/identifiers/test_method.rb +35 -0
  183. data/lib/pubid/bsi/identifiers/value_added_publication.rb +37 -0
  184. data/lib/pubid/bsi/identifiers.rb +51 -0
  185. data/lib/pubid/bsi/model.rb +196 -0
  186. data/lib/pubid/bsi/parser.rb +673 -0
  187. data/lib/pubid/bsi/renderer.rb +1064 -0
  188. data/lib/pubid/bsi/single_identifier.rb +141 -0
  189. data/lib/pubid/bsi/urn_generator.rb +92 -0
  190. data/lib/pubid/bsi/urn_parser.rb +52 -0
  191. data/lib/pubid/bsi.rb +282 -0
  192. data/lib/pubid/builder/base.rb +187 -0
  193. data/lib/pubid/bundled_identifier.rb +134 -0
  194. data/lib/pubid/calconnect/builder.rb +38 -0
  195. data/lib/pubid/calconnect/identifier.rb +121 -0
  196. data/lib/pubid/calconnect/identifiers/standard.rb +29 -0
  197. data/lib/pubid/calconnect/identifiers.rb +9 -0
  198. data/lib/pubid/calconnect/parser.rb +54 -0
  199. data/lib/pubid/calconnect/renderer.rb +36 -0
  200. data/lib/pubid/calconnect/urn_generator.rb +33 -0
  201. data/lib/pubid/calconnect/urn_parser.rb +34 -0
  202. data/lib/pubid/calconnect.rb +82 -0
  203. data/lib/pubid/ccsds/builder.rb +57 -0
  204. data/lib/pubid/ccsds/identifier.rb +76 -0
  205. data/lib/pubid/ccsds/identifiers/base.rb +41 -0
  206. data/lib/pubid/ccsds/identifiers/base_BASE_88929.rb +70 -0
  207. data/lib/pubid/ccsds/identifiers/corrigendum.rb +40 -0
  208. data/lib/pubid/ccsds/identifiers.rb +10 -0
  209. data/lib/pubid/ccsds/parser.rb +73 -0
  210. data/lib/pubid/ccsds/single_identifier.rb +77 -0
  211. data/lib/pubid/ccsds/supplement_identifier.rb +37 -0
  212. data/lib/pubid/ccsds/urn_generator.rb +115 -0
  213. data/lib/pubid/ccsds/urn_parser.rb +20 -0
  214. data/lib/pubid/ccsds.rb +64 -0
  215. data/lib/pubid/cen_cenelec/builder.rb +362 -0
  216. data/lib/pubid/cen_cenelec/identifier.rb +38 -0
  217. data/lib/pubid/cen_cenelec/identifiers/adopted_european_norm.rb +45 -0
  218. data/lib/pubid/cen_cenelec/identifiers/amendment.rb +19 -0
  219. data/lib/pubid/cen_cenelec/identifiers/base.rb +34 -0
  220. data/lib/pubid/cen_cenelec/identifiers/cen_report.rb +29 -0
  221. data/lib/pubid/cen_cenelec/identifiers/cen_workshop_agreement.rb +28 -0
  222. data/lib/pubid/cen_cenelec/identifiers/cenelec_harmonization_document.rb +28 -0
  223. data/lib/pubid/cen_cenelec/identifiers/consolidated_identifier.rb +40 -0
  224. data/lib/pubid/cen_cenelec/identifiers/corrigendum.rb +20 -0
  225. data/lib/pubid/cen_cenelec/identifiers/european_norm.rb +99 -0
  226. data/lib/pubid/cen_cenelec/identifiers/european_prestandard.rb +50 -0
  227. data/lib/pubid/cen_cenelec/identifiers/european_specification.rb +29 -0
  228. data/lib/pubid/cen_cenelec/identifiers/fragment.rb +18 -0
  229. data/lib/pubid/cen_cenelec/identifiers/guide.rb +27 -0
  230. data/lib/pubid/cen_cenelec/identifiers/harmonization_document.rb +28 -0
  231. data/lib/pubid/cen_cenelec/identifiers/technical_report.rb +28 -0
  232. data/lib/pubid/cen_cenelec/identifiers/technical_specification.rb +36 -0
  233. data/lib/pubid/cen_cenelec/identifiers.rb +32 -0
  234. data/lib/pubid/cen_cenelec/parser.rb +144 -0
  235. data/lib/pubid/cen_cenelec/renderer.rb +261 -0
  236. data/lib/pubid/cen_cenelec/single_identifier.rb +49 -0
  237. data/lib/pubid/cen_cenelec/supplement_identifier.rb +47 -0
  238. data/lib/pubid/cen_cenelec/urn_generator.rb +129 -0
  239. data/lib/pubid/cen_cenelec/urn_parser.rb +28 -0
  240. data/lib/pubid/cen_cenelec.rb +208 -0
  241. data/lib/pubid/cie/builder.rb +524 -0
  242. data/lib/pubid/cie/components/language.rb +58 -0
  243. data/lib/pubid/cie/identifier.rb +33 -0
  244. data/lib/pubid/cie/identifiers/bundle.rb +50 -0
  245. data/lib/pubid/cie/identifiers/code_attributes.rb +52 -0
  246. data/lib/pubid/cie/identifiers/conference.rb +37 -0
  247. data/lib/pubid/cie/identifiers/corrigendum.rb +34 -0
  248. data/lib/pubid/cie/identifiers/dual_published.rb +41 -0
  249. data/lib/pubid/cie/identifiers/identical.rb +64 -0
  250. data/lib/pubid/cie/identifiers/joint_published.rb +52 -0
  251. data/lib/pubid/cie/identifiers/proceedings.rb +41 -0
  252. data/lib/pubid/cie/identifiers/standard.rb +93 -0
  253. data/lib/pubid/cie/identifiers/supplement.rb +47 -0
  254. data/lib/pubid/cie/identifiers/tutorial_bundle.rb +24 -0
  255. data/lib/pubid/cie/identifiers.rb +19 -0
  256. data/lib/pubid/cie/parser.rb +396 -0
  257. data/lib/pubid/cie/single_identifier.rb +69 -0
  258. data/lib/pubid/cie/supplement_identifier.rb +39 -0
  259. data/lib/pubid/cie/urn_generator.rb +126 -0
  260. data/lib/pubid/cie/urn_parser.rb +28 -0
  261. data/lib/pubid/cie.rb +83 -0
  262. data/lib/pubid/components/adoption.rb +104 -0
  263. data/lib/pubid/components/code.rb +47 -0
  264. data/lib/pubid/components/date.rb +72 -0
  265. data/lib/pubid/components/edition.rb +35 -0
  266. data/lib/pubid/components/iteration.rb +32 -0
  267. data/lib/pubid/components/language.rb +39 -0
  268. data/lib/pubid/components/locality.rb +19 -0
  269. data/lib/pubid/components/publisher.rb +39 -0
  270. data/lib/pubid/components/relationship.rb +151 -0
  271. data/lib/pubid/components/stage.rb +45 -0
  272. data/lib/pubid/components/supplement.rb +184 -0
  273. data/lib/pubid/components/type.rb +48 -0
  274. data/lib/pubid/components/typed_stage.rb +58 -0
  275. data/lib/pubid/components.rb +19 -0
  276. data/lib/pubid/core/pattern_doc_generator.rb +272 -0
  277. data/lib/pubid/core/update_codes.rb +98 -0
  278. data/lib/pubid/core.rb +8 -0
  279. data/lib/pubid/csa/builder.rb +671 -0
  280. data/lib/pubid/csa/components/code.rb +9 -0
  281. data/lib/pubid/csa/components.rb +9 -0
  282. data/lib/pubid/csa/composite_identifier.rb +38 -0
  283. data/lib/pubid/csa/identifier.rb +570 -0
  284. data/lib/pubid/csa/identifiers/base.rb +10 -0
  285. data/lib/pubid/csa/identifiers/bundled.rb +141 -0
  286. data/lib/pubid/csa/identifiers/canadian_adopted.rb +82 -0
  287. data/lib/pubid/csa/identifiers/cec.rb +66 -0
  288. data/lib/pubid/csa/identifiers/combined.rb +158 -0
  289. data/lib/pubid/csa/identifiers/csa_adopted.rb +78 -0
  290. data/lib/pubid/csa/identifiers/package.rb +65 -0
  291. data/lib/pubid/csa/identifiers/series.rb +23 -0
  292. data/lib/pubid/csa/identifiers/standard.rb +10 -0
  293. data/lib/pubid/csa/identifiers.rb +17 -0
  294. data/lib/pubid/csa/parser.rb +449 -0
  295. data/lib/pubid/csa/renderer.rb +300 -0
  296. data/lib/pubid/csa/single_identifier.rb +119 -0
  297. data/lib/pubid/csa/urn_generator.rb +87 -0
  298. data/lib/pubid/csa/urn_parser.rb +33 -0
  299. data/lib/pubid/csa/wrapper_identifier.rb +64 -0
  300. data/lib/pubid/csa.rb +80 -0
  301. data/lib/pubid/doi/builder.rb +18 -0
  302. data/lib/pubid/doi/identifier.rb +49 -0
  303. data/lib/pubid/doi/identifiers/resource.rb +30 -0
  304. data/lib/pubid/doi/identifiers.rb +9 -0
  305. data/lib/pubid/doi/parser.rb +52 -0
  306. data/lib/pubid/doi/renderer.rb +13 -0
  307. data/lib/pubid/doi.rb +55 -0
  308. data/lib/pubid/easc/builder.rb +55 -0
  309. data/lib/pubid/easc/identifier.rb +59 -0
  310. data/lib/pubid/easc/identifiers/pmg.rb +20 -0
  311. data/lib/pubid/easc/identifiers/rmg.rb +19 -0
  312. data/lib/pubid/easc/identifiers.rb +10 -0
  313. data/lib/pubid/easc/parser.rb +88 -0
  314. data/lib/pubid/easc/renderer.rb +48 -0
  315. data/lib/pubid/easc/urn_generator.rb +46 -0
  316. data/lib/pubid/easc/urn_parser.rb +57 -0
  317. data/lib/pubid/easc.rb +52 -0
  318. data/lib/pubid/ecma/builder.rb +45 -0
  319. data/lib/pubid/ecma/identifier.rb +147 -0
  320. data/lib/pubid/ecma/identifiers/memento.rb +30 -0
  321. data/lib/pubid/ecma/identifiers/standard.rb +31 -0
  322. data/lib/pubid/ecma/identifiers/technical_report.rb +31 -0
  323. data/lib/pubid/ecma/identifiers.rb +11 -0
  324. data/lib/pubid/ecma/parser.rb +76 -0
  325. data/lib/pubid/ecma/renderer.rb +67 -0
  326. data/lib/pubid/ecma/urn_generator.rb +46 -0
  327. data/lib/pubid/ecma/urn_parser.rb +51 -0
  328. data/lib/pubid/ecma.rb +67 -0
  329. data/lib/pubid/errors.rb +79 -0
  330. data/lib/pubid/etsi/builder.rb +142 -0
  331. data/lib/pubid/etsi/components/code.rb +43 -0
  332. data/lib/pubid/etsi/components/version.rb +32 -0
  333. data/lib/pubid/etsi/components.rb +10 -0
  334. data/lib/pubid/etsi/identifier.rb +4 -0
  335. data/lib/pubid/etsi/identifiers/amendment.rb +15 -0
  336. data/lib/pubid/etsi/identifiers/base.rb +74 -0
  337. data/lib/pubid/etsi/identifiers/corrigendum.rb +15 -0
  338. data/lib/pubid/etsi/identifiers/etsi_standard.rb +222 -0
  339. data/lib/pubid/etsi/identifiers/supplement_identifier.rb +123 -0
  340. data/lib/pubid/etsi/identifiers.rb +13 -0
  341. data/lib/pubid/etsi/parser.rb +139 -0
  342. data/lib/pubid/etsi/renderer.rb +48 -0
  343. data/lib/pubid/etsi/urn_generator.rb +76 -0
  344. data/lib/pubid/etsi/urn_parser.rb +34 -0
  345. data/lib/pubid/etsi.rb +71 -0
  346. data/lib/pubid/export/auditor.rb +89 -0
  347. data/lib/pubid/export/exporter.rb +33 -0
  348. data/lib/pubid/export/flavor_exporter.rb +250 -0
  349. data/lib/pubid/export/result.rb +97 -0
  350. data/lib/pubid/export.rb +12 -0
  351. data/lib/pubid/format_detector.rb +16 -0
  352. data/lib/pubid/format_registry.rb +42 -0
  353. data/lib/pubid/gb/builder.rb +45 -0
  354. data/lib/pubid/gb/identifier.rb +67 -0
  355. data/lib/pubid/gb/identifiers/standard.rb +34 -0
  356. data/lib/pubid/gb/identifiers.rb +9 -0
  357. data/lib/pubid/gb/parser.rb +63 -0
  358. data/lib/pubid/gb/renderer.rb +35 -0
  359. data/lib/pubid/gb.rb +87 -0
  360. data/lib/pubid/gost/builder.rb +148 -0
  361. data/lib/pubid/gost/identifier.rb +47 -0
  362. data/lib/pubid/gost/identifiers/foreign_reference.rb +25 -0
  363. data/lib/pubid/gost/identifiers/harmonized.rb +39 -0
  364. data/lib/pubid/gost/identifiers/identical_adoption.rb +39 -0
  365. data/lib/pubid/gost/identifiers/interstate_standard.rb +20 -0
  366. data/lib/pubid/gost/identifiers/national_standard.rb +19 -0
  367. data/lib/pubid/gost/identifiers.rb +13 -0
  368. data/lib/pubid/gost/parser.rb +105 -0
  369. data/lib/pubid/gost/renderer.rb +48 -0
  370. data/lib/pubid/gost/urn_generator.rb +46 -0
  371. data/lib/pubid/gost/urn_parser.rb +52 -0
  372. data/lib/pubid/gost.rb +49 -0
  373. data/lib/pubid/iala/builder.rb +102 -0
  374. data/lib/pubid/iala/identifier.rb +90 -0
  375. data/lib/pubid/iala/identifiers/advice.rb +15 -0
  376. data/lib/pubid/iala/identifiers/annex.rb +57 -0
  377. data/lib/pubid/iala/identifiers/general_assembly.rb +19 -0
  378. data/lib/pubid/iala/identifiers/guideline.rb +17 -0
  379. data/lib/pubid/iala/identifiers/letter.rb +16 -0
  380. data/lib/pubid/iala/identifiers/manual.rb +18 -0
  381. data/lib/pubid/iala/identifiers/model_course.rb +17 -0
  382. data/lib/pubid/iala/identifiers/recommendation.rb +17 -0
  383. data/lib/pubid/iala/identifiers/report.rb +16 -0
  384. data/lib/pubid/iala/identifiers/resolution.rb +16 -0
  385. data/lib/pubid/iala/identifiers/standard.rb +17 -0
  386. data/lib/pubid/iala/identifiers.rb +19 -0
  387. data/lib/pubid/iala/parser.rb +138 -0
  388. data/lib/pubid/iala/renderer.rb +36 -0
  389. data/lib/pubid/iala/urn_generator.rb +49 -0
  390. data/lib/pubid/iala/urn_parser.rb +67 -0
  391. data/lib/pubid/iala.rb +71 -0
  392. data/lib/pubid/iana/builder.rb +22 -0
  393. data/lib/pubid/iana/identifier.rb +140 -0
  394. data/lib/pubid/iana/identifiers/registry.rb +69 -0
  395. data/lib/pubid/iana/identifiers.rb +9 -0
  396. data/lib/pubid/iana/parser.rb +38 -0
  397. data/lib/pubid/iana/renderer.rb +32 -0
  398. data/lib/pubid/iana/urn_generator.rb +19 -0
  399. data/lib/pubid/iana/urn_parser.rb +24 -0
  400. data/lib/pubid/iana.rb +69 -0
  401. data/lib/pubid/identifier.rb +1118 -0
  402. data/lib/pubid/identifier_metadata.rb +148 -0
  403. data/lib/pubid/idf/builder.rb +82 -0
  404. data/lib/pubid/idf/identifier.rb +79 -0
  405. data/lib/pubid/idf/identifiers/amendment.rb +28 -0
  406. data/lib/pubid/idf/identifiers/corrigendum.rb +28 -0
  407. data/lib/pubid/idf/identifiers/international_standard.rb +124 -0
  408. data/lib/pubid/idf/identifiers/reviewed_method.rb +101 -0
  409. data/lib/pubid/idf/identifiers.rb +13 -0
  410. data/lib/pubid/idf/parser.rb +144 -0
  411. data/lib/pubid/idf/renderer.rb +84 -0
  412. data/lib/pubid/idf/single_identifier.rb +19 -0
  413. data/lib/pubid/idf/supplement_identifier.rb +35 -0
  414. data/lib/pubid/idf/urn_generator.rb +49 -0
  415. data/lib/pubid/idf/urn_parser.rb +25 -0
  416. data/lib/pubid/idf.rb +89 -0
  417. data/lib/pubid/iec/builder.rb +458 -0
  418. data/lib/pubid/iec/components/code.rb +36 -0
  419. data/lib/pubid/iec/components/consolidated_amendment.rb +59 -0
  420. data/lib/pubid/iec/components/publisher.rb +35 -0
  421. data/lib/pubid/iec/components/sheet.rb +32 -0
  422. data/lib/pubid/iec/components/trf_info.rb +38 -0
  423. data/lib/pubid/iec/components/vap_suffix.rb +41 -0
  424. data/lib/pubid/iec/components.rb +14 -0
  425. data/lib/pubid/iec/identifier.rb +341 -0
  426. data/lib/pubid/iec/identifiers/amendment.rb +97 -0
  427. data/lib/pubid/iec/identifiers/base.rb +54 -0
  428. data/lib/pubid/iec/identifiers/component_specification.rb +29 -0
  429. data/lib/pubid/iec/identifiers/conformity_assessment.rb +28 -0
  430. data/lib/pubid/iec/identifiers/consolidated_identifier.rb +85 -0
  431. data/lib/pubid/iec/identifiers/corrigendum.rb +93 -0
  432. data/lib/pubid/iec/identifiers/fragment_identifier.rb +148 -0
  433. data/lib/pubid/iec/identifiers/guide.rb +86 -0
  434. data/lib/pubid/iec/identifiers/international_standard.rb +162 -0
  435. data/lib/pubid/iec/identifiers/interpretation_sheet.rb +103 -0
  436. data/lib/pubid/iec/identifiers/operational_document.rb +29 -0
  437. data/lib/pubid/iec/identifiers/publicly_available_specification.rb +88 -0
  438. data/lib/pubid/iec/identifiers/sheet_identifier.rb +68 -0
  439. data/lib/pubid/iec/identifiers/societal_technology_trend_report.rb +30 -0
  440. data/lib/pubid/iec/identifiers/systems_reference_document.rb +29 -0
  441. data/lib/pubid/iec/identifiers/technical_group.rb +30 -0
  442. data/lib/pubid/iec/identifiers/technical_report.rb +114 -0
  443. data/lib/pubid/iec/identifiers/technical_specification.rb +114 -0
  444. data/lib/pubid/iec/identifiers/technology_report.rb +28 -0
  445. data/lib/pubid/iec/identifiers/test_report_form.rb +35 -0
  446. data/lib/pubid/iec/identifiers/vap_identifier.rb +76 -0
  447. data/lib/pubid/iec/identifiers/white_paper.rb +29 -0
  448. data/lib/pubid/iec/identifiers/working_document.rb +62 -0
  449. data/lib/pubid/iec/identifiers.rb +31 -0
  450. data/lib/pubid/iec/parser.rb +443 -0
  451. data/lib/pubid/iec/renderer.rb +267 -0
  452. data/lib/pubid/iec/rendering_style.rb +113 -0
  453. data/lib/pubid/iec/single_identifier.rb +72 -0
  454. data/lib/pubid/iec/supplement_identifier.rb +178 -0
  455. data/lib/pubid/iec/urn_generator.rb +245 -0
  456. data/lib/pubid/iec/urn_parser.rb +128 -0
  457. data/lib/pubid/iec.rb +64 -0
  458. data/lib/pubid/ieee/aiee/builder.rb +85 -0
  459. data/lib/pubid/ieee/aiee/identifier.rb +89 -0
  460. data/lib/pubid/ieee/aiee/parser.rb +130 -0
  461. data/lib/pubid/ieee/aiee.rb +11 -0
  462. data/lib/pubid/ieee/builder.rb +1554 -0
  463. data/lib/pubid/ieee/compaction.rb +121 -0
  464. data/lib/pubid/ieee/components/code.rb +110 -0
  465. data/lib/pubid/ieee/components/draft.rb +147 -0
  466. data/lib/pubid/ieee/components/relationship.rb +13 -0
  467. data/lib/pubid/ieee/components/typed_stage.rb +100 -0
  468. data/lib/pubid/ieee/identifier.rb +5 -0
  469. data/lib/pubid/ieee/identifiers/adopted_standard.rb +81 -0
  470. data/lib/pubid/ieee/identifiers/amendment.rb +40 -0
  471. data/lib/pubid/ieee/identifiers/base.rb +384 -0
  472. data/lib/pubid/ieee/identifiers/code_number.rb +82 -0
  473. data/lib/pubid/ieee/identifiers/conformance_identifier.rb +29 -0
  474. data/lib/pubid/ieee/identifiers/corrigendum.rb +40 -0
  475. data/lib/pubid/ieee/identifiers/csa_dual_published.rb +62 -0
  476. data/lib/pubid/ieee/identifiers/dual_identifier.rb +14 -0
  477. data/lib/pubid/ieee/identifiers/dual_published.rb +79 -0
  478. data/lib/pubid/ieee/identifiers/iec_ieee_copublished.rb +115 -0
  479. data/lib/pubid/ieee/identifiers/interpretation_identifier.rb +48 -0
  480. data/lib/pubid/ieee/identifiers/joint_development.rb +223 -0
  481. data/lib/pubid/ieee/identifiers/multi_numbered_identifier.rb +85 -0
  482. data/lib/pubid/ieee/identifiers/nesc/base.rb +127 -0
  483. data/lib/pubid/ieee/identifiers/nesc/draft.rb +43 -0
  484. data/lib/pubid/ieee/identifiers/nesc/edition.rb +32 -0
  485. data/lib/pubid/ieee/identifiers/nesc/handbook.rb +43 -0
  486. data/lib/pubid/ieee/identifiers/nesc/redline.rb +35 -0
  487. data/lib/pubid/ieee/identifiers/nesc/standard.rb +41 -0
  488. data/lib/pubid/ieee/identifiers/nesc.rb +16 -0
  489. data/lib/pubid/ieee/identifiers/parenthetical_identifier.rb +14 -0
  490. data/lib/pubid/ieee/identifiers/project_draft_identifier.rb +49 -0
  491. data/lib/pubid/ieee/identifiers/redlined_standard.rb +26 -0
  492. data/lib/pubid/ieee/identifiers/si_standard.rb +38 -0
  493. data/lib/pubid/ieee/identifiers/standard.rb +44 -0
  494. data/lib/pubid/ieee/identifiers/supplement_identifier.rb +42 -0
  495. data/lib/pubid/ieee/identifiers.rb +34 -0
  496. data/lib/pubid/ieee/ire/builder.rb +62 -0
  497. data/lib/pubid/ieee/ire/identifier.rb +73 -0
  498. data/lib/pubid/ieee/ire/parser.rb +91 -0
  499. data/lib/pubid/ieee/ire.rb +11 -0
  500. data/lib/pubid/ieee/nesc/builder.rb +114 -0
  501. data/lib/pubid/ieee/nesc/parser.rb +155 -0
  502. data/lib/pubid/ieee/nesc.rb +10 -0
  503. data/lib/pubid/ieee/parser.rb +1644 -0
  504. data/lib/pubid/ieee/pre_parser.rb +301 -0
  505. data/lib/pubid/ieee/renderer.rb +408 -0
  506. data/lib/pubid/ieee/typed_stages.rb +183 -0
  507. data/lib/pubid/ieee/urn_generator.rb +215 -0
  508. data/lib/pubid/ieee/urn_parser.rb +34 -0
  509. data/lib/pubid/ieee.rb +163 -0
  510. data/lib/pubid/ieee_debug.rb +30 -0
  511. data/lib/pubid/ietf/builder.rb +78 -0
  512. data/lib/pubid/ietf/identifier.rb +5 -0
  513. data/lib/pubid/ietf/identifiers/base.rb +72 -0
  514. data/lib/pubid/ietf/identifiers/bcp.rb +36 -0
  515. data/lib/pubid/ietf/identifiers/fyi.rb +36 -0
  516. data/lib/pubid/ietf/identifiers/internet_draft.rb +45 -0
  517. data/lib/pubid/ietf/identifiers/rfc.rb +27 -0
  518. data/lib/pubid/ietf/identifiers/serialization.rb +51 -0
  519. data/lib/pubid/ietf/identifiers/std.rb +36 -0
  520. data/lib/pubid/ietf/identifiers.rb +14 -0
  521. data/lib/pubid/ietf/parser.rb +61 -0
  522. data/lib/pubid/ietf/renderer.rb +64 -0
  523. data/lib/pubid/ietf/urn_generator.rb +37 -0
  524. data/lib/pubid/ietf/urn_parser.rb +43 -0
  525. data/lib/pubid/ietf.rb +85 -0
  526. data/lib/pubid/iho/builder.rb +37 -0
  527. data/lib/pubid/iho/identifier.rb +7 -0
  528. data/lib/pubid/iho/identifiers/base.rb +75 -0
  529. data/lib/pubid/iho/identifiers/bibliographic.rb +16 -0
  530. data/lib/pubid/iho/identifiers/circular_letter.rb +15 -0
  531. data/lib/pubid/iho/identifiers/miscellaneous.rb +16 -0
  532. data/lib/pubid/iho/identifiers/publication.rb +15 -0
  533. data/lib/pubid/iho/identifiers/standard.rb +15 -0
  534. data/lib/pubid/iho/identifiers.rb +13 -0
  535. data/lib/pubid/iho/parser.rb +68 -0
  536. data/lib/pubid/iho/renderer.rb +30 -0
  537. data/lib/pubid/iho/urn_generator.rb +29 -0
  538. data/lib/pubid/iho/urn_parser.rb +58 -0
  539. data/lib/pubid/iho.rb +77 -0
  540. data/lib/pubid/isbn/builder.rb +44 -0
  541. data/lib/pubid/isbn/check_digit.rb +53 -0
  542. data/lib/pubid/isbn/identifier.rb +81 -0
  543. data/lib/pubid/isbn/identifiers/book.rb +30 -0
  544. data/lib/pubid/isbn/identifiers.rb +9 -0
  545. data/lib/pubid/isbn/parser.rb +45 -0
  546. data/lib/pubid/isbn/renderer.rb +16 -0
  547. data/lib/pubid/isbn.rb +52 -0
  548. data/lib/pubid/iso/builder.rb +316 -0
  549. data/lib/pubid/iso/bundled_identifier.rb +138 -0
  550. data/lib/pubid/iso/combined_identifier.rb +24 -0
  551. data/lib/pubid/iso/components/code.rb +24 -0
  552. data/lib/pubid/iso/components/publisher.rb +62 -0
  553. data/lib/pubid/iso/components.rb +10 -0
  554. data/lib/pubid/iso/format_resolver.rb +45 -0
  555. data/lib/pubid/iso/identifier.rb +318 -0
  556. data/lib/pubid/iso/identifiers/addendum.rb +107 -0
  557. data/lib/pubid/iso/identifiers/amendment.rb +132 -0
  558. data/lib/pubid/iso/identifiers/corrigendum.rb +108 -0
  559. data/lib/pubid/iso/identifiers/data.rb +75 -0
  560. data/lib/pubid/iso/identifiers/directives.rb +65 -0
  561. data/lib/pubid/iso/identifiers/directives_supplement.rb +148 -0
  562. data/lib/pubid/iso/identifiers/extract.rb +30 -0
  563. data/lib/pubid/iso/identifiers/guide.rb +99 -0
  564. data/lib/pubid/iso/identifiers/international_standard.rb +168 -0
  565. data/lib/pubid/iso/identifiers/international_standardized_profile.rb +94 -0
  566. data/lib/pubid/iso/identifiers/international_workshop_agreement.rb +95 -0
  567. data/lib/pubid/iso/identifiers/pas.rb +93 -0
  568. data/lib/pubid/iso/identifiers/recommendation.rb +45 -0
  569. data/lib/pubid/iso/identifiers/supplement.rb +95 -0
  570. data/lib/pubid/iso/identifiers/tc_document.rb +137 -0
  571. data/lib/pubid/iso/identifiers/technical_report.rb +103 -0
  572. data/lib/pubid/iso/identifiers/technical_specification.rb +102 -0
  573. data/lib/pubid/iso/identifiers/technology_trends_assessments.rb +95 -0
  574. data/lib/pubid/iso/identifiers.rb +32 -0
  575. data/lib/pubid/iso/normalizer.rb +89 -0
  576. data/lib/pubid/iso/parser.rb +534 -0
  577. data/lib/pubid/iso/rendering_style.rb +120 -0
  578. data/lib/pubid/iso/single_identifier.rb +60 -0
  579. data/lib/pubid/iso/supplement_identifier.rb +53 -0
  580. data/lib/pubid/iso/urn_generator.rb +313 -0
  581. data/lib/pubid/iso/urn_parser.rb +442 -0
  582. data/lib/pubid/iso/utilities.rb +86 -0
  583. data/lib/pubid/iso.rb +236 -0
  584. data/lib/pubid/itu/builder.rb +360 -0
  585. data/lib/pubid/itu/components/code.rb +84 -0
  586. data/lib/pubid/itu/components/designation.rb +35 -0
  587. data/lib/pubid/itu/components/sector.rb +46 -0
  588. data/lib/pubid/itu/components/series.rb +25 -0
  589. data/lib/pubid/itu/components.rb +12 -0
  590. data/lib/pubid/itu/i18n.rb +9 -0
  591. data/lib/pubid/itu/i18n.yaml +30 -0
  592. data/lib/pubid/itu/identifier.rb +4 -0
  593. data/lib/pubid/itu/identifiers/addendum.rb +15 -0
  594. data/lib/pubid/itu/identifiers/amendment.rb +19 -0
  595. data/lib/pubid/itu/identifiers/annex.rb +83 -0
  596. data/lib/pubid/itu/identifiers/annex_of_recommendation.rb +87 -0
  597. data/lib/pubid/itu/identifiers/appendix_of_recommendation.rb +92 -0
  598. data/lib/pubid/itu/identifiers/base.rb +482 -0
  599. data/lib/pubid/itu/identifiers/combined_identifier.rb +121 -0
  600. data/lib/pubid/itu/identifiers/corrigendum.rb +35 -0
  601. data/lib/pubid/itu/identifiers/errata.rb +15 -0
  602. data/lib/pubid/itu/identifiers/handbook.rb +38 -0
  603. data/lib/pubid/itu/identifiers/question.rb +63 -0
  604. data/lib/pubid/itu/identifiers/recommendation.rb +15 -0
  605. data/lib/pubid/itu/identifiers/report.rb +39 -0
  606. data/lib/pubid/itu/identifiers/special_publication.rb +31 -0
  607. data/lib/pubid/itu/identifiers/standard_serialization.rb +58 -0
  608. data/lib/pubid/itu/identifiers/supplement.rb +149 -0
  609. data/lib/pubid/itu/identifiers.rb +25 -0
  610. data/lib/pubid/itu/model.rb +111 -0
  611. data/lib/pubid/itu/parser.rb +679 -0
  612. data/lib/pubid/itu/urn_generator.rb +135 -0
  613. data/lib/pubid/itu/urn_parser.rb +31 -0
  614. data/lib/pubid/itu.rb +78 -0
  615. data/lib/pubid/jcgm/builder.rb +106 -0
  616. data/lib/pubid/jcgm/components/publisher.rb +20 -0
  617. data/lib/pubid/jcgm/components.rb +9 -0
  618. data/lib/pubid/jcgm/identifier.rb +21 -0
  619. data/lib/pubid/jcgm/identifiers/amendment.rb +24 -0
  620. data/lib/pubid/jcgm/identifiers/corrigendum.rb +34 -0
  621. data/lib/pubid/jcgm/identifiers/guide.rb +21 -0
  622. data/lib/pubid/jcgm/identifiers/gum_guide.rb +39 -0
  623. data/lib/pubid/jcgm/identifiers/meeting.rb +47 -0
  624. data/lib/pubid/jcgm/identifiers.rb +13 -0
  625. data/lib/pubid/jcgm/parser.rb +151 -0
  626. data/lib/pubid/jcgm/renderer.rb +89 -0
  627. data/lib/pubid/jcgm/single_identifier.rb +118 -0
  628. data/lib/pubid/jcgm/supplement_identifier.rb +51 -0
  629. data/lib/pubid/jcgm/urn_generator.rb +116 -0
  630. data/lib/pubid/jcgm/urn_parser.rb +177 -0
  631. data/lib/pubid/jcgm.rb +86 -0
  632. data/lib/pubid/jis/builder.rb +116 -0
  633. data/lib/pubid/jis/identifier.rb +194 -0
  634. data/lib/pubid/jis/identifiers/amendment.rb +16 -0
  635. data/lib/pubid/jis/identifiers/corrigendum.rb +16 -0
  636. data/lib/pubid/jis/identifiers/explanation.rb +22 -0
  637. data/lib/pubid/jis/identifiers/japanese_industrial_standard.rb +16 -0
  638. data/lib/pubid/jis/identifiers/standard.rb +28 -0
  639. data/lib/pubid/jis/identifiers/technical_report.rb +32 -0
  640. data/lib/pubid/jis/identifiers/technical_specification.rb +32 -0
  641. data/lib/pubid/jis/identifiers.rb +17 -0
  642. data/lib/pubid/jis/parser.rb +135 -0
  643. data/lib/pubid/jis/renderer.rb +69 -0
  644. data/lib/pubid/jis/single_identifier.rb +31 -0
  645. data/lib/pubid/jis/supplement_identifier.rb +50 -0
  646. data/lib/pubid/jis/urn_generator.rb +25 -0
  647. data/lib/pubid/jis/urn_parser.rb +23 -0
  648. data/lib/pubid/jis.rb +69 -0
  649. data/lib/pubid/lutaml/no_store_registration.rb +30 -0
  650. data/lib/pubid/nist/builder.rb +481 -0
  651. data/lib/pubid/nist/caster.rb +1234 -0
  652. data/lib/pubid/nist/circular_supplement_builder.rb +293 -0
  653. data/lib/pubid/nist/components/code.rb +27 -0
  654. data/lib/pubid/nist/components/edition.rb +134 -0
  655. data/lib/pubid/nist/components/issue_number.rb +28 -0
  656. data/lib/pubid/nist/components/part.rb +77 -0
  657. data/lib/pubid/nist/components/stage.rb +53 -0
  658. data/lib/pubid/nist/components/supplement.rb +191 -0
  659. data/lib/pubid/nist/components/translation.rb +42 -0
  660. data/lib/pubid/nist/components/update.rb +103 -0
  661. data/lib/pubid/nist/components/version.rb +35 -0
  662. data/lib/pubid/nist/components/volume.rb +32 -0
  663. data/lib/pubid/nist/components.rb +18 -0
  664. data/lib/pubid/nist/configuration.rb +87 -0
  665. data/lib/pubid/nist/identifier.rb +8 -0
  666. data/lib/pubid/nist/identifiers/base.rb +744 -0
  667. data/lib/pubid/nist/identifiers/circular.rb +80 -0
  668. data/lib/pubid/nist/identifiers/circular_supplement.rb +60 -0
  669. data/lib/pubid/nist/identifiers/commercial_standard.rb +42 -0
  670. data/lib/pubid/nist/identifiers/commercial_standard_emergency.rb +58 -0
  671. data/lib/pubid/nist/identifiers/commercial_standards_monthly.rb +69 -0
  672. data/lib/pubid/nist/identifiers/crpl_report.rb +138 -0
  673. data/lib/pubid/nist/identifiers/dated_document.rb +49 -0
  674. data/lib/pubid/nist/identifiers/federal_information_processing_standards.rb +95 -0
  675. data/lib/pubid/nist/identifiers/grant_contractor_report.rb +36 -0
  676. data/lib/pubid/nist/identifiers/handbook.rb +58 -0
  677. data/lib/pubid/nist/identifiers/internal_report.rb +64 -0
  678. data/lib/pubid/nist/identifiers/letter_circular.rb +46 -0
  679. data/lib/pubid/nist/identifiers/miscellaneous_publication.rb +74 -0
  680. data/lib/pubid/nist/identifiers/monograph.rb +80 -0
  681. data/lib/pubid/nist/identifiers/ncstar.rb +41 -0
  682. data/lib/pubid/nist/identifiers/nsrds.rb +41 -0
  683. data/lib/pubid/nist/identifiers/owmwp.rb +35 -0
  684. data/lib/pubid/nist/identifiers/report.rb +77 -0
  685. data/lib/pubid/nist/identifiers/special_publication.rb +46 -0
  686. data/lib/pubid/nist/identifiers/technical_note.rb +91 -0
  687. data/lib/pubid/nist/identifiers.rb +33 -0
  688. data/lib/pubid/nist/parser.rb +752 -0
  689. data/lib/pubid/nist/parser_output_normalizer.rb +233 -0
  690. data/lib/pubid/nist/preprocessor.rb +443 -0
  691. data/lib/pubid/nist/renderer.rb +43 -0
  692. data/lib/pubid/nist/router.rb +149 -0
  693. data/lib/pubid/nist/series/base.rb +58 -0
  694. data/lib/pubid/nist/series/crpl.rb +13 -0
  695. data/lib/pubid/nist/series/fips.rb +14 -0
  696. data/lib/pubid/nist/series/ir.rb +57 -0
  697. data/lib/pubid/nist/series/letter_preserving.rb +15 -0
  698. data/lib/pubid/nist/series/mono.rb +19 -0
  699. data/lib/pubid/nist/series/ncstar.rb +20 -0
  700. data/lib/pubid/nist/series.rb +49 -0
  701. data/lib/pubid/nist/supplement_identifier.rb +84 -0
  702. data/lib/pubid/nist/urn_generator.rb +133 -0
  703. data/lib/pubid/nist/urn_parser.rb +67 -0
  704. data/lib/pubid/nist.rb +138 -0
  705. data/lib/pubid/oasis/builder.rb +79 -0
  706. data/lib/pubid/oasis/identifier.rb +160 -0
  707. data/lib/pubid/oasis/identifiers/standard.rb +29 -0
  708. data/lib/pubid/oasis/identifiers.rb +9 -0
  709. data/lib/pubid/oasis/parser.rb +34 -0
  710. data/lib/pubid/oasis/renderer.rb +29 -0
  711. data/lib/pubid/oasis/urn_generator.rb +25 -0
  712. data/lib/pubid/oasis/urn_parser.rb +22 -0
  713. data/lib/pubid/oasis.rb +79 -0
  714. data/lib/pubid/ogc/builder.rb +33 -0
  715. data/lib/pubid/ogc/identifier.rb +81 -0
  716. data/lib/pubid/ogc/identifiers/document.rb +26 -0
  717. data/lib/pubid/ogc/identifiers.rb +10 -0
  718. data/lib/pubid/ogc/parser.rb +40 -0
  719. data/lib/pubid/ogc/renderer.rb +33 -0
  720. data/lib/pubid/ogc/urn_generator.rb +14 -0
  721. data/lib/pubid/ogc/urn_parser.rb +22 -0
  722. data/lib/pubid/ogc.rb +71 -0
  723. data/lib/pubid/oiml/builder.rb +270 -0
  724. data/lib/pubid/oiml/components/code.rb +37 -0
  725. data/lib/pubid/oiml/components.rb +9 -0
  726. data/lib/pubid/oiml/identifier.rb +64 -0
  727. data/lib/pubid/oiml/identifiers/amendment.rb +13 -0
  728. data/lib/pubid/oiml/identifiers/annex.rb +29 -0
  729. data/lib/pubid/oiml/identifiers/basic_publication.rb +15 -0
  730. data/lib/pubid/oiml/identifiers/bulletin.rb +137 -0
  731. data/lib/pubid/oiml/identifiers/code_number.rb +90 -0
  732. data/lib/pubid/oiml/identifiers/document.rb +15 -0
  733. data/lib/pubid/oiml/identifiers/errata.rb +15 -0
  734. data/lib/pubid/oiml/identifiers/expert_report.rb +15 -0
  735. data/lib/pubid/oiml/identifiers/guide.rb +15 -0
  736. data/lib/pubid/oiml/identifiers/recommendation.rb +15 -0
  737. data/lib/pubid/oiml/identifiers/seminar_report.rb +15 -0
  738. data/lib/pubid/oiml/identifiers/vocabulary.rb +15 -0
  739. data/lib/pubid/oiml/identifiers.rb +20 -0
  740. data/lib/pubid/oiml/parser.rb +274 -0
  741. data/lib/pubid/oiml/renderer.rb +232 -0
  742. data/lib/pubid/oiml/single_identifier.rb +113 -0
  743. data/lib/pubid/oiml/supplement_identifier.rb +88 -0
  744. data/lib/pubid/oiml/urn_generator.rb +78 -0
  745. data/lib/pubid/oiml/urn_parser.rb +39 -0
  746. data/lib/pubid/oiml.rb +81 -0
  747. data/lib/pubid/omg/builder.rb +19 -0
  748. data/lib/pubid/omg/identifier.rb +47 -0
  749. data/lib/pubid/omg/identifiers/specification.rb +32 -0
  750. data/lib/pubid/omg/identifiers.rb +9 -0
  751. data/lib/pubid/omg/parser.rb +40 -0
  752. data/lib/pubid/omg/renderer.rb +19 -0
  753. data/lib/pubid/omg.rb +51 -0
  754. data/lib/pubid/parser/common_parse_methods.rb +13 -0
  755. data/lib/pubid/parser/common_parse_rules.rb +56 -0
  756. data/lib/pubid/parser/grammar.rb +74 -0
  757. data/lib/pubid/parser.rb +9 -0
  758. data/lib/pubid/parsers/base.rb +11 -0
  759. data/lib/pubid/parsers/mr_string.rb +206 -0
  760. data/lib/pubid/plateau/builder.rb +54 -0
  761. data/lib/pubid/plateau/identifier.rb +4 -0
  762. data/lib/pubid/plateau/identifiers/annex.rb +16 -0
  763. data/lib/pubid/plateau/identifiers/base.rb +55 -0
  764. data/lib/pubid/plateau/identifiers/handbook.rb +28 -0
  765. data/lib/pubid/plateau/identifiers/technical_report.rb +16 -0
  766. data/lib/pubid/plateau/identifiers.rb +11 -0
  767. data/lib/pubid/plateau/parser.rb +73 -0
  768. data/lib/pubid/plateau/renderer.rb +51 -0
  769. data/lib/pubid/plateau/supplement_identifier.rb +68 -0
  770. data/lib/pubid/plateau/urn_generator.rb +29 -0
  771. data/lib/pubid/plateau/urn_parser.rb +43 -0
  772. data/lib/pubid/plateau.rb +82 -0
  773. data/lib/pubid/prefixes_support.rb +51 -0
  774. data/lib/pubid/renderers/annotator.rb +233 -0
  775. data/lib/pubid/renderers/base.rb +66 -0
  776. data/lib/pubid/renderers/directives_renderer.rb +75 -0
  777. data/lib/pubid/renderers/guide_renderer.rb +26 -0
  778. data/lib/pubid/renderers/human_readable.rb +83 -0
  779. data/lib/pubid/renderers/iwa_renderer.rb +20 -0
  780. data/lib/pubid/renderers/mr_string.rb +64 -0
  781. data/lib/pubid/renderers/supplement_renderer.rb +36 -0
  782. data/lib/pubid/renderers/urn.rb +11 -0
  783. data/lib/pubid/renderers.rb +15 -0
  784. data/lib/pubid/rendering/context.rb +168 -0
  785. data/lib/pubid/rendering/date.rb +27 -0
  786. data/lib/pubid/rendering/language.rb +21 -0
  787. data/lib/pubid/rendering/numbering.rb +42 -0
  788. data/lib/pubid/rendering/publisher.rb +25 -0
  789. data/lib/pubid/rendering/stage.rb +38 -0
  790. data/lib/pubid/rendering/supplement.rb +46 -0
  791. data/lib/pubid/rendering.rb +13 -0
  792. data/lib/pubid/sae/builder.rb +32 -0
  793. data/lib/pubid/sae/components/code.rb +9 -0
  794. data/lib/pubid/sae/components/date.rb +27 -0
  795. data/lib/pubid/sae/components/type.rb +23 -0
  796. data/lib/pubid/sae/components.rb +11 -0
  797. data/lib/pubid/sae/identifier.rb +4 -0
  798. data/lib/pubid/sae/identifiers/base.rb +47 -0
  799. data/lib/pubid/sae/identifiers.rb +8 -0
  800. data/lib/pubid/sae/parser.rb +55 -0
  801. data/lib/pubid/sae/renderer.rb +36 -0
  802. data/lib/pubid/sae/urn_generator.rb +30 -0
  803. data/lib/pubid/sae/urn_parser.rb +36 -0
  804. data/lib/pubid/sae.rb +66 -0
  805. data/lib/pubid/tgpp/builder.rb +41 -0
  806. data/lib/pubid/tgpp/identifier.rb +107 -0
  807. data/lib/pubid/tgpp/identifiers/technical_report.rb +32 -0
  808. data/lib/pubid/tgpp/identifiers/technical_specification.rb +33 -0
  809. data/lib/pubid/tgpp/identifiers.rb +11 -0
  810. data/lib/pubid/tgpp/parser.rb +78 -0
  811. data/lib/pubid/tgpp/renderer.rb +52 -0
  812. data/lib/pubid/tgpp/urn_generator.rb +39 -0
  813. data/lib/pubid/tgpp/urn_parser.rb +30 -0
  814. data/lib/pubid/tgpp.rb +83 -0
  815. data/lib/pubid/type_resolver.rb +59 -0
  816. data/lib/pubid/un/builder.rb +42 -0
  817. data/lib/pubid/un/identifier.rb +40 -0
  818. data/lib/pubid/un/identifiers/document.rb +24 -0
  819. data/lib/pubid/un/identifiers.rb +9 -0
  820. data/lib/pubid/un/parser.rb +25 -0
  821. data/lib/pubid/un/renderer.rb +11 -0
  822. data/lib/pubid/un.rb +46 -0
  823. data/lib/pubid/urn_generator/base.rb +110 -0
  824. data/lib/pubid/urn_parser/base.rb +81 -0
  825. data/lib/pubid/urn_parser/errors.rb +16 -0
  826. data/lib/pubid/urn_parser.rb +14 -0
  827. data/lib/pubid/utils/string_normalizer.rb +196 -0
  828. data/lib/pubid/utils.rb +7 -0
  829. data/lib/pubid/version.rb +3 -1
  830. data/lib/pubid/w3c/builder.rb +55 -0
  831. data/lib/pubid/w3c/identifier.rb +130 -0
  832. data/lib/pubid/w3c/identifiers/candidate_recommendation.rb +31 -0
  833. data/lib/pubid/w3c/identifiers/candidate_recommendation_draft.rb +31 -0
  834. data/lib/pubid/w3c/identifiers/draft_note.rb +31 -0
  835. data/lib/pubid/w3c/identifiers/note.rb +30 -0
  836. data/lib/pubid/w3c/identifiers/obsolete_recommendation.rb +31 -0
  837. data/lib/pubid/w3c/identifiers/proposed_edited_recommendation.rb +31 -0
  838. data/lib/pubid/w3c/identifiers/proposed_recommendation.rb +31 -0
  839. data/lib/pubid/w3c/identifiers/recommendation.rb +31 -0
  840. data/lib/pubid/w3c/identifiers/standard.rb +12 -0
  841. data/lib/pubid/w3c/identifiers/superseded_recommendation.rb +31 -0
  842. data/lib/pubid/w3c/identifiers/working_draft.rb +30 -0
  843. data/lib/pubid/w3c/identifiers.rb +25 -0
  844. data/lib/pubid/w3c/parser.rb +43 -0
  845. data/lib/pubid/w3c/renderer.rb +35 -0
  846. data/lib/pubid/w3c/urn_generator.rb +18 -0
  847. data/lib/pubid/w3c/urn_parser.rb +36 -0
  848. data/lib/pubid/w3c.rb +67 -0
  849. data/lib/pubid/xsf/builder.rb +17 -0
  850. data/lib/pubid/xsf/identifier.rb +66 -0
  851. data/lib/pubid/xsf/identifiers/xep.rb +31 -0
  852. data/lib/pubid/xsf/identifiers.rb +9 -0
  853. data/lib/pubid/xsf/parser.rb +25 -0
  854. data/lib/pubid/xsf/renderer.rb +23 -0
  855. data/lib/pubid/xsf/urn_generator.rb +13 -0
  856. data/lib/pubid/xsf/urn_parser.rb +18 -0
  857. data/lib/pubid/xsf.rb +81 -0
  858. data/lib/pubid.rb +551 -13
  859. data/lib/tasks/docs.rake +37 -0
  860. data/lib/tasks/export.rake +39 -0
  861. data/lib/tasks/website-data.json +7546 -0
  862. metadata +875 -171
  863. data/lib/pubid/registry.rb +0 -30
@@ -0,0 +1,752 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "parslet"
4
+
5
+ module Pubid
6
+ module Nist
7
+ # Parser class for NIST identifiers
8
+ # Single Responsibility: Parsing NIST identifier syntax
9
+ class Parser < ::Pubid::Parser::Grammar
10
+
11
+ # Class-level parse method with preprocessing.
12
+ # Delegates all string normalization to Nist::Preprocessor, then
13
+ # feeds the cleaned string to the Parslet grammar and stamps the
14
+ # detected format onto the parse tree.
15
+ def self.class_parse_with_preprocessing(input)
16
+ result = Preprocessor.new(input).call
17
+ parsed = new.parse(result.cleaned)
18
+
19
+ if parsed.is_a?(Hash)
20
+ parsed.merge(parsed_format: result.format)
21
+ elsif parsed.is_a?(Array)
22
+ merged = parsed.each_with_object({}) do |hash, acc|
23
+ next acc unless hash.is_a?(Hash)
24
+
25
+ acc.merge!(hash)
26
+ end
27
+ merged.merge(parsed_format: result.format)
28
+ else
29
+ parsed
30
+ end
31
+ end
32
+
33
+ # Basic building blocks
34
+ rule(:space) { str(" ") }
35
+ rule(:dot) { str(".") }
36
+ rule(:dash) { str("-") }
37
+ rule(:slash) { str("/") }
38
+ rule(:digit) { match("[0-9]") }
39
+ rule(:digits) { digit.repeat(1) }
40
+ rule(:letter) { match("[A-Za-z]") }
41
+ rule(:upper_letter) { match("[A-Z]") }
42
+ rule(:lower_letter) { match("[a-z]") }
43
+
44
+ # Hash prefix for machine-readable formats
45
+ rule(:hash_prefix) { str("#") }
46
+
47
+ # Month abbreviations
48
+ rule(:month_abbrev) do
49
+ str("January") | str("February") | str("March") | str("April") |
50
+ str("May") | str("June") | str("July") | str("August") |
51
+ str("September") | str("October") | str("November") | str("December") |
52
+ str("Jan") | str("Feb") | str("Mar") | str("Apr") |
53
+ str("Jun") | str("Jul") | str("Aug") | str("Sep") | str("Oct") | str("Nov") | str("Dec")
54
+ end
55
+
56
+ # Language codes for translations - 2-4 letter codes
57
+ # Supports: " spa", "(spa)", ".spa" (MR format)
58
+ rule(:language_code) do
59
+ ((space | dot).maybe >> (str("es") | str("pt") | str("chi") | str("viet") | str("port") | str("esp") |
60
+ match("[a-z]").repeat(2, 4))).as(:translation)
61
+ end
62
+
63
+ # Stage ID: i (initial), f (final), 1-9 (numbered iterations)
64
+ rule(:stage_id) do
65
+ str("i") | str("I") | str("f") | str("F") |
66
+ str("1") | str("2") | str("3") | str("4") | str("5") |
67
+ str("6") | str("7") | str("8") | str("9")
68
+ end
69
+
70
+ # Stage type: pd (public draft), wd (work-in-progress), prd (preliminary)
71
+ rule(:stage_type) do
72
+ str("pd") | str("PD") | str("wd") | str("WD") | str("prd") | str("PRD")
73
+ end
74
+
75
+ # Old style stage: (IPD), (FPD), (2PD) - parenthetical at document start
76
+ rule(:old_stage) do
77
+ str("(") >> (stage_id.as(:stage_id) >> stage_type.as(:stage_type)).as(:stage) >> str(")")
78
+ end
79
+
80
+ # New style stage: " ipd", ".ipd" - inline at document end
81
+ rule(:new_stage) do
82
+ (space | dot) >> (stage_id.as(:stage_id) >> stage_type.as(:stage_type)).as(:stage)
83
+ end
84
+
85
+ # Publisher
86
+ rule(:publisher) do
87
+ (str("NBS") | str("NIST")).as(:publisher)
88
+ end
89
+
90
+ # Compound series (include publisher in series name) - must be checked FIRST
91
+ rule(:compound_series) do
92
+ (
93
+ # Longest patterns first to avoid partial matches
94
+ str("NBS BRPD-CRPL-D") | str("NBS CRPL-F-A") | str("NBS CRPL-F-B") |
95
+ str("NBS CS-E") | str("CSRC Building Block") | str("CSRC Use Case") | str("CSRC Book") |
96
+ str("ITL Bulletin") | str("NSRDS-NBS") |
97
+ # NBS and NIST specific patterns that conflict with simple series
98
+ # CRITICAL: Put longer patterns before shorter to avoid partial matches!
99
+ str("NIST LCIRC") | str("NBS LCIRC") | str("NIST.LCIRC") | str("NBS.LCIRC") | str("NBS RPT") |
100
+ str("NIST PS") | str("NIST DCI") | str("NIST Other") |
101
+ str("NISTPUB") |
102
+ str("NBS CSM") | str("NBS CIRC") | str("NBS.CRPL") | str("NBS CRPL") | str("NBS CS") |
103
+ str("NBS CIS") | str("NBS HR") | str("NBS IRPL") | str("NBS IP") | str("NBS PS") |
104
+ str("NBS BH")
105
+ ).as(:series)
106
+ end
107
+
108
+ # Simple series (no publisher prefix)
109
+ rule(:simple_series) do
110
+ (
111
+ str("AMS") | str("VTS") | # NEW - Added for NIST AMS and VTS series
112
+ str("BSS") | str("BMS") | str("BH") |
113
+ str("FIPS") | str("GCR") | str("HB") | str("MONO") |
114
+ str("MP") | str("NCSTAR") | str("NSRDS") | str("IR") |
115
+ str("SP") | str("TN") | str("CSWP") |
116
+ str("AI") | str("CIRC") | str("CS") | str("CSM") |
117
+ str("CRPL") | str("LCIRC") | str("OWMWP") | str("PC") | str("RPT") |
118
+ str("SIBS") | str("TIBM") | str("TTB") | str("EAB") |
119
+ str("JPCRD") | str("JRES") |
120
+ # NEW - CHIPS Act, NWIRP, and Research Brief series
121
+ str("CHIPS") | str("NWIRP") | str("RB")
122
+ ).as(:series)
123
+ end
124
+
125
+ # Suffix letter(s) after number - supports single letters and specific two-letter suffixes
126
+ # Two-letter suffixes: Ur (Unclassified Revised), Ua (Unclassified Amended), Ub-Uj (series variants)
127
+ # Single letter: any letter not followed by excluded keywords
128
+ rule(:number_suffix) do
129
+ (str("U") >> lower_letter) | (match("[a-zA-Z]") >> (
130
+ # Match suffixes
131
+ str("ec") |
132
+ str("ndex") |
133
+ str("nsert") |
134
+ str("rrata") |
135
+ str("raft") | # NEW: Exclude "draft" from number suffix matching
136
+ str("pp") |
137
+ str("s") |
138
+ str("t") |
139
+ str("hi") |
140
+ str("iet") |
141
+ str("ort") |
142
+ str("r") | # NEW: Exclude "r" revision marker (e.g., r5, r1963)
143
+ str("p") # NEW: Exclude "p" part marker (e.g., 28p11969 - part with year pattern)
144
+ ).absent? >>
145
+ digits.maybe)
146
+ end
147
+
148
+ rule(:digits_with_suffix) do
149
+ digits >>
150
+ # Suffix only if not followed by digit (e.g., don't match 'e' in '140e2')
151
+ (number_suffix >> digit.absent?).maybe
152
+ end
153
+
154
+ # Report number - first part - support edition prefixes like "e104" and supplement suffixes like "144supp"
155
+ # Supplements should be handled as separate parts
156
+ rule(:first_number) do
157
+ (
158
+ # OWMWP date format: MM-DD-YYYY (e.g., 06-13-2018)
159
+ # Must be FIRST to match before other dash patterns
160
+ (match("[0-9]").repeat(2, 2).as(:owmwp_month) >> dash >>
161
+ match("[0-9]").repeat(2, 2).as(:owmwp_day) >> dash >>
162
+ match("[0-9]").repeat(4, 4).as(:owmwp_year)).as(:owmwp_date_number) |
163
+ # Special text patterns - MOST SPECIFIC FIRST (NEW for RPT patterns)
164
+ str("ADHOC") | (str("div") >> digits) |
165
+ # Month ranges for RPT: Apr-Jun1948 (NEW)
166
+ (month_abbrev >> dash >> month_abbrev >> digits) |
167
+ # Number with volume suffix (e.g., "539v10" for CIRC, "1011v1" for general patterns)
168
+ # CRITICAL: Must be before CS series pattern to avoid consuming "GB" as letter suffix
169
+ (digits.as(:number) >> str("v") >> digits.as(:volume_suffix)).as(:number_with_volume) |
170
+ # Roman numeral patterns: 1011-I-2.0, 1011-II-1.0 (ENHANCED to accept optional dots)
171
+ (digits >> dash >> (str("III") | str("II") | str("IV") | str("I") | str("V") | str("VI") | str("VII") | str("VIII") | str("IX") | str("X")) >> dash >> digits >> (dot >> digits).maybe) |
172
+ # GB series pattern: 1190GB-1, 1190GB-4A
173
+ (digits >> str("GB") >> dash >> digits >> upper_letter.maybe) |
174
+ # CS series pattern with letter in middle: 102E-42, 123A-50
175
+ (digits >> upper_letter >> dash >> digits) |
176
+ # Volume-number format for CSM series: v6n1, v7n12
177
+ # CHANGED: Capture volume and issue_number separately for proper semantics
178
+ (str("v") >> digits.as(:volume_number) >> str("n") >> digits.as(:issue_number)) |
179
+ # Regular number with supplement and revision suffix: "154supprev"
180
+ (digits >> str("supprev")) |
181
+ # Regular number with edition and revision year-only: "13e2rev1908"
182
+ (digits >> str("e") >> digits >> str("rev") >> digits) |
183
+ # NEW: Number with revision year (rv pattern for LetterCircular): "1013rv1953"
184
+ (digits.as(:number) >> str("rv") >> digits.as(:revision_year)).as(:number_with_rev_year) |
185
+ # Regular number with edition, revision, and month-date: "13e2revJune1908"
186
+ (digits >> str("e") >> digits >> str("rev") >> month_abbrev >> digits) |
187
+ # Regular number with eN suffix and optional supplement (e.g., "101e2supp") - most specific
188
+ (digits >> str("e") >> digits >> str("supp") >> digits.maybe) |
189
+ # Edition prefix with revision and date: e2revJune1908
190
+ (str("e") >> digits >> str("rev") >> month_abbrev >> digits) |
191
+ # Edition prefix followed by digits and optional supplement with digits
192
+ (str("e") >> digits >> str("supp") >> digits.maybe) |
193
+ # Regular number with eN suffix (e.g., "101e2")
194
+ (digits >> str("e") >> digits) |
195
+ # NEW: Bare edition (just "e2" without number prefix)
196
+ (str("e") >> digits >> (dash >> digits).absent?) |
197
+ # Letter prefix with digits (e.g., "c4" for CRPL)
198
+ (lower_letter >> digits) |
199
+ # Regular number with supplement suffix with month/year (e.g., "24suppJan1924")
200
+ (digits >> str("supp") >> month_abbrev >> digits) |
201
+ # Regular number with supplement suffix (e.g., "144supp") - with optional digits
202
+ (digits >> str("supp") >> digits.maybe) |
203
+ # Regular number with supplement suffix followed by month/year for date range
204
+ (digits >> str("sup") >> month_abbrev >> digits) |
205
+ # Regular number with "sup" suffix (e.g., "9350sup") - NEW for RPT patterns
206
+ (digits >> str("sup")) |
207
+ # Language code suffix without separator (e.g., "1088sp")
208
+ # Must come BEFORE general suffix pattern to capture specific language codes
209
+ # Must come AFTER other patterns (like sup, supp, etc.) to avoid consuming them
210
+ # Note: Preprocessing doesn't convert attached suffixes, so we handle both cases
211
+ (digits.as(:number) >> (str("sp") | str("pt") | str("es") | str("SP") | str("PT") | str("ES")).as(:language_code) >> (upper_letter.absent? >> digit.absent? >> letter.absent? >> dash.absent? >> dot.absent?)) |
212
+ # Part+edition suffix for MR format: "28pt1e1969" (part notation + edition year)
213
+ # Handles patterns like "NBS.HB.28pt1e1969" where part and edition are attached
214
+ # Must come BEFORE language code pattern to take priority
215
+ (digits.as(:number) >> str("pt") >> digits.as(:part_number) >> str("e") >> digits.as(:edition_year)) |
216
+ # Parenthetical language code (e.g., "378(sp)")
217
+ # Must come AFTER other patterns to avoid consuming letter suffixes
218
+ # Note: Preprocessing converts content inside parentheses to uppercase
219
+ # Use specific patterns to avoid consuming other parenthetical content
220
+ (digits.as(:number) >> str("(") >> (str("SP") | str("PT") | str("ES")).as(:language_code) >> str(")")) |
221
+ # Number with letter suffix followed by revision (e.g., "8278Ar1", "256Ar1930")
222
+ # CRITICAL: Must come BEFORE digits_with_suffix because number_suffix's
223
+ # str("r").absent? guard rejects any letter followed by 'r' (would
224
+ # otherwise drop the letter and parse "256" + "Ar1930" as garbage).
225
+ (digits.as(:number) >>
226
+ upper_letter.as(:letter_suffix) >>
227
+ str("r") >>
228
+ digits.as(:revision_id)).as(:number_with_letter_revision) |
229
+ # Regular number with optional suffix (original) - includes letters like "A"
230
+ digits_with_suffix
231
+ ).as(:first_number)
232
+ end
233
+
234
+ # Second number (after dash) - allow pt suffix, letter suffixes, and CRPL patterns
235
+ rule(:second_number) do
236
+ # Explicitly exclude month abbreviations at start (so -Feb1985 goes to edition, not second_number)
237
+ month_abbrev.absent? >>
238
+ # NEW: Exclude "draft" keyword
239
+ str("draft").absent? >>
240
+ (
241
+ # Trailing bare supplement marker on a compound second number
242
+ # (e.g. "800-53sup") so it isn't split into "53s" + "up". Builder
243
+ # strips the marker and sets supplement="" (canonical "sup").
244
+ (digits >> (str("supp") | str("sup")) >>
245
+ (digit.absent? >> letter.absent?)) |
246
+ # NEW: Revision pattern with U+letter suffix (e.g., "22r1Ua", "38Ua")
247
+ # MUST come BEFORE general letter suffix to avoid matching just "U" from "Ua"
248
+ (digits >> str("r") >> digits >> str("U") >> lower_letter) |
249
+ # NEW: Revision pattern with letter suffix (e.g., "22r1a", "22r1A" for SP patterns)
250
+ # This allows second_number to match the entire "22r1A" as a single unit
251
+ # MUST come BEFORE plain r+digits to avoid greedy match of just "22r1"
252
+ (digits >> str("r") >> digits >> match("[a-zA-Z]")) |
253
+ # NEW: Revision pattern with year (e.g., "126r2013")
254
+ # This handles SP revision format where revision is attached to second_number
255
+ (digits.as(:number_only) >> str("r") >> digits.as(:edition_id)) |
256
+ # CRPL range with underscore (e.g., "2_3-1A")
257
+ (digits >> str("_") >> digits >> dash >> digits >> upper_letter.maybe) |
258
+ # Letter followed by dash and digits (e.g., "m-5")
259
+ (lower_letter >> dash >> digits) |
260
+ # Number with pt suffix (e.g., "57pt1")
261
+ # EXCLUDE pt#-# patterns (e.g., "pt3-1") which are part components for CRPL
262
+ # Use negative lookahead to prevent matching when followed by dash
263
+ (digits >> str("pt") >> digits >> dash.absent?) |
264
+ # Number with uppercase letter suffix (e.g., "56A", "123B") - for patterns like "56Ar2"
265
+ (digits >> upper_letter) |
266
+ # NEW: Revision pattern where r is directly followed by a letter (e.g., "27ra" -> rA)
267
+ # For patterns like NIST SP 800-27ra where revision 'ra' is attached directly to number
268
+ (digits.as(:number_only) >> str("r") >> match("[a-zA-Z]").as(:letter)).as(:revision_letter) |
269
+ # NEW: Revision pattern where r is directly followed by a letter without leading digits (e.g., "rA")
270
+ # For patterns like NIST SP 800-27ra where revision 'ra' is attached directly to number
271
+ (str("r") >> match("[a-zA-Z]")).as(:revision_letter_suffix) |
272
+ # NEW: Simple revision pattern r followed by digits (e.g., "r1", "r2") for trailing revision
273
+ (str("r") >> digits.as(:edition_id)).as(:revision_simple) |
274
+ # Special patterns like "NCNR", "PERMIS", "BFRL"
275
+ str("NCNR") | str("PERMIS") | str("BFRL") |
276
+ # Just capital letters (e.g., "A", "B", "C") - standalone
277
+ upper_letter.repeat(1, 3) |
278
+ # Regular number with optional suffix - but NOT if part of FIPS date (digit-dash-month-digit-slash)
279
+ (digits_with_suffix >> (dash >> month_abbrev >> digits >> slash).absent?) |
280
+ # Single lowercase letter (e.g., "a", "b") - but NOT "r" followed by digits (edition marker)
281
+ # This is for patterns like "126a" but not "126r2"
282
+ (lower_letter >> digit.absent?)
283
+ ).as(:second_number)
284
+ end
285
+
286
+ # Edition component per NIST spec: <edition-type><edition-id>
287
+ # Type: "e" (edition), "r" (revision), "rev" (revision verbose), "-" (historical)
288
+ # ID: number (1-9) or year (yyyy)
289
+ # Examples: e2, e2021, r5, rev2013, rev 2013, -3
290
+ # Enhanced: Support space-separated format from preprocessing (r1 separated from number)
291
+ rule(:edition) do
292
+ # Edition with "e" prefix: e2, e3, e2021 (1-4 digits for ID)
293
+ (space.maybe >> str("e") >> digits.as(:edition_id)).as(:edition_e) |
294
+ # Revision with "r" prefix and SPACE, with letter: r 5A (preserve format)
295
+ (space >> str("r") >> digits.as(:edition_id) >> match("[a-zA-Z]").as(:edition_letter)).as(:edition_r_with_space_letter) |
296
+ # Revision with "r" prefix and SPACE: r 5 (preserve format)
297
+ (space >> str("r") >> digits.as(:edition_id)).as(:edition_r_with_space) |
298
+ # Revision with "r" prefix NO space, with letter: r5A (compact format)
299
+ (str("r") >> digits.as(:edition_id) >> match("[a-zA-Z]").as(:edition_letter)).as(:edition_r_no_space_letter) |
300
+ # Revision with "r" prefix NO space: r5 (compact format)
301
+ (str("r") >> digits.as(:edition_id)).as(:edition_r_no_space) |
302
+ # Revision with "rev" prefix (verbose): rev2013, rev 2013
303
+ (space.maybe >> str("rev") >> space.maybe >> digits.as(:edition_id)).as(:edition_rev) |
304
+ # Historical with "-" prefix: -2, -3 (ONLY if followed by non-digit or end)
305
+ # This avoids consuming date patterns like "-1908"
306
+ # Historical precedent uses small numbers (1-9), dates use 4-digit years
307
+ (dash >> match("[1-9]").as(:edition_id) >> digit.absent?).as(:edition_historical) |
308
+ # Edition dash-year pattern: -1979, -1990 (dash + 4-digit year)
309
+ # This matches year-only editions like "NBS HB 130-1979"
310
+ (dash >> match("[0-9]").repeat(4,
311
+ 4).as(:dash_year)).as(:edition_dash_year)
312
+ end
313
+
314
+ # Date component per NIST spec: -{YYYY} or -{YYYYMM} or -{YYYYMMDD}
315
+ # Separate from Edition - both can coexist
316
+ # Examples: -1908, -190806, -19770930
317
+ rule(:date) do
318
+ (
319
+ # Date with month and day: -19770930 (YYYYMMDD)
320
+ (dash >> match("[0-9]").repeat(4, 4).as(:date_year) >>
321
+ match("[0-9]").repeat(2, 2).as(:date_month) >>
322
+ match("[0-9]").repeat(2, 2).as(:date_day)) |
323
+ # Date with month: -190806 (YYYYMM)
324
+ (dash >> match("[0-9]").repeat(4, 4).as(:date_year) >>
325
+ match("[0-9]").repeat(2, 2).as(:date_month)) |
326
+ # Date with year only: -1908 (YYYY)
327
+ (dash >> match("[0-9]").repeat(4, 4).as(:date_year)) |
328
+ # Legacy month format: -June1908, -Jan1925 (normalize to YYYYMM)
329
+ (dash >> month_abbrev.as(:date_month) >> digits.as(:date_year))
330
+ ).as(:date)
331
+ end
332
+
333
+ # ISO date token (YYYY-MM-DD) for date-style identifiers
334
+ rule(:iso_date) do
335
+ (match("[0-9]").repeat(4, 4).as(:date_year) >> dash >>
336
+ match("[0-9]").repeat(2, 2).as(:date_month) >> dash >>
337
+ match("[0-9]").repeat(2, 2).as(:date_day))
338
+ end
339
+
340
+ # Date-style identifier with no series (e.g. "NIST 2022-04-15 001",
341
+ # "NIST.2022-04-15.001" — DOI 10.6028/NIST.2022-04-15.001)
342
+ rule(:dated_identifier) do
343
+ hash_prefix.maybe >>
344
+ publisher >> (space | dot) >>
345
+ iso_date.as(:dated_date) >> (space | dot) >>
346
+ match("[0-9]").repeat(1).as(:dated_seq)
347
+ end
348
+
349
+ # "NIST Research Library (YYYY)" — one-off NIST publication that doesn't
350
+ # fit the standard series+number shape (no report number, year in parens).
351
+ # See pubid/pubid#151.
352
+ rule(:research_library_identifier) do
353
+ publisher >> space >>
354
+ str("Research Library").as(:series) >>
355
+ (space >> str("(") >>
356
+ match("[0-9]").repeat(4, 4).as(:year) >> str(")")).maybe
357
+ end
358
+
359
+ # LEGACY EDITION PATTERNS (for backward compatibility during migration)
360
+ # These will be gradually replaced as we migrate to proper Edition/Date components
361
+ rule(:legacy_edition) do
362
+ # Complex revision patterns: r1a, r2b
363
+ ((str("r") | str(" R")) >> match("[0-9]").repeat(1,
364
+ 2).as(:edition) >> lower_letter.as(:edition_letter)) |
365
+ # Edition with revision and year: rev2013, rev2020, rev 2013 (with space)
366
+ (str("rev") >> space.maybe >> digits.as(:edition_year)) |
367
+ # Edition with revision and date: e2revJune1908 (will migrate to e2 + date)
368
+ ((str("e") | str(" E")) >> match("[0-9]").repeat(1, 3).as(:edition) >>
369
+ str("rev") >> match("[A-Za-z]").repeat(3,
370
+ 9).as(:edition_month) >> digits.as(:edition_year)) |
371
+ # Edition with year and month: e201801 (ambiguous - could be e2018 or year 2018 month 01)
372
+ (str("e") >> match("[0-9]").repeat(4,
373
+ 4).as(:edition_year) >> match("[0-9]").repeat(
374
+ 2, 2
375
+ ).as(:edition_month).maybe) |
376
+ # Revision-based edition: revJune1908, revJan1925 (normalize to date)
377
+ (str("rev") >> match("[A-Za-z]").repeat(3,
378
+ 9).as(:edition_month) >> digits.as(:edition_year))
379
+ end
380
+
381
+ # CRPL range pattern (e.g., 1-2_3-1, 1-2_3-1A with suffix) - matches after first dash
382
+ rule(:crpl_range) do
383
+ (digits >> str("_") >> digits >> dash >> digits >> upper_letter.maybe).as(:crpl_range)
384
+ end
385
+
386
+ # Full report number - support dot-separated parts AND CRPL ranges
387
+ # ENHANCED: Support multiple dashes for GCR patterns (Session 220)
388
+ # FIXED: Put GCR pattern first to prioritize matching full dash-separated patterns
389
+ # FIXED: Add edition.maybe to support revision patterns like 800-53r5 in short format
390
+ # FIXED: Month abbreviation as edition (e.g., 107-Mar1985, 11-Jan1925)
391
+ # FIXED: FIPS date format with day and slash (e.g., 11-1-Sep30/1977)
392
+ rule(:report_number) do
393
+ first_number >>
394
+ (
395
+ # Underscore edition-year (space-form mirror of mr_identifier): "1648_2009"
396
+ (str("_") >> digits.as(:edition_year)) |
397
+ # Month abbreviation as edition (e.g., 107-Mar1985, 11-Jan1925)
398
+ # MUST BE FIRST to catch -MonthYear patterns before they're
399
+ # incorrectly parsed as other alternatives
400
+ (dash >> month_abbrev.as(:edition_month) >> digits.as(:edition_year)) |
401
+ # FIPS date format: -1-Sep30/1977 (part-month-day/year with slash)
402
+ # Must come before GCR pattern to avoid being matched as multi-dash
403
+ (dash >> digits.as(:fips_part) >> dash >> month_abbrev.as(:edition_month) >>
404
+ digits.as(:edition_day) >> slash >> digits.as(:edition_year)) |
405
+ # Dash with decimal suffix (e.g., 80-2073.3, 123-45.67)
406
+ # Must come before GCR pattern which expects another dash after second_number
407
+ (dash >> digits.as(:decimal_base) >> dot >> digits.as(:decimal_suffix)).as(:decimal_number) |
408
+ # Dash with letter suffix (e.g., 1-1A, 1-3B for NCSTAR, 73-197Ur for IR)
409
+ # Must come before GCR pattern which expects another dash
410
+ # Supports U+lowercase letter suffix (e.g., Ur, Ua, Ub-Uj for Unclassified variants)
411
+ # For other uppercase letters, only match single letter (A, B, C) to avoid consuming revision r
412
+ (dash >> digits.as(:letter_base) >> (
413
+ (str("U") >> lower_letter.as(:letter_suffix_extra)) |
414
+ upper_letter
415
+ ).as(:letter_suffix)).as(:letter_number) |
416
+ # Dash-SEPARATED letter suffix on a numbered part (e.g., 21-4-B,
417
+ # 173-1-B for FIPS, and the reparseable form of letter_number's own
418
+ # rendered output 200-30-B). The month_abbrev guard keeps FIPS date
419
+ # forms like 11-1-Sep1977 with the earlier patterns; the trailing
420
+ # guard restricts to a single clean letter so GCR -200-30B is unaffected.
421
+ (dash >> digits.as(:letter_base) >> dash >> month_abbrev.absent? >>
422
+ upper_letter.as(:letter_suffix) >> (letter | digit).absent?).as(:letter_number) |
423
+ # Edition dash-year pattern (e.g., -1979 for handbooks like "NBS HB 130-1979")
424
+ # Matches any 4-digit sequence - the builder decides if it's a year or second_number
425
+ (dash >> match("[0-9]").repeat(4,
426
+ 4).as(:dash_year) >> (space | dot | part | crpl_range | second_number | dash).absent?).as(:edition_dash_year) |
427
+ # Second number followed by edition dash-year (e.g., -1-1990 for "105-1-1990")
428
+ # Handles compound numbers with edition year at the end
429
+ # MUST be BEFORE GCR pattern because both start with dash + second_number + dash
430
+ (dash >> second_number >> dash >> match("[0-9]").repeat(4,
431
+ 4).as(:dash_year) >> (space | dot | part | crpl_range | revision | draft).absent?).as(:second_number_edition_year) |
432
+ # FIPS month+year pattern after part (e.g., -1-Sep1977 for "11-1-Sep1977")
433
+ (dash >> second_number >> dash >> month_abbrev.as(:edition_month) >> digits.as(:edition_year) >> (space | dot | part | crpl_range | edition | revision | draft).absent?).as(:fips_month_year_after_part) |
434
+ # GCR multi-dash pattern (e.g., 85-3273-37, 19-200-30B)
435
+ (dash >> second_number >> dash >> (digits >> upper_letter.maybe).as(:part_number)) |
436
+ # Dot-separated part (e.g., 984.4 = number 984, part 4)
437
+ (dot >> second_number) |
438
+ # Dash-separated with optional revision (e.g., 800-53r5, 1019r1963)
439
+ (dash >> (crpl_range | second_number) >> edition.maybe) |
440
+ (dash >> edition)
441
+ # TODO: Language code suffix without separator (e.g., "1088sp")
442
+ # Must come AFTER other patterns to avoid consuming them
443
+ # | (str("sp") | str("pt") | str("es") | match("[a-z]").repeat(2, 4)).as(:language_code) >> (space | dot | part | crpl_range | second_number).absent?) |
444
+ # Parenthetical language code (e.g., "378(sp)")
445
+ # | (str("(") >> match("[a-z]").repeat(2, 4).as(:language_code) >> str(")") >> (space | dot | part | crpl_range | second_number).absent?)
446
+ ).maybe
447
+ end
448
+
449
+ # Volume
450
+ rule(:volume) do
451
+ # Long-form "Vol." comes FIRST so PEG ordered choice doesn't commit to
452
+ # the bare "v" alternative after consuming the leading space via
453
+ # space.maybe (which would then starve the " Vol. " form). Both
454
+ # "Vol. 4" (period + space) and "Vol.4" (period only) are accepted.
455
+ (space.maybe >>
456
+ (str("Vol. ") | str("Vol.") | str("v"))) >>
457
+ (digits >>
458
+ # Support letter ranges (lowercase normalized in preprocessing)
459
+ (str("a-l") | str("m-z") | str("A-L") | str("M-Z")).maybe >>
460
+ # Support single uppercase letters (e.g., v3B, v1A)
461
+ upper_letter.repeat(0, 2)).as(:volume)
462
+ end
463
+
464
+ # Part - enhanced to support patterns like p1adde1 AND pt3r1 (part with revision)
465
+ rule(:part) do
466
+ (str(" Part. ") | str(" Part.") | str(" Part ") |
467
+ (space.maybe >> (str("pt") | str("p") | str("P")))) >>
468
+ (digits >>
469
+ # NEW: Revision after part number: pt3r1, p1r1 (space.maybe for preprocessing)
470
+ (space.maybe >> str("r") >> digits).maybe >>
471
+ # Existing: Addendum with optional edition: add, adde1
472
+ (str("add") >> (str("e") >> digits).maybe).maybe >>
473
+ (dash >> digits).maybe).as(:part)
474
+ end
475
+
476
+ # Revision
477
+ rule(:revision) do
478
+ # NEW: Revision with month and year: rJun1992, r Jun1992 - LONGEST MATCH FIRST
479
+ # Enhanced to support leading space (Session 219)
480
+ (space.maybe >> (str("r") | str("rev")) >> space.maybe >> month_abbrev.as(:revision_month) >> digits.as(:revision_year)) |
481
+ # Revision with slash and year: r6/1925, r11/1924 (NEW for LCIRC patterns)
482
+ (space.maybe >> (str("r") | str("rev")) >> digits.as(:revision) >>
483
+ slash >> digits.as(:revision_year)) |
484
+ # Revision with 4-digit year directly: r1995, r 1995 (allow space before year)
485
+ ((str(" r") | str("r")) >> space.maybe >> match("[0-9]").repeat(4,
486
+ 4).as(:revision_year)) |
487
+ # Revision with year: rev2013, rev 2013 (allow space before year)
488
+ (str("rev") >> space.maybe >> digits.as(:revision_year)) |
489
+ # Revision with digits AND/OR letters: r1a, r1A, ra, r1
490
+ # Enhanced to accept letter-only revisions and space before r
491
+ # ENHANCED: Accept BOTH lowercase and uppercase letters in suffix
492
+ # ENHANCED: Capture original format prefix for format preservation (e.g., " Rev. 5")
493
+ ((str(" rev ") | str("rev") | str(" r") | str("r") | str(" Rev. ") | str(" Rev.") | str(" Revision (r)")).as(:revision_prefix) >>
494
+ space.maybe >>
495
+ ((digits >> match("[a-zA-Z]").maybe) | match("[a-zA-Z]").repeat(1)).as(:revision_id)).as(:revision) |
496
+ # NEW: Standalone 'r' - MUST BE LAST to avoid consuming from other patterns
497
+ # Matches " r" at end of input (after preprocessing: "800-56a r", "800-27 r")
498
+ (str(" r") >> any.absent?).as(:revision_standalone)
499
+ end
500
+
501
+ # Version - V1 SP PARSER COMPATIBLE
502
+ # Supports: ver1.0.2, ver2, " Ver. 2.0", " Version 1.0", v1.0.2, -v1.0, .ver1.0 (MR format)
503
+ rule(:version) do
504
+ # Verbose "ver" form - with or without dots (space.maybe before AND after "ver")
505
+ # ENHANCED: Accept dot prefix for MR format (e.g., "500-281.ver1.0")
506
+ ((space | dot).maybe >> str("ver") >> space.maybe >> (digits >> (dot >> digits).repeat).as(:version)) |
507
+ # Verbose forms with space: " Ver. ", " Version " - require dots
508
+ ((str(" Ver. ") | str(" Version ")) >>
509
+ (digits >> dot >> digits >> (dot >> digits).maybe).as(:version)) |
510
+ # Short form "v" with mandatory dots (v1.0, v1.0.2) - allow optional dash or space before
511
+ ((dash | space).maybe >> str("v") >> (digits >> dot >> digits >> (dot >> digits).maybe).as(:version))
512
+ end
513
+
514
+ # Update - V1 COMPATIBLE
515
+ # Format: /Upd{N}-{YYYY}{MM} where MM is optional
516
+ # Examples: /Upd1-2015, /Upd3-202102, -upd, /upd (after preprocessing)
517
+ # Update number is optional (e.g., "500-300-upd" has no number)
518
+ # Captures prefix to preserve original format (-upd vs /Upd)
519
+ rule(:update) do
520
+ prefix = (
521
+ str("/Upd") |
522
+ (space.maybe >> (str("/upd") | str("-upd")))
523
+ ).as(:update_prefix)
524
+
525
+ prefix >>
526
+ (
527
+ digits.as(:update_number).maybe >>
528
+ (dash >>
529
+ (
530
+ # Real updates: 4-digit year + optional 2-digit month
531
+ # (e.g. /Upd1-2015, /Upd3-202102).
532
+ (match("[0-9]").repeat(4, 4).as(:update_year) >>
533
+ match("[0-9]").repeat(2, 2).as(:update_month)) |
534
+ # Fallback: capture the whole digit run as the year. Handles the
535
+ # unpadded CIRC/LCIRC supplement form pubid emits, where year and
536
+ # revision are fused without a 2-digit month boundary
537
+ # (e.g. /Upd1-19256 = 1925 + revision 6). Keeps these strings
538
+ # re-parseable so generated ids round-trip.
539
+ match("[0-9]").repeat(4).as(:update_year)
540
+ )
541
+ ).maybe
542
+ ).as(:update)
543
+ end
544
+
545
+ # Addendum
546
+ rule(:addendum) do
547
+ ((str("-add") | str(".add") | str(" Add.")) >>
548
+ (space | dash).maybe >> (digits | str("")).as(:addendum_number)).as(:addendum)
549
+ end
550
+
551
+ # Supplement - enhanced to support date patterns, year patterns, and combined with revision
552
+ # Examples: suppJan1924, supp3/1926, supp1925, supJun1925-Jun1927 (date ranges), supprev
553
+ rule(:supplement) do
554
+ space.maybe >>
555
+ (str("supp") | str("sup")) >>
556
+ (
557
+ # Supplement followed by revision: supprev
558
+ str("rev").as(:supplement_with_rev) |
559
+ # Date range pattern: Jan1924-Jan1926
560
+ (month_abbrev.as(:supp_month_start) >> digits.as(:supp_year_start) >>
561
+ dash >> month_abbrev.as(:supp_month_end) >> digits.as(:supp_year_end)).as(:supplement_date_range) |
562
+ # Month and year: Jan1924
563
+ (month_abbrev.as(:supp_month) >> digits.as(:supp_year)).as(:supplement_date) |
564
+ # Number with slash and year: 3/1926
565
+ (digits.as(:supp_number) >> slash >> digits.as(:supp_year)).as(:supplement_slash_year) |
566
+ # Just year: 1925
567
+ digits.as(:supp_year) |
568
+ # General suffix (other patterns)
569
+ match("[A-Za-z0-9]").repeat(1).as(:supplement_suffix)
570
+ ).maybe
571
+ end
572
+
573
+ # Errata
574
+ rule(:errata) do
575
+ (dash.maybe >> (str("errata") | str("err"))).as(:errata)
576
+ end
577
+
578
+ # Index
579
+ rule(:index) do
580
+ (str("index") | str("indx")).as(:index)
581
+ end
582
+
583
+ # Insert
584
+ rule(:insert) do
585
+ (str("insert") | str("ins")).as(:insert)
586
+ end
587
+
588
+ # Appendix
589
+ rule(:appendix) do
590
+ str("app").as(:appendix)
591
+ end
592
+
593
+ # Section - make digits optional for patterns like just "sec"
594
+ rule(:section) do
595
+ str("sec") >> digits.as(:section).maybe
596
+ end
597
+
598
+ # Translation (3-letter language code) - V1 COMPATIBLE
599
+ # Supports: (spa), " spa", ".spa" (MR format)
600
+ rule(:translation) do
601
+ # Parenthetical format: (spa), (por), (ind)
602
+ (str("(") >> match('\w').repeat(3, 3).as(:translation) >> str(")")) |
603
+ # Space-prefix format: " spa"
604
+ (space >> match('\w').repeat(3, 3).as(:translation)) |
605
+ # Dot-prefix format: ".spa" (machine-readable), optional leading space: " .spa"
606
+ (space.maybe >> dot >> match('\w').repeat(3, 3).as(:translation))
607
+ end
608
+
609
+ # Public draft suffix - for patterns like 2pd, 3pd
610
+ rule(:pd_suffix) do
611
+ (space >> digits >> str("pd")).as(:public_draft)
612
+ end
613
+
614
+ # Draft stage - enhanced to support suffix pattern and number after draft
615
+ # ENHANCED: Accept optional space before dash to match after report_number
616
+ rule(:draft) do
617
+ ((space >> str("(Draft)")) |
618
+ (space.maybe >> dash >> str("draft") >> ((space >> digits) | digits).maybe) | # Match " -draft 2" OR "-draft2"
619
+ pd_suffix).as(:draft)
620
+ end
621
+
622
+ # Special date format with slash for FIPS (part of number, not edition)
623
+ rule(:fips_date) do
624
+ dash >> digits.as(:fips_part) >> dash >> month_abbrev.as(:fips_month) >>
625
+ digits.as(:fips_day) >> slash >> digits.as(:fips_year)
626
+ end
627
+
628
+ # All possible parts (order matters!)
629
+ rule(:parts) do
630
+ # Put more specific patterns first
631
+ # CRITICAL: new_stage BEFORE language_code to avoid "ipd" being treated as translation
632
+ new_stage |
633
+ section | index | insert | appendix | pd_suffix |
634
+ edition | date | legacy_edition | revision |
635
+ version | # MOVED BEFORE volume - try dotted versions (v1.1) before simple volumes (v1)
636
+ volume | part | update | addendum |
637
+ supplement | errata | language_code
638
+ end
639
+
640
+ # CIRC Supplement identifier - split into base + supplement
641
+ # Examples:
642
+ # - "NBS CIRC 101e2supp" → base="NBS CIRC 101e2", supplement
643
+ # - "NBS CIRC 25supp-1924" → base="NBS CIRC 25", supplement_year="1924"
644
+ # - "NBS CIRC 24suppJan1924" → base="NBS CIRC 24", supplement_edition="Jan1924"
645
+ # - "NBS CIRC suppJun1925-Jun1926" → date range supplement (no base)
646
+ # - "NBS LCIRC 378Gsup" → base="NBS LCIRC 378G", supplement (no metadata)
647
+ # - "NBS.LCIRC.378sup1/1927" → dot-separated MR format (after preprocessing)
648
+ # Dot-separated machine-readable format: NIST.SP.800-116 or #NIST.2024-01-15.123
649
+ # Enhanced to support parts after number like NIST.SP.1011-I-2.0
650
+ # Enhanced to support revision+update patterns like NIST.IR.8115r1-upd
651
+ rule(:mr_identifier) do
652
+ hash_prefix.maybe >>
653
+ publisher >> dot >>
654
+ simple_series >> dot >>
655
+ report_number >>
656
+ # Edition with underscore separator (MR format: 1648_2009)
657
+ (str("_") >> digits.as(:edition_year)).maybe >>
658
+ # Support letter suffix before update (e.g., 8286C-upd1) - Session 219
659
+ upper_letter.maybe >>
660
+ # Support revision component (r1, r5, etc.) before update
661
+ edition.maybe >>
662
+ update.maybe >>
663
+ # Additional dot-separated parts (parts, version, volume, etc.)
664
+ # MUST come before translation to avoid conflicting with language codes
665
+ (dot >> (digits | upper_letter)).repeat(0, 3) >>
666
+ # Language codes at end (.spa, .por, .ind)
667
+ parts.repeat >> draft.maybe
668
+ end
669
+
670
+ # Main identifier structure
671
+ # Try compound series first (longest match), then publisher + simple series
672
+ rule(:identifier) do
673
+ circ_supplement_identifier |
674
+ dated_identifier |
675
+ mr_identifier |
676
+ research_library_identifier |
677
+ (
678
+ # Compound series (includes publisher in series name)
679
+ compound_series >> (space | dot) >>
680
+ old_stage.maybe >> # Old style stage after series
681
+ report_number.maybe >> fips_date.maybe >> parts.repeat >> draft.maybe >> translation.maybe >> new_stage.maybe
682
+ ) |
683
+ (
684
+ # Publisher + simple series - require space/dot between publisher and series
685
+ publisher >> (space | dot) >>
686
+ simple_series >>
687
+ old_stage.maybe >> # Old style stage after series
688
+ (space | dot) >>
689
+ report_number.maybe >> fips_date.maybe >> parts.repeat >> draft.maybe >> translation.maybe >> new_stage.maybe
690
+ ) |
691
+ (
692
+ # Simple series only (no publisher)
693
+ simple_series >>
694
+ old_stage.maybe >> # Old style stage after series
695
+ (space | dot) >>
696
+ report_number.maybe >> fips_date.maybe >> parts.repeat >> draft.maybe >> translation.maybe >> new_stage.maybe
697
+ )
698
+ end
699
+
700
+ # CIRC Supplement identifier - split into base + supplement
701
+ # Must be complete rule with all patterns
702
+ rule(:circ_supplement_identifier) do
703
+ (
704
+ (str("NBS CIRC") | str("NBS LCIRC") | str("NBS.CIRC") | str("NBS.LCIRC")).as(:series) >>
705
+ (space | dot)
706
+ ).as(:circ_series) >>
707
+ (
708
+ # Date range supplement (no base number)
709
+ (str("supp") >> month_abbrev.as(:supp_month_start) >> digits.as(:supp_year_start) >>
710
+ dash >> month_abbrev.as(:supp_month_end) >> digits.as(:supp_year_end)).as(:supplement_date_range) |
711
+ # Year-only date range supplement to the whole series, no months
712
+ # (e.g. "NBS CIRC sup1925-1926" — pubid/pubid#152). Requires two
713
+ # 4-digit years so it can't swallow "sup3/1926" or a base number.
714
+ ((str("supp") | str("sup")) >> match("[0-9]").repeat(4, 4).as(:supp_year_start) >>
715
+ dash >> match("[0-9]").repeat(4, 4).as(:supp_year_end)).as(:supplement_date_range) |
716
+ # With base identifier + supplement
717
+ (
718
+ # Capture base portion (everything before "supp" or "sup" or slash+year)
719
+ (
720
+ # Number with edition: "101e2"
721
+ (digits.as(:base_number) >> str("e") >> digits.as(:edition_number)) |
722
+ # Number with revision (for supplement patterns): "145r11"
723
+ (digits.as(:base_number) >> lower_letter.as(:revision_letter) >> digits.as(:revision_number)) |
724
+ # Number with letter suffix: "378G"
725
+ (digits.as(:base_number) >> upper_letter.as(:letter_suffix)) |
726
+ # Just number: "25", "24"
727
+ digits.as(:simple_number)
728
+ ).as(:base_portion) >>
729
+ # Supplement marker - support both "supp" and "sup", OR implicit supplement via slash+year
730
+ (
731
+ # Explicit supplement marker
732
+ ((str("supp") | str("sup")) >>
733
+ # Optional supplement metadata
734
+ (
735
+ (month_abbrev >> digits).as(:supplement_month_year) |
736
+ # Dash + number + slash + year (e.g., supp-12/1926)
737
+ (dash >> digits.as(:supp_number) >> slash >> digits.as(:supp_year)).as(:supplement_dash_slash_year) |
738
+ (dash >> digits.as(:supplement_year)) |
739
+ (digits.as(:supp_number) >> slash >> digits.as(:supp_year)).as(:supplement_slash_year) |
740
+ str("").as(:supplement_empty)
741
+ ).maybe) |
742
+ # Implicit supplement via slash+year (e.g., "145r11/1925")
743
+ (slash >> digits.as(:implicit_supplement_year)).as(:implicit_supplement)
744
+ )
745
+ )
746
+ )
747
+ end
748
+
749
+ root(:identifier)
750
+ end
751
+ end
752
+ end