pubid 2.0.1 → 2.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (185) hide show
  1. checksums.yaml +4 -4
  2. data/data/parg/adobe.json +1 -1
  3. data/data/parg/amca.json +1 -1
  4. data/data/parg/ansi.json +1 -1
  5. data/data/parg/api.json +1 -1
  6. data/data/parg/ashrae.json +1 -1
  7. data/data/parg/asme.json +1 -1
  8. data/data/parg/astm.json +1 -1
  9. data/data/parg/bipm.json +1 -1
  10. data/data/parg/bsi.json +1 -1
  11. data/data/parg/ccsds.json +1 -1
  12. data/data/parg/cen_cenelec.json +1 -1
  13. data/data/parg/cie.json +1 -1
  14. data/data/parg/csa.json +1 -1
  15. data/data/parg/ecma.json +1 -1
  16. data/data/parg/etsi.json +1 -1
  17. data/data/parg/evs.json +1 -1
  18. data/data/parg/gost.json +1 -1
  19. data/data/parg/iana.json +1 -1
  20. data/data/parg/idf.json +1 -1
  21. data/data/parg/iec.json +1 -1
  22. data/data/parg/iho.json +1 -0
  23. data/data/parg/isbn.json +1 -1
  24. data/data/parg/itu.json +1 -1
  25. data/data/parg/jcgm.json +1 -1
  26. data/data/parg/jis.json +1 -1
  27. data/data/parg/nist.json +1 -1
  28. data/data/parg/oiml.json +1 -1
  29. data/data/parg/omg.json +1 -1
  30. data/data/parg/plateau.json +1 -1
  31. data/data/parg/tgpp.json +1 -1
  32. data/data/parg/un.json +1 -1
  33. data/lib/pubid/adobe/identifier.rb +1 -1
  34. data/lib/pubid/adobe/parser.rb +2 -113
  35. data/lib/pubid/amca/identifiers/base.rb +1 -1
  36. data/lib/pubid/amca/parser.rb +1 -145
  37. data/lib/pubid/ansi/identifier.rb +1 -1
  38. data/lib/pubid/ansi/parser.rb +1 -82
  39. data/lib/pubid/api/builder.rb +32 -1
  40. data/lib/pubid/api/identifier.rb +1 -1
  41. data/lib/pubid/api/parser.rb +1 -131
  42. data/lib/pubid/ashrae/identifiers/base.rb +1 -1
  43. data/lib/pubid/ashrae/parser.rb +3 -710
  44. data/lib/pubid/asme/builder.rb +6 -4
  45. data/lib/pubid/asme/identifier.rb +1 -2
  46. data/lib/pubid/asme/parser.rb +1 -328
  47. data/lib/pubid/astm/builder.rb +12 -3
  48. data/lib/pubid/astm/identifier.rb +1 -2
  49. data/lib/pubid/astm/parser.rb +1 -227
  50. data/lib/pubid/bipm/identifier.rb +8 -1
  51. data/lib/pubid/bipm/parser.rb +2 -224
  52. data/lib/pubid/bsi/builder.rb +2 -4
  53. data/lib/pubid/bsi/parser.rb +1 -666
  54. data/lib/pubid/bsi/single_identifier.rb +38 -1
  55. data/lib/pubid/calconnect/parser.rb +2 -40
  56. data/lib/pubid/ccsds/identifier.rb +1 -1
  57. data/lib/pubid/ccsds/parser.rb +1 -66
  58. data/lib/pubid/cen_cenelec/identifier.rb +16 -1
  59. data/lib/pubid/cen_cenelec/parser.rb +3 -136
  60. data/lib/pubid/cie/identifier.rb +1 -1
  61. data/lib/pubid/cie/parser.rb +3 -378
  62. data/lib/pubid/conformance.rb +1 -1
  63. data/lib/pubid/csa/builder.rb +41 -18
  64. data/lib/pubid/csa/identifier.rb +12 -4
  65. data/lib/pubid/csa/identifiers/amendment.rb +28 -0
  66. data/lib/pubid/csa/identifiers.rb +1 -0
  67. data/lib/pubid/csa/parser.rb +16 -397
  68. data/lib/pubid/doi/parser.rb +2 -37
  69. data/lib/pubid/easc/builder.rb +1 -1
  70. data/lib/pubid/easc/parser.rb +2 -70
  71. data/lib/pubid/ecma/CLAUDE.md +8 -1
  72. data/lib/pubid/ecma/identifier.rb +13 -8
  73. data/lib/pubid/ecma/parser.rb +2 -54
  74. data/lib/pubid/ecma/renderer.rb +3 -7
  75. data/lib/pubid/errors.rb +18 -13
  76. data/lib/pubid/etsi/builder.rb +8 -5
  77. data/lib/pubid/etsi/identifiers/base.rb +1 -1
  78. data/lib/pubid/etsi/parser.rb +1 -132
  79. data/lib/pubid/evs/identifier.rb +7 -0
  80. data/lib/pubid/evs/parser.rb +1 -8
  81. data/lib/pubid/evs.rb +1 -1
  82. data/lib/pubid/gb/identifier.rb +6 -0
  83. data/lib/pubid/gb/parser.rb +2 -51
  84. data/lib/pubid/gost/identifier.rb +9 -1
  85. data/lib/pubid/gost/parser.rb +4 -81
  86. data/lib/pubid/iala/parser.rb +2 -121
  87. data/lib/pubid/iana/identifier.rb +1 -1
  88. data/lib/pubid/iana/parser.rb +2 -24
  89. data/lib/pubid/identifier.rb +78 -1
  90. data/lib/pubid/idf/builder.rb +42 -0
  91. data/lib/pubid/idf/identifier.rb +1 -1
  92. data/lib/pubid/idf/parser.rb +1 -137
  93. data/lib/pubid/idf.rb +1 -2
  94. data/lib/pubid/iec/builder.rb +158 -50
  95. data/lib/pubid/iec/identifier.rb +1 -1
  96. data/lib/pubid/iec/parser.rb +3 -430
  97. data/lib/pubid/ieee/aiee/identifier.rb +2 -1
  98. data/lib/pubid/ieee/aiee.rb +0 -1
  99. data/lib/pubid/ieee/builder.rb +2 -2
  100. data/lib/pubid/ieee/identifiers/base.rb +1 -1
  101. data/lib/pubid/ieee/ire/identifier.rb +2 -1
  102. data/lib/pubid/ieee/ire.rb +0 -1
  103. data/lib/pubid/ieee/nesc.rb +0 -1
  104. data/lib/pubid/ieee/parser.rb +1 -1257
  105. data/lib/pubid/ietf/identifiers/base.rb +17 -1
  106. data/lib/pubid/ietf/parser.rb +2 -47
  107. data/lib/pubid/ietf/renderer.rb +17 -2
  108. data/lib/pubid/iho/CLAUDE.md +89 -0
  109. data/lib/pubid/iho/builder.rb +4 -1
  110. data/lib/pubid/iho/identifiers/base.rb +28 -2
  111. data/lib/pubid/iho/renderer.rb +8 -0
  112. data/lib/pubid/iho/urn_generator.rb +11 -1
  113. data/lib/pubid/iho/urn_parser.rb +21 -11
  114. data/lib/pubid/iho.rb +0 -1
  115. data/lib/pubid/isbn/identifier.rb +1 -1
  116. data/lib/pubid/isbn/parser.rb +2 -31
  117. data/lib/pubid/iso/builder.rb +1 -1
  118. data/lib/pubid/iso/identifiers/directives.rb +6 -3
  119. data/lib/pubid/iso/identifiers/guide.rb +6 -3
  120. data/lib/pubid/iso/identifiers/international_workshop_agreement.rb +6 -3
  121. data/lib/pubid/iso/normalizer.rb +1 -1
  122. data/lib/pubid/iso/parser.rb +1 -539
  123. data/lib/pubid/iso/supplement_identifier.rb +6 -3
  124. data/lib/pubid/iso/utilities.rb +4 -5
  125. data/lib/pubid/iso.rb +1 -19
  126. data/lib/pubid/itu/builder.rb +36 -20
  127. data/lib/pubid/itu/identifiers/base.rb +15 -2
  128. data/lib/pubid/itu/parser.rb +1 -775
  129. data/lib/pubid/jcgm/builder.rb +35 -0
  130. data/lib/pubid/jcgm/parser.rb +1 -151
  131. data/lib/pubid/jcgm.rb +1 -2
  132. data/lib/pubid/jis/builder.rb +18 -29
  133. data/lib/pubid/jis/identifier.rb +1 -1
  134. data/lib/pubid/jis/parser.rb +1 -128
  135. data/lib/pubid/nist/builder.rb +5 -1
  136. data/lib/pubid/nist/caster.rb +13 -3
  137. data/lib/pubid/nist/identifiers/base.rb +37 -2
  138. data/lib/pubid/nist/identifiers/circular.rb +2 -2
  139. data/lib/pubid/nist/identifiers/circular_supplement.rb +2 -2
  140. data/lib/pubid/nist/identifiers/commercial_standards_monthly.rb +2 -2
  141. data/lib/pubid/nist/identifiers/crpl_report.rb +2 -2
  142. data/lib/pubid/nist/identifiers/handbook.rb +2 -2
  143. data/lib/pubid/nist/identifiers/internal_report.rb +2 -2
  144. data/lib/pubid/nist/identifiers/miscellaneous_publication.rb +2 -2
  145. data/lib/pubid/nist/identifiers/monograph.rb +2 -2
  146. data/lib/pubid/nist/identifiers/report.rb +2 -2
  147. data/lib/pubid/nist/parser.rb +19 -775
  148. data/lib/pubid/nist/router.rb +4 -1
  149. data/lib/pubid/nist/supplement_identifier.rb +2 -2
  150. data/lib/pubid/oasis/parser.rb +2 -16
  151. data/lib/pubid/ogc/parser.rb +2 -26
  152. data/lib/pubid/oiml/identifiers/certification_system.rb +7 -0
  153. data/lib/pubid/oiml/identifiers/dual_published.rb +2 -2
  154. data/lib/pubid/oiml/parser.rb +1 -303
  155. data/lib/pubid/oiml.rb +1 -2
  156. data/lib/pubid/omg/identifier.rb +6 -1
  157. data/lib/pubid/omg/parser.rb +2 -76
  158. data/lib/pubid/parser.rb +5 -4
  159. data/lib/pubid/parsers/mr_string.rb +1 -1
  160. data/lib/pubid/plateau/parser.rb +1 -66
  161. data/lib/pubid/plateau.rb +1 -2
  162. data/lib/pubid/renderers/directives_renderer.rb +1 -1
  163. data/lib/pubid/renderers/iwa_renderer.rb +1 -1
  164. data/lib/pubid/renderers/publisher_stripper.rb +82 -0
  165. data/lib/pubid/renderers/supplement_renderer.rb +1 -1
  166. data/lib/pubid/renderers.rb +1 -0
  167. data/lib/pubid/sae/parser.rb +1 -48
  168. data/lib/pubid/tgpp/identifier.rb +1 -1
  169. data/lib/pubid/tgpp/parser.rb +2 -59
  170. data/lib/pubid/un/identifier.rb +1 -1
  171. data/lib/pubid/un/parser.rb +1 -18
  172. data/lib/pubid/version.rb +1 -1
  173. data/lib/pubid/w3c/parser.rb +2 -27
  174. data/lib/pubid/xsf/identifier.rb +10 -6
  175. data/lib/pubid/xsf/parser.rb +3 -31
  176. data/lib/pubid/xsf/renderer.rb +2 -4
  177. data/lib/pubid.rb +8 -9
  178. metadata +6 -23
  179. data/lib/pubid/ieee/aiee/parser.rb +0 -130
  180. data/lib/pubid/ieee/ire/parser.rb +0 -109
  181. data/lib/pubid/ieee/nesc/parser.rb +0 -155
  182. data/lib/pubid/iho/parser.rb +0 -68
  183. data/lib/pubid/parser/common_parse_methods.rb +0 -13
  184. data/lib/pubid/parser/common_parse_rules.rb +0 -56
  185. data/lib/pubid/parser/grammar.rb +0 -96
@@ -1,130 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "parslet"
4
-
5
- module Pubid
6
- module Ieee
7
- module Aiee
8
- # Parser for AIEE (American Institute of Electrical Engineers) identifiers
9
- # Historical period: 1884-1963 (merged into IEEE in 1963)
10
- class Parser < ::Pubid::Parser::Grammar
11
- # Basic building blocks
12
- rule(:space) { str(" ") }
13
- rule(:space?) { space.maybe }
14
- rule(:dash) { str("-") }
15
- rule(:dot) { str(".") }
16
- rule(:digit) { match("[0-9]") }
17
- rule(:digits) { digit.repeat(1) }
18
- rule(:letter) { match("[A-Za-z]") }
19
- rule(:upper) { match("[A-Z]") }
20
-
21
- # Year pattern (for AIEE period: 1884-1963)
22
- rule(:year) do
23
- (str("18") >> digit.repeat(2, 2)) | # 1884-1899
24
- (str("19") >> (str("0") | str("1") | str("2") | str("3") | str("4") | str("5")) >> digit) | # 1900-1959
25
- (str("196") >> match("[0-3]")) # 1960-1963
26
- end
27
-
28
- # Month patterns
29
- rule(:month_name) do
30
- str("January") | str("February") | str("March") | str("April") |
31
- str("May") | str("June") | str("July") | str("August") |
32
- str("September") | str("October") | str("November") | str("December") |
33
- str("Jan") | str("Feb") | str("Mar") | str("Apr") | str("Jun") |
34
- str("Jul") | str("Aug") | str("Sep") | str("Sept") | str("Oct") | str("Nov") | str("Dec")
35
- end
36
-
37
- # AIEE prefix variations
38
- rule(:aiee_prefix) do
39
- (
40
- str("IEEE-AIEE") | # Transitional period (1963-1965)
41
- str("A.I.E.E.") | # With dots variant (no spaces)
42
- str("A. I. E. E.") | # With dots and spaces variant
43
- str("AIEE")
44
- ).as(:publisher)
45
- end
46
-
47
- # Document types
48
- rule(:aiee_type) do
49
- (
50
- str("Standard No.") | # AIEE Standard No. 19-1938 (compound type)
51
- str("Standard No") | # AIEE Standard No 19-1938 (compound type, no dot)
52
- str("Std No.") | # AIEE Std No. 800
53
- str("Std No") | # AIEE Std No 800 (no dot)
54
- str("Std") | # AIEE Std 800
55
- str("Nos") | # NEW Session 171: Plural variant (e.g., "Nos 72 and 73")
56
- str("No.") | # AIEE No. 56
57
- str("No") | # AIEE No 18 (can be followed by space)
58
- str("no") | # AIEE no 700 (lowercase variant)
59
- str("Standard") | # AIEE Standard 56
60
- str("Trans.") # AIEE Trans. PAS-84
61
- ).as(:type)
62
- end
63
-
64
- # Number formats
65
- rule(:number) do
66
- (
67
- # Transaction format: PAS-84, PGI-7
68
- (upper.repeat(2, 3) >> dash >> digits) |
69
-
70
- # Complex with letter suffix: 27A, 22A, 1E - allow space before dash
71
- # But don't match if it's actually "Nos 72 and 73" pattern
72
- (digits >> upper >> (space >> str("and")).absent?) |
73
-
74
- # Decimal number: 750.1, 750.11, 750.5
75
- (digits >> dot >> digits) |
76
-
77
- # Number with parenthetical variant: 431 (105)
78
- # Pattern: main number followed by alternate number in parentheses
79
- (digits.as(:main_number) >> space >> (str("(") >> digits.as(:alt_number) >> str(")")).as(:parenthetical)) |
80
-
81
- # Simple number: 56, 123, 18, 552
82
- (digits >>
83
-
84
- # Handle "Nos X and Y" pattern - we only capture first number
85
- (space >> str("and") >> space >> digits).absent?)
86
- ).as(:number)
87
- end
88
-
89
- # Date formats
90
- # Long form: ", 1956" or ", November 1955" or ". December 1958" or " -1957" (with space)
91
- # NEW: Also support "May-1928" (month dash year, no comma)
92
- rule(:date_long) do
93
- space? >>
94
- (
95
- # Format 1: ", Month Year" or ". Month Year"
96
- ((str(",") | dot).as(:separator) >> space? >>
97
- (month_name.as(:month) >> space).maybe >> year.as(:year)) |
98
- # Format 2: " -Year" (space dash year)
99
- ((space >> dash).as(:separator) >> space? >> year.as(:year)) |
100
- # Format 3: "Month-Year" (NEW - month dash year, no comma/dot/space prefix)
101
- (month_name.as(:month) >> dash >> year.as(:year))
102
- )
103
- end
104
-
105
- # Short form: "-1962" (directly after number) or " -1958" (with space)
106
- # ENHANCED: Allow leading space for patterns like "431 (105) -1958"
107
- rule(:date_short) do
108
- space.maybe >> dash >> year.as(:year)
109
- end
110
-
111
- # Combined date rule
112
- # Try short form first to avoid matching empty prefix in date_long
113
- rule(:date) do
114
- (date_short | date_long).maybe
115
- end
116
-
117
- # Complete AIEE identifier
118
- rule(:aiee_identifier) do
119
- aiee_prefix >>
120
- space >>
121
- (aiee_type >> space).maybe >>
122
- number >>
123
- date
124
- end
125
-
126
- root(:aiee_identifier)
127
- end
128
- end
129
- end
130
- end
@@ -1,109 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "parslet"
4
-
5
- module Pubid
6
- module Ieee
7
- module Ire
8
- # Parser for IRE (Institute of Radio Engineers) identifiers
9
- # Historical period: 1912-1963 (merged into IEEE in 1963)
10
- class Parser < ::Pubid::Parser::Grammar
11
- # Basic building blocks
12
- rule(:space) { str(" ") }
13
- rule(:space?) { space.maybe }
14
- rule(:dash) { str("-") }
15
- rule(:dot) { str(".") }
16
- rule(:digit) { match("[0-9]") }
17
- rule(:digits) { digit.repeat(1) }
18
- rule(:letter) { match("[A-Za-z]") }
19
- rule(:upper) { match("[A-Z]") }
20
-
21
- # Year pattern - handle both 2-digit (52 = 1952) and 4-digit (1952) formats
22
- rule(:year_short) do
23
- # 2-digit year: 12-63 (1912-1963 IRE period)
24
- match("[1-6]") >> digit
25
- end
26
-
27
- rule(:year_full) do
28
- # 4-digit year for IRE period: 1912-1963
29
- (str("191") >> digit.repeat(1, 1)) | # 1912-1919
30
- (str("19") >> (str("2") | str("3") | str("4") | str("5")) >> digit) | # 1920-1959
31
- (str("196") >> match("[0-3]")) # 1960-1963
32
- end
33
-
34
- rule(:year) { year_full | year_short }
35
-
36
- # IRE prefix variations
37
- rule(:ire_prefix) do
38
- (
39
- str("IEEE-IRE") | # Transitional period (1963-1965)
40
- str("IRE")
41
- ).as(:publisher)
42
- end
43
-
44
- # Document types
45
- rule(:ire_type) do
46
- (
47
- str("Trans.") | # IRE Trans. PGI-7
48
- str("Standard") | # IRE Standard
49
- str("Std") # IRE Std
50
- ).as(:type)
51
- end
52
-
53
- # Number formats
54
- rule(:number) do
55
- (
56
- # Complex format with spaces: 28 S1, 15.S1, 7.S2
57
- (digits >> (space | dot) >> upper >> digits) |
58
-
59
- # Complex format: 1.IRE62.1S1
60
- (digits >> dot >> str("IRE") >> digits >> dot >> digits >> upper >> digits) |
61
-
62
- # Transaction format: PGI-7, PGAP-4
63
- (upper.repeat(2, 4) >> dash >> digits) |
64
-
65
- # Simple number: 56, 123
66
- digits
67
- ).as(:number)
68
- end
69
-
70
- # Date (year only for IRE)
71
- rule(:date) do
72
- (space? >> (dash | str(",")).maybe >> space? >> year.as(:year)).maybe
73
- end
74
-
75
- # Complete IRE identifier - YEAR FIRST format
76
- rule(:ire_identifier_year_first) do
77
- # Format: "52 IRE 7.S2" or "1952 IRE 7.S2"
78
- year.as(:year) >>
79
- space >>
80
- ire_prefix >>
81
- space >>
82
- (ire_type >> space).maybe >>
83
- number >>
84
- (space? >> (dash | str(",")).maybe >> space? >> year_full.as(:full_year)).maybe
85
- end
86
-
87
- # Prefix-first format: "IRE 7.S2-1952" (pubid#316 family 2) — the
88
- # year trails the designation instead of leading the identifier.
89
- # The renderer always emits the year-first short-year form, so this
90
- # spelling canonicalizes onto it ("IRE 7.S2-1952" → "52 IRE 7.S2").
91
- rule(:ire_identifier_prefix_first) do
92
- ire_prefix >>
93
- space >>
94
- (ire_type >> space).maybe >>
95
- number >>
96
- date
97
- end
98
-
99
- # Year-first is tried first so the original spellings keep their
100
- # match; prefix-first claims only what year-first cannot.
101
- rule(:ire_identifier) do
102
- ire_identifier_year_first | ire_identifier_prefix_first
103
- end
104
-
105
- root(:ire_identifier)
106
- end
107
- end
108
- end
109
- end
@@ -1,155 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "parslet"
4
-
5
- module Pubid
6
- module Ieee
7
- module Nesc
8
- # Parser for National Electrical Safety Code (NESC) identifiers
9
- #
10
- # Handles multiple NESC identifier formats including:
11
- # - Standard C2-YYYY format
12
- # - Year-first YYYY NESC format
13
- # - Draft format
14
- # - Handbook and Redline variations
15
- #
16
- # @example Parse C2 standard
17
- # parser = Parser.new
18
- # result = parser.parse("C2-1997 National Electric Safety Code")
19
- #
20
- # @example Parse handbook
21
- # parser = Parser.new
22
- # result = parser.parse("2017 NESC Handbook, Premier Edition")
23
- class Parser < ::Pubid::Parser::Grammar
24
- root(:nesc_identifier)
25
-
26
- rule(:space) { str(" ") }
27
- rule(:comma) { str(",") }
28
- rule(:digit) { match("[0-9]") }
29
- rule(:year) { digit.repeat(4, 4) }
30
- rule(:dash) { str("-") }
31
-
32
- # C2 code designation
33
- rule(:c2_code) do
34
- str("C2").as(:code)
35
- end
36
-
37
- # NESC name variations (the "(R)" registered mark is captured
38
- # separately by the `registered` rule so it can be round-tripped)
39
- rule(:nesc_full_name) do
40
- str("National Electrical Safety Code") |
41
- str("National Electric Safety Code") # Typo variation
42
- end
43
-
44
- rule(:nesc_abbr) do
45
- str("NESC")
46
- end
47
-
48
- rule(:nesc_name) do
49
- nesc_full_name | nesc_abbr
50
- end
51
-
52
- # Registered trademark notation
53
- rule(:registered) do
54
- str("(R)")
55
- end
56
-
57
- # Edition notations
58
- rule(:edition) do
59
- (
60
- str("Premier Edition") |
61
- str("First Edition") |
62
- str("Second Edition") |
63
- str("Third Edition") |
64
- str("Fourth Edition") |
65
- str("Fifth Edition") |
66
- str("Sixth Edition") |
67
- str("Seventh Edition") |
68
- str("Eighth Edition") |
69
- str("Ninth Edition") |
70
- str("Tenth Edition")
71
- ).as(:edition)
72
- end
73
-
74
- # Variant types (Handbook, Redline)
75
- rule(:variant) do
76
- (
77
- str("Handbook") |
78
- str("Redline")
79
- ).as(:variant)
80
- end
81
-
82
- # Month names for drafts
83
- rule(:month) do
84
- (
85
- str("January") | str("February") | str("March") |
86
- str("April") | str("May") | str("June") |
87
- str("July") | str("August") | str("September") |
88
- str("October") | str("November") | str("December")
89
- ).as(:month)
90
- end
91
-
92
- # Pattern 1: C2-YYYY Standard format
93
- # Examples: "C2-1997 National Electric Safety Code (NESC)"
94
- # "C2-2012 National Electrical Safety Code"
95
- rule(:c2_standard) do
96
- c2_code >>
97
- dash >>
98
- year.as(:year) >>
99
- (comma.maybe >> space).maybe >>
100
- nesc_full_name >> registered.maybe >>
101
- (space >> str("(") >> nesc_abbr >> registered.maybe >> str(")")).maybe
102
- end
103
-
104
- # Pattern 2: YYYY NESC format (year-first)
105
- # Examples: "2017 NESC(R) Handbook, Premier Edition"
106
- # "2017 National Electrical Safety Code(R) (NESC(R))"
107
- # "2012 NESC Handbook"
108
- rule(:year_first) do
109
- year.as(:year) >>
110
- space >>
111
- (
112
- # Full name with optional (NESC) abbreviation suffix
113
- (nesc_full_name.as(:full_name) >> registered.as(:name_registered).maybe >>
114
- (space >> str("(") >> nesc_abbr.as(:paren_abbr) >>
115
- registered.as(:paren_registered).maybe >> str(")")).maybe) |
116
- # Just the NESC abbreviation (e.g. "2017 NESC(R) Handbook")
117
- (nesc_abbr.as(:abbr) >> registered.as(:abbr_registered).maybe)
118
- ) >>
119
- (space >> variant).maybe >>
120
- (comma >> space >> edition).maybe
121
- end
122
-
123
- # Pattern 3: Name-first format
124
- # Examples: "National Electrical Safety Code, C2-2012"
125
- # "National Electrical Safety Code, C2-2012 - Redline"
126
- rule(:name_first) do
127
- nesc_full_name >> registered.maybe >>
128
- comma >>
129
- space >>
130
- c2_code >>
131
- dash >>
132
- year.as(:year) >>
133
- (space >> str("-") >> space >> variant.as(:variant)).maybe
134
- end
135
-
136
- # Pattern 4: Draft format
137
- # Examples: "Draft National Electrical Safety Code, January 2016"
138
- # "Draft NESC, June 2011"
139
- rule(:draft_nesc) do
140
- str("Draft").as(:draft) >>
141
- space >>
142
- nesc_name >> registered.maybe >>
143
- comma >> space >>
144
- month >> space >> year.as(:year)
145
- end
146
-
147
- # Main identifier rule - try patterns in order
148
- # Put most specific patterns first
149
- rule(:nesc_identifier) do
150
- draft_nesc | name_first | c2_standard | year_first
151
- end
152
- end
153
- end
154
- end
155
- end
@@ -1,68 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "parslet"
4
-
5
- module Pubid
6
- module Iho
7
- # Parser class for IHO identifiers
8
- class Parser < ::Pubid::Parser::Grammar
9
- rule(:space) { str(" ") }
10
- rule(:dash) { str("-") }
11
- rule(:dot) { str(".") }
12
- rule(:digits) { match("[0-9]").repeat(1) }
13
-
14
- rule(:series) do
15
- (str("S") | str("P") | str("M") | str("B") | str("C")).as(:type)
16
- end
17
-
18
- rule(:number_suffix) do
19
- (str(":") >> digits) | (str("/") >> digits) | (dash >> digits) | match("[A-Z]")
20
- end
21
-
22
- rule(:number) do
23
- (digits >> number_suffix.maybe).as(:number)
24
- end
25
-
26
- rule(:appendix) do
27
- space >> (str("Appendix") | str("Ap.")) >> space >>
28
- (
29
- (match("[A-Z]") >> dash >> digits) |
30
- digits |
31
- match("[A-Z]")
32
- ).as(:appendix)
33
- end
34
-
35
- rule(:part) do
36
- space >> str("Part") >> space >>
37
- (
38
- (digits >> match("[a-zA-Z]").repeat).as(:part) |
39
- match("[A-Z]").as(:part)
40
- )
41
- end
42
-
43
- rule(:annex) do
44
- space >> str("Annex") >> space >> match("[A-Z]").as(:annex)
45
- end
46
-
47
- rule(:supplement) do
48
- space >> str("Suppl") >> space >> digits.as(:supplement)
49
- end
50
-
51
- rule(:version) do
52
- space >> (digits >> dot >> digits >> dot >> digits).as(:version)
53
- end
54
-
55
- rule(:identifier) do
56
- (str("IHO") >> space).maybe >>
57
- series >> dash >> number >>
58
- appendix.maybe >> part.maybe >> annex.maybe >> supplement.maybe >> version.maybe
59
- end
60
-
61
- root :identifier
62
-
63
- def self.parse(string)
64
- new.parse(string.strip)
65
- end
66
- end
67
- end
68
- end
@@ -1,13 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Pubid
4
- module Parser
5
- module CommonParseMethods
6
- def array_to_str(array)
7
- array.reduce(str(array.first)) do |acc, value|
8
- acc | str(value)
9
- end
10
- end
11
- end
12
- end
13
- end
@@ -1,56 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Pubid
4
- module Parser
5
- module CommonParseRules
6
- def self.included(base)
7
- base.class_eval do
8
- rule(:space) { str(" ") }
9
- rule(:space?) { space.maybe }
10
-
11
- rule(:digits) do
12
- match('\d').repeat(1)
13
- end
14
-
15
- rule(:year) do
16
- match('\d').repeat(4, 4).as(:year)
17
- end
18
-
19
- rule(:comma) { str(", ") }
20
- rule(:comma?) { comma.maybe }
21
- rule(:comma_space) { comma | space }
22
- rule(:dash) { str("-") }
23
- rule(:dot) { str(".") }
24
- rule(:words_digits) { match('[\dA-Za-z]').repeat(1) }
25
- rule(:words) { match("[A-Za-z]").repeat(1) }
26
- rule(:words?) { words.maybe }
27
- rule(:year_digits) do
28
- (str("19") | str("20")) >> match('\d').repeat(2,
29
- 2) >> digits.absent?
30
- end
31
-
32
- rule(:month_digits) do
33
- match('\d').repeat(2, 2)
34
- end
35
-
36
- rule(:day_digits) do
37
- match('\d').repeat(2, 2)
38
- end
39
-
40
- rule(:originator) do
41
- organization.as(:publisher) >>
42
- (space? >> str("/") >> organization.as(:copublisher)).repeat
43
- end
44
-
45
- rule(:comma_month_year) do
46
- comma >> words.as(:month) >> space >> year_digits.as(:year)
47
- end
48
-
49
- rule(:year_month) do
50
- year_digits >> dash >> month_digits
51
- end
52
- end
53
- end
54
- end
55
- end
56
- end
@@ -1,96 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "parslet"
4
-
5
- module Pubid
6
- module Parser
7
- # The superclass of every flavor grammar.
8
- #
9
- # Its only job is to keep parslet out of pubid's public contract. Every
10
- # grammar failure originates in `Parslet::Atoms::Base#parse`, which
11
- # `Parslet::Parser` does not override, so one override here covers all 46
12
- # grammars, both public entry points of every flavor, and the cross-flavor
13
- # delegation routes (`Pubid::Iso.parse("ITU-T G.711")` runs ITU's grammar)
14
- # — without touching the 131 `parse` methods.
15
- #
16
- # The name is `Grammar`, not `Base`, because {Pubid::Parsers::Base} already
17
- # exists and means something unrelated (the MR-string parser).
18
- #
19
- # Known limit: a rule atom parsed directly, `Parser.new.<rule>.parse(str)`,
20
- # bypasses this and raises a bare `Parslet::ParseFailed`. Nothing in the
21
- # gem does that.
22
- class Grammar < ::Parslet::Parser
23
- # A trailing "(all parts)" marks the reference as the whole document.
24
- # The flavor grammars that carry their own rule consume it inside
25
- # parslet; this shared strip gives every other flavor the same read:
26
- # the suffix never reaches the flavor grammar, and the parsed tree
27
- # carries :all_parts for the builder to wrap (see Builder::Base).
28
- ALL_PARTS_SUFFIX = "(all parts)".freeze
29
-
30
- # @param io [String, IO]
31
- # @param options [Hash] passed through to parslet
32
- # @raise [Pubid::Errors::ParseError]
33
- def parse(io, options = {})
34
- if io.is_a?(String) && io.end_with?(ALL_PARTS_SUFFIX)
35
- base = io.sub(/\s*\(all parts\)\s*\z/, "")
36
- return mark_all_parts(super(base, options))
37
- end
38
-
39
- super
40
- rescue ::Pubid::Errors::ParseError
41
- # A nested grammar already wrapped it. Keep the inner flavor and input.
42
- raise
43
- rescue ::Parslet::ParseFailed => e
44
- raise wrap_parse_failure(e, io)
45
- end
46
-
47
- private
48
-
49
- # Carry the stripped suffix into the tree. Parslet tops are a Hash or
50
- # an Array of Hashes; the marker joins either shape, and every builder
51
- # (Builder::Base and the standalone ones) routes it to #to_all_parts.
52
- def mark_all_parts(tree)
53
- case tree
54
- when Hash then tree.merge(all_parts: true)
55
- when Array then tree.map { |t| t.merge(all_parts: true) }
56
- else tree
57
- end
58
- end
59
-
60
- # @param error [Parslet::ParseFailed]
61
- # @param io [String, IO] what was handed to {#parse}
62
- # @return [Pubid::Errors::ParseError]
63
- def wrap_parse_failure(error, io)
64
- ::Pubid::Errors::ParseError.new(
65
- error.message,
66
- error.parse_failure_cause,
67
- input: io.is_a?(String) ? io : nil,
68
- flavor: pubid_flavor_name,
69
- )
70
- end
71
-
72
- # "Pubid::Iso::Parser" -> "iso"; "Pubid::Ieee::Aiee::Parser" -> "ieee".
73
- #
74
- # Resolved through {Pubid::Registry} rather than taken from the module
75
- # name, because the two disagree: `Pubid::Tgpp` registers as `"3gpp"`,
76
- # and `Pubid::CenCenelec` registers twice (`"cen_cenelec"` first, then
77
- # the `"cen"` alias). Reporting the registered name is what lets a caller
78
- # feed `error.flavor` straight back to `Pubid::Registry.get`.
79
- # @return [String, nil]
80
- def pubid_flavor_name
81
- parts = self.class.name.to_s.split("::")
82
- return nil unless parts[0] == "Pubid" && parts.length > 1
83
-
84
- registered_flavor_name(parts[1]) || parts[1].downcase
85
- end
86
-
87
- # @param module_name [String] e.g. "Tgpp"
88
- # @return [String, nil] the registered name, nil if not registered
89
- def registered_flavor_name(module_name)
90
- ::Pubid::Registry.canonical_name(::Pubid.const_get(module_name))
91
- rescue ::NameError
92
- nil
93
- end
94
- end
95
- end
96
- end