pubid 2.0.0.pre.alpha.12 → 2.0.0.pre.alpha.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.adoc +43 -1
- data/data/ieee/update_codes.yaml +17 -4
- data/data/nist/update_codes.yaml +7 -3
- data/data/parg/tables/bipm_groups.yaml +14 -0
- data/data/parg/tables/bipm_type_codes.yaml +5 -0
- data/data/parg/tables/bipm_type_names_en.yaml +6 -0
- data/data/parg/tables/bipm_type_names_fr.yaml +6 -0
- data/data/parg/tables/directives_supplements_typed_stages.yaml +3 -0
- data/data/parg/tables/directives_typed_stages.yaml +5 -0
- data/data/parg/tables/idf_typed_stages.yaml +27 -0
- data/data/parg/tables/idf_typed_stages_supplements.yaml +2 -0
- data/data/parg/tables/iec_typed_stages.yaml +130 -0
- data/data/parg/tables/iso_publishers.yaml +4 -0
- data/data/parg/tables/organizations.yaml +12 -0
- data/data/parg/tables/tc_types.yaml +42 -0
- data/data/parg/tables/typed_stages.yaml +114 -0
- data/data/parg/tables/typed_stages_supplements.yaml +64 -0
- data/data/parg/tables/wg_types.yaml +21 -0
- data/lib/pubid/adobe/builder.rb +2 -0
- data/lib/pubid/adobe/identifier.rb +11 -1
- data/lib/pubid/all_parts.rb +201 -0
- data/lib/pubid/all_parts_identifier.rb +19 -0
- data/lib/pubid/amca/CLAUDE.md +47 -0
- data/lib/pubid/amca/builder.rb +3 -5
- data/lib/pubid/amca/identifiers/base.rb +11 -1
- data/lib/pubid/amca/identifiers/publication.rb +13 -0
- data/lib/pubid/amca/parser.rb +2 -1
- data/lib/pubid/amca/renderer.rb +22 -33
- data/lib/pubid/amca/urn_generator.rb +21 -2
- data/lib/pubid/amca/urn_parser.rb +36 -10
- data/lib/pubid/ansi/builder.rb +6 -0
- data/lib/pubid/ansi/identifier.rb +1 -1
- data/lib/pubid/api/CLAUDE.md +23 -0
- data/lib/pubid/api/builder.rb +2 -0
- data/lib/pubid/api/identifier.rb +1 -1
- data/lib/pubid/api/parser.rb +8 -4
- data/lib/pubid/ashrae/CLAUDE.md +13 -0
- data/lib/pubid/ashrae/builder.rb +58 -14
- data/lib/pubid/ashrae/identifiers/base.rb +10 -1
- data/lib/pubid/ashrae/identifiers/errata.rb +14 -2
- data/lib/pubid/ashrae/identifiers/interpretation.rb +2 -10
- data/lib/pubid/ashrae/parser.rb +80 -39
- data/lib/pubid/ashrae/renderer.rb +32 -1
- data/lib/pubid/ashrae/urn_generator.rb +32 -9
- data/lib/pubid/asme/CLAUDE.md +25 -0
- data/lib/pubid/asme/builder.rb +16 -9
- data/lib/pubid/asme/components/code.rb +2 -0
- data/lib/pubid/asme/identifier.rb +1 -1
- data/lib/pubid/asme/identifiers/standard.rb +6 -1
- data/lib/pubid/asme/parser.rb +41 -14
- data/lib/pubid/astm/CLAUDE.md +9 -0
- data/lib/pubid/astm/builder.rb +2 -0
- data/lib/pubid/astm/components/code.rb +2 -0
- data/lib/pubid/astm/identifier.rb +1 -1
- data/lib/pubid/astm/parser.rb +4 -1
- data/lib/pubid/bipm/CLAUDE.md +11 -0
- data/lib/pubid/bipm/builder.rb +2 -0
- data/lib/pubid/bipm/identifier.rb +1 -1
- data/lib/pubid/bsi/CLAUDE.md +93 -0
- data/lib/pubid/bsi/builder.rb +13 -11
- data/lib/pubid/bsi/identifiers/addendum_document.rb +2 -0
- data/lib/pubid/bsi/identifiers/adopted_european_norm.rb +6 -54
- data/lib/pubid/bsi/identifiers/adopted_international_standard.rb +5 -22
- data/lib/pubid/bsi/identifiers/amendment.rb +36 -12
- data/lib/pubid/bsi/identifiers/bundled_identifier.rb +2 -0
- data/lib/pubid/bsi/identifiers/consolidated_identifier.rb +23 -26
- data/lib/pubid/bsi/identifiers/corrigendum.rb +29 -12
- data/lib/pubid/bsi/identifiers/expert_commentary.rb +6 -7
- data/lib/pubid/bsi/identifiers/national_annex.rb +18 -20
- data/lib/pubid/bsi/identifiers/root_identity.rb +31 -0
- data/lib/pubid/bsi/identifiers/set.rb +2 -0
- data/lib/pubid/bsi/identifiers/supplement_document.rb +2 -0
- data/lib/pubid/bsi/identifiers.rb +1 -0
- data/lib/pubid/bsi/parser.rb +8 -8
- data/lib/pubid/bsi/renderer.rb +20 -20
- data/lib/pubid/bsi/single_identifier.rb +1 -3
- data/lib/pubid/bsi/urn_generator.rb +28 -18
- data/lib/pubid/builder/base.rb +27 -0
- data/lib/pubid/calconnect/builder.rb +2 -0
- data/lib/pubid/calconnect/identifier.rb +5 -1
- data/lib/pubid/ccsds/builder.rb +2 -0
- data/lib/pubid/ccsds/identifier.rb +9 -1
- data/lib/pubid/cen_cenelec/CLAUDE.md +59 -0
- data/lib/pubid/cen_cenelec/builder.rb +6 -1
- data/lib/pubid/cen_cenelec/identifier.rb +12 -28
- data/lib/pubid/cen_cenelec/identifiers/amendment.rb +3 -10
- data/lib/pubid/cen_cenelec/identifiers/corrigendum.rb +3 -10
- data/lib/pubid/cen_cenelec/parser.rb +20 -5
- data/lib/pubid/cie/CLAUDE.md +58 -0
- data/lib/pubid/cie/builder.rb +2 -0
- data/lib/pubid/cie/components/language.rb +2 -0
- data/lib/pubid/cie/identifier.rb +1 -1
- data/lib/pubid/cie/parser.rb +9 -2
- data/lib/pubid/components/adoption.rb +2 -0
- data/lib/pubid/components/code.rb +2 -0
- data/lib/pubid/components/date.rb +8 -6
- data/lib/pubid/components/edition.rb +2 -0
- data/lib/pubid/components/iteration.rb +2 -0
- data/lib/pubid/components/language.rb +2 -0
- data/lib/pubid/components/locality.rb +2 -0
- data/lib/pubid/components/publisher.rb +2 -0
- data/lib/pubid/components/relationship.rb +2 -0
- data/lib/pubid/components/stage.rb +2 -0
- data/lib/pubid/components/supplement.rb +2 -0
- data/lib/pubid/components/type.rb +2 -0
- data/lib/pubid/components/typed_stage.rb +8 -0
- data/lib/pubid/conformance/checks.rb +1 -1
- data/lib/pubid/csa/CLAUDE.md +41 -0
- data/lib/pubid/csa/builder.rb +2 -0
- data/lib/pubid/csa/identifier.rb +19 -3
- data/lib/pubid/csa/parser.rb +25 -8
- data/lib/pubid/csa/renderer.rb +12 -12
- data/lib/pubid/csa/single_identifier.rb +17 -0
- data/lib/pubid/doi/builder.rb +2 -0
- data/lib/pubid/doi/identifier.rb +1 -1
- data/lib/pubid/easc/builder.rb +2 -0
- data/lib/pubid/easc/identifier.rb +10 -1
- data/lib/pubid/ecma/CLAUDE.md +28 -0
- data/lib/pubid/ecma/builder.rb +2 -0
- data/lib/pubid/ecma/identifier.rb +8 -1
- data/lib/pubid/etsi/CLAUDE.md +34 -0
- data/lib/pubid/etsi/builder.rb +2 -0
- data/lib/pubid/etsi/components/code.rb +6 -0
- data/lib/pubid/etsi/components/version.rb +2 -0
- data/lib/pubid/etsi/identifiers/base.rb +1 -1
- data/lib/pubid/etsi/identifiers/etsi_standard.rb +7 -0
- data/lib/pubid/evs/CLAUDE.md +58 -0
- data/lib/pubid/evs/builder.rb +2 -0
- data/lib/pubid/evs.rb +1 -1
- data/lib/pubid/gb/CLAUDE.md +140 -0
- data/lib/pubid/gb/builder.rb +7 -2
- data/lib/pubid/gb/identifier.rb +6 -4
- data/lib/pubid/gb/identifiers/all_parts.rb +17 -0
- data/lib/pubid/gb/identifiers.rb +1 -0
- data/lib/pubid/gb/renderer.rb +0 -1
- data/lib/pubid/gost/CLAUDE.md +64 -0
- data/lib/pubid/gost/builder.rb +3 -1
- data/lib/pubid/gost/identifier.rb +16 -1
- data/lib/pubid/gost/parser.rb +8 -1
- data/lib/pubid/iala/CLAUDE.md +82 -0
- data/lib/pubid/iala/builder.rb +2 -0
- data/lib/pubid/iala/identifier.rb +10 -1
- data/lib/pubid/iana/CLAUDE.md +7 -0
- data/lib/pubid/iana/builder.rb +2 -0
- data/lib/pubid/iana/identifier.rb +1 -1
- data/lib/pubid/identifier.rb +161 -17
- data/lib/pubid/idf/builder.rb +11 -1
- data/lib/pubid/idf/identifier.rb +5 -0
- data/lib/pubid/idf/identifiers/all_parts.rb +17 -0
- data/lib/pubid/idf/identifiers.rb +1 -0
- data/lib/pubid/iec/CLAUDE.md +31 -0
- data/lib/pubid/iec/builder.rb +7 -1
- data/lib/pubid/iec/components/consolidated_amendment.rb +4 -0
- data/lib/pubid/iec/components/sheet.rb +2 -0
- data/lib/pubid/iec/components/trf_info.rb +2 -0
- data/lib/pubid/iec/components/vap_suffix.rb +2 -0
- data/lib/pubid/iec/identifier.rb +8 -3
- data/lib/pubid/iec/identifiers/all_parts.rb +19 -0
- data/lib/pubid/iec/identifiers.rb +1 -0
- data/lib/pubid/iec/parser.rb +9 -4
- data/lib/pubid/iec/renderer.rb +0 -1
- data/lib/pubid/iec/urn_generator.rb +9 -1
- data/lib/pubid/iec/urn_parser.rb +3 -2
- data/lib/pubid/ieee/CLAUDE.md +97 -0
- data/lib/pubid/ieee/builder.rb +194 -27
- data/lib/pubid/ieee/components/code.rb +2 -0
- data/lib/pubid/ieee/components/draft.rb +35 -2
- data/lib/pubid/ieee/components/typed_stage.rb +2 -0
- data/lib/pubid/ieee/identifiers/base.rb +21 -1
- data/lib/pubid/ieee/identifiers/iec_ieee_copublished.rb +9 -0
- data/lib/pubid/ieee/identifiers/joint_development.rb +66 -23
- data/lib/pubid/ieee/identifiers/project_draft_identifier.rb +8 -1
- data/lib/pubid/ieee/parser.rb +156 -29
- data/lib/pubid/ieee/renderer.rb +42 -7
- data/lib/pubid/ieee/urn_generator.rb +31 -0
- data/lib/pubid/ietf/CLAUDE.md +7 -0
- data/lib/pubid/ietf/builder.rb +2 -0
- data/lib/pubid/ietf/identifiers/base.rb +1 -1
- data/lib/pubid/iho/builder.rb +2 -0
- data/lib/pubid/isbn/builder.rb +2 -0
- data/lib/pubid/isbn/identifier.rb +1 -1
- data/lib/pubid/iso/CLAUDE.md +47 -0
- data/lib/pubid/iso/builder.rb +19 -5
- data/lib/pubid/iso/components/publisher.rb +2 -0
- data/lib/pubid/iso/identifier.rb +10 -15
- data/lib/pubid/iso/identifiers/all_parts.rb +19 -0
- data/lib/pubid/iso/identifiers/directives_supplement.rb +4 -2
- data/lib/pubid/iso/identifiers.rb +1 -0
- data/lib/pubid/iso/normalizer.rb +4 -1
- data/lib/pubid/iso/rendering_style.rb +0 -1
- data/lib/pubid/itu/CLAUDE.md +115 -0
- data/lib/pubid/itu/builder.rb +26 -4
- data/lib/pubid/itu/components/code.rb +2 -0
- data/lib/pubid/itu/components/designation.rb +2 -0
- data/lib/pubid/itu/components/sector.rb +2 -0
- data/lib/pubid/itu/components/series.rb +2 -0
- data/lib/pubid/itu/identifiers/base.rb +11 -18
- data/lib/pubid/itu/identifiers/radio_regulations.rb +27 -0
- data/lib/pubid/itu/identifiers/special_publication.rb +48 -14
- data/lib/pubid/itu/identifiers/standard_serialization.rb +2 -0
- data/lib/pubid/itu/identifiers/supplement.rb +15 -0
- data/lib/pubid/itu/identifiers.rb +1 -0
- data/lib/pubid/itu/parser.rb +108 -22
- data/lib/pubid/itu/urn_generator.rb +9 -2
- data/lib/pubid/jcgm/CLAUDE.md +7 -0
- data/lib/pubid/jcgm/builder.rb +2 -0
- data/lib/pubid/jcgm/components/publisher.rb +2 -0
- data/lib/pubid/jcgm.rb +1 -1
- data/lib/pubid/jis/builder.rb +5 -1
- data/lib/pubid/jis/identifier.rb +6 -18
- data/lib/pubid/jis/identifiers/all_parts.rb +19 -0
- data/lib/pubid/jis/identifiers.rb +1 -0
- data/lib/pubid/jis/renderer.rb +0 -2
- data/lib/pubid/jis/urn_generator.rb +0 -1
- data/lib/pubid/nist/CLAUDE.md +56 -0
- data/lib/pubid/nist/builder.rb +3 -0
- data/lib/pubid/nist/components/edition.rb +2 -0
- data/lib/pubid/nist/components/issue_number.rb +2 -0
- data/lib/pubid/nist/components/part.rb +2 -0
- data/lib/pubid/nist/components/stage.rb +2 -0
- data/lib/pubid/nist/components/supplement.rb +2 -0
- data/lib/pubid/nist/components/translation.rb +2 -0
- data/lib/pubid/nist/components/update.rb +2 -0
- data/lib/pubid/nist/components/version.rb +2 -0
- data/lib/pubid/nist/components/volume.rb +2 -0
- data/lib/pubid/nist/identifiers/base.rb +39 -7
- data/lib/pubid/nist/parser.rb +24 -2
- data/lib/pubid/nist/preprocessor.rb +53 -2
- data/lib/pubid/nist/urn_parser.rb +10 -1
- data/lib/pubid/oasis/CLAUDE.md +19 -0
- data/lib/pubid/oasis/builder.rb +2 -0
- data/lib/pubid/oasis/identifier.rb +20 -1
- data/lib/pubid/ogc/CLAUDE.md +34 -0
- data/lib/pubid/ogc/builder.rb +2 -0
- data/lib/pubid/ogc/identifier.rb +12 -1
- data/lib/pubid/oiml/CLAUDE.md +189 -0
- data/lib/pubid/oiml/builder.rb +20 -0
- data/lib/pubid/oiml/components/code.rb +6 -0
- data/lib/pubid/oiml/identifier.rb +13 -0
- data/lib/pubid/oiml/identifiers/annex.rb +4 -0
- data/lib/pubid/oiml/identifiers/certification_system.rb +34 -0
- data/lib/pubid/oiml/identifiers/code_number.rb +8 -0
- data/lib/pubid/oiml/identifiers/dual_published.rb +174 -0
- data/lib/pubid/oiml/identifiers.rb +2 -0
- data/lib/pubid/oiml/parser.rb +35 -4
- data/lib/pubid/oiml/renderer.rb +23 -1
- data/lib/pubid/oiml/single_identifier.rb +4 -0
- data/lib/pubid/oiml/supplement_identifier.rb +7 -0
- data/lib/pubid/oiml/urn_generator.rb +28 -0
- data/lib/pubid/oiml.rb +6 -1
- data/lib/pubid/omg/CLAUDE.md +15 -0
- data/lib/pubid/omg/builder.rb +2 -0
- data/lib/pubid/omg/identifier.rb +1 -1
- data/lib/pubid/parg/artifact.rb +46 -0
- data/lib/pubid/parg/backend.rb +92 -0
- data/lib/pubid/parg.rb +8 -0
- data/lib/pubid/parser/grammar.rb +23 -0
- data/lib/pubid/pg.rb +8 -0
- data/lib/pubid/plateau/builder.rb +2 -0
- data/lib/pubid/plateau/identifiers/base.rb +4 -0
- data/lib/pubid/plateau/supplement_identifier.rb +14 -2
- data/lib/pubid/plateau/urn_generator.rb +7 -1
- data/lib/pubid/plateau.rb +1 -2
- data/lib/pubid/renderers/human_readable.rb +0 -1
- data/lib/pubid/sae/builder.rb +2 -0
- data/lib/pubid/sae/components/date.rb +2 -0
- data/lib/pubid/sae/components/type.rb +2 -0
- data/lib/pubid/sae/identifiers/base.rb +1 -1
- data/lib/pubid/subset_match.rb +197 -0
- data/lib/pubid/tgpp/CLAUDE.md +43 -0
- data/lib/pubid/tgpp/builder.rb +2 -0
- data/lib/pubid/tgpp/identifier.rb +15 -1
- data/lib/pubid/type_resolver.rb +14 -2
- data/lib/pubid/un/builder.rb +2 -0
- data/lib/pubid/un/identifier.rb +1 -1
- data/lib/pubid/version.rb +1 -1
- data/lib/pubid/w3c/CLAUDE.md +7 -0
- data/lib/pubid/w3c/builder.rb +2 -0
- data/lib/pubid/w3c/identifier.rb +1 -1
- data/lib/pubid/xsf/CLAUDE.md +11 -0
- data/lib/pubid/xsf/builder.rb +2 -0
- data/lib/pubid/xsf/identifier.rb +1 -1
- data/lib/pubid.rb +17 -3
- metadata +78 -2
|
@@ -16,6 +16,8 @@ module Pubid
|
|
|
16
16
|
# +original_separator+ to round-trip dot vs dash notation, and uses
|
|
17
17
|
# +number+ rather than +value+.
|
|
18
18
|
class Code < Lutaml::Model::Serializable
|
|
19
|
+
include ::Pubid::SubsetMatch
|
|
20
|
+
|
|
19
21
|
attribute :prefix, :string # C, P for some identifiers
|
|
20
22
|
attribute :number, :string # Main number (802, 1234, etc.)
|
|
21
23
|
attribute :parts, :string, collection: true # Array of part strings
|
|
@@ -11,6 +11,8 @@ module Pubid
|
|
|
11
11
|
# /D3.4 - version with revision
|
|
12
12
|
# /D7, July 2019 - with date
|
|
13
13
|
class Draft < Lutaml::Model::Serializable
|
|
14
|
+
include ::Pubid::SubsetMatch
|
|
15
|
+
|
|
14
16
|
attribute :version, :string # D5, D3, etc.
|
|
15
17
|
attribute :revision, :string # .4, .2 in D3.4
|
|
16
18
|
attribute :year, :string
|
|
@@ -20,6 +22,11 @@ module Pubid
|
|
|
20
22
|
attribute :comma_before_month, :boolean, default: -> {
|
|
21
23
|
false
|
|
22
24
|
} # Track if comma was in input
|
|
25
|
+
# The joint stage-draft half of the compound form "D5=DDIS.3":
|
|
26
|
+
# the ISO/IEC stage this draft iterates (DIS) and its iteration
|
|
27
|
+
# numeral (3). See docs/IEEE-DRAFT-STAGES.md §1.3.
|
|
28
|
+
attribute :iso_stage, :string
|
|
29
|
+
attribute :iso_iteration, :string
|
|
23
30
|
|
|
24
31
|
# Month name to number mapping
|
|
25
32
|
MONTH_NAMES = {
|
|
@@ -32,7 +39,7 @@ module Pubid
|
|
|
32
39
|
}.freeze
|
|
33
40
|
|
|
34
41
|
def initialize(version: nil, revision: nil, year: nil, month: nil,
|
|
35
|
-
day: nil)
|
|
42
|
+
day: nil, iso_stage: nil, iso_iteration: nil)
|
|
36
43
|
super()
|
|
37
44
|
self.version = version
|
|
38
45
|
self.revision = revision
|
|
@@ -40,6 +47,15 @@ day: nil)
|
|
|
40
47
|
self.original_month = month # Store original format
|
|
41
48
|
self.month = convert_month(month)
|
|
42
49
|
self.day = day
|
|
50
|
+
# The grammar's ordered alternation captures the stage WITH its
|
|
51
|
+
# draft-marker D when the spelling doubles it ("=DDIS"): the
|
|
52
|
+
# marker is notation, the stage is the bare ISO/IEC token.
|
|
53
|
+
if iso_stage.to_s.start_with?("D") &&
|
|
54
|
+
%w[PWI NP WD CD CDV DIS FDIS].include?(iso_stage[1..])
|
|
55
|
+
iso_stage = iso_stage[1..]
|
|
56
|
+
end
|
|
57
|
+
self.iso_stage = iso_stage
|
|
58
|
+
self.iso_iteration = iso_iteration
|
|
43
59
|
end
|
|
44
60
|
|
|
45
61
|
# Month names as an alternation, longest-first so "September" wins over
|
|
@@ -61,12 +77,27 @@ day: nil)
|
|
|
61
77
|
# this method after `from_hash` (a mismatch breaks `to_hash` round-trip).
|
|
62
78
|
# @param value [String, Draft] the value to coerce
|
|
63
79
|
# @return [Draft]
|
|
80
|
+
# The compound stage suffix (docs/IEEE-DRAFT-STAGES.md §1.3):
|
|
81
|
+
# "=DIS.3" is canonical — D (draft) = DIS (the stage), iteration 3.
|
|
82
|
+
# "=DDIS.3", "=DDIS3", "=DDIS-3" (the stage echoed with its own D)
|
|
83
|
+
# are accepted aliases. Captures [stage, iteration].
|
|
84
|
+
COMPOUND_SUFFIX = /=D?(PWI|NP|WD|CDV|FDIS|DIS|CD)(?:[.-]?(\d+))?\z/.freeze
|
|
85
|
+
private_constant :COMPOUND_SUFFIX
|
|
86
|
+
|
|
64
87
|
def self.parse(value)
|
|
65
88
|
return value if value.is_a?(Draft)
|
|
66
89
|
|
|
67
90
|
body = strip_prefix(value.to_s)
|
|
91
|
+
iso_stage = nil
|
|
92
|
+
iso_iteration = nil
|
|
93
|
+
if (m = body.match(COMPOUND_SUFFIX))
|
|
94
|
+
iso_stage = m[1]
|
|
95
|
+
iso_iteration = m[2]
|
|
96
|
+
body = body[0...m.begin(0)]
|
|
97
|
+
end
|
|
68
98
|
version, month, day, year, comma = split_date(body)
|
|
69
|
-
draft = new(version: version, month: month, day: day, year: year
|
|
99
|
+
draft = new(version: version, month: month, day: day, year: year,
|
|
100
|
+
iso_stage: iso_stage, iso_iteration: iso_iteration)
|
|
70
101
|
draft.comma_before_month = comma
|
|
71
102
|
draft
|
|
72
103
|
end
|
|
@@ -110,6 +141,8 @@ day: nil)
|
|
|
110
141
|
|
|
111
142
|
def to_s
|
|
112
143
|
result = "/D#{version}"
|
|
144
|
+
result += "=#{iso_stage}" if iso_stage
|
|
145
|
+
result += ".#{iso_iteration}" if iso_stage && iso_iteration
|
|
113
146
|
result += ".#{revision}" if revision
|
|
114
147
|
|
|
115
148
|
if year
|
|
@@ -19,6 +19,8 @@ module Pubid
|
|
|
19
19
|
# - Approved Draft: Board-approved but unpublished (D7-D9)
|
|
20
20
|
# - Published: Final standards (no P prefix)
|
|
21
21
|
class TypedStage < Lutaml::Model::Serializable
|
|
22
|
+
include ::Pubid::SubsetMatch
|
|
23
|
+
|
|
22
24
|
# All recognized abbreviations for this stage
|
|
23
25
|
# First in array is canonical abbreviation
|
|
24
26
|
attribute :abbr, :string, collection: true
|
|
@@ -201,6 +201,18 @@ module Pubid
|
|
|
201
201
|
hash
|
|
202
202
|
end
|
|
203
203
|
|
|
204
|
+
# Three more IEEE discriminators the default %i[date year edition
|
|
205
|
+
# version] list misses, alongside `edition`/`year`: `revision` (e.g.
|
|
206
|
+
# "2" in "P802.16Rev2"); `reaffirmed` (the "(R2010)" year, read by
|
|
207
|
+
# renderer.rb and urn_generator.rb — two reaffirmations of the same
|
|
208
|
+
# standard failed to collapse under #to_all_parts/#===); and
|
|
209
|
+
# `edition_month`, the month half of "Edition N YYYY-MM"
|
|
210
|
+
# (renderer.rb's `"Edition #{edition} #{year}-#{edition_month}"`),
|
|
211
|
+
# which survived even though its sibling `year` is already stripped.
|
|
212
|
+
def self.all_parts_edition_keys
|
|
213
|
+
super + %i[revision reaffirmed edition_month]
|
|
214
|
+
end
|
|
215
|
+
|
|
204
216
|
# Inverse of the to_hash compaction: expand a scalar `stage` back into the
|
|
205
217
|
# `typed_stage` sub-hash (on a deep copy, recursively) before lutaml
|
|
206
218
|
# deserializes, so nested bases rebuild their component too. `draft` needs
|
|
@@ -351,7 +363,15 @@ module Pubid
|
|
|
351
363
|
def self.parse_single(input)
|
|
352
364
|
# Apply legacy update_codes normalization first, before Parser's extensive preprocessing
|
|
353
365
|
normalized = Core::UpdateCodes.apply(input, :ieee)
|
|
354
|
-
|
|
366
|
+
# UpdateCodes may introduce the "; " double-label separator
|
|
367
|
+
# ("ISO/IEC13210: 1994 (E) ANSI/IEEE Std ..." → the ISO/IEC and
|
|
368
|
+
# IEEE labels of one document), but the dispatch ran on the raw
|
|
369
|
+
# input - re-dispatch so the dual construction sees it.
|
|
370
|
+
if normalized != input && normalized.include?("; ")
|
|
371
|
+
result = PreParser.preprocess(normalized)
|
|
372
|
+
return build_dual(result.parts) if result.dispatch == :dual_semicolon
|
|
373
|
+
end
|
|
374
|
+
parsed = Pubid::Parg::Backend.parse(:ieee, Parser.normalize_input(normalized))
|
|
355
375
|
builder = Builder.new(Identifier)
|
|
356
376
|
# Pass the original input string to builder for context
|
|
357
377
|
builder.original_input = input
|
|
@@ -26,6 +26,15 @@ module Pubid
|
|
|
26
26
|
attribute :iec_year, :string # IEC year like "2013"
|
|
27
27
|
attribute :date_info, :string # Date information like "(10/07)"
|
|
28
28
|
|
|
29
|
+
# `year_sep` only describes how a year is attached. When the reference
|
|
30
|
+
# omits the year, a subset match skips it: its default "-" would
|
|
31
|
+
# otherwise refuse a candidate printed with ":".
|
|
32
|
+
def subset_attribute_match?(name, mine, theirs)
|
|
33
|
+
return true if name == :year_sep && year.nil?
|
|
34
|
+
|
|
35
|
+
super
|
|
36
|
+
end
|
|
37
|
+
|
|
29
38
|
# The printed IEC/IEEE number, rebuilt losslessly from the split
|
|
30
39
|
# columns (the renderer/urn read this). Not stored — number/parts/
|
|
31
40
|
# separators/year fully describe it, so the verbatim string never
|
|
@@ -42,6 +42,8 @@ module Pubid
|
|
|
42
42
|
attribute :year, :string
|
|
43
43
|
attribute :iso_stage, :string # For ISO stage if present
|
|
44
44
|
attribute :ieee_draft, :string # For IEEE P/D notation if present
|
|
45
|
+
attribute :parenthetical_content, :string # e.g. the "(E)" edition
|
|
46
|
+
# marker of an ISO/IEC label
|
|
45
47
|
|
|
46
48
|
# Accepts keyword args or a single positional hash (the base
|
|
47
49
|
# #exclude/matching rebuild passes the latter) — see
|
|
@@ -77,6 +79,11 @@ module Pubid
|
|
|
77
79
|
# Canonical format based on lead party
|
|
78
80
|
# @return [Symbol] :ieee or :iso
|
|
79
81
|
def canonical_format
|
|
82
|
+
# A stage-tracked D= designator is IEEE draft notation — its
|
|
83
|
+
# canonical face is the designator spelling (§1.3 spelling 7:
|
|
84
|
+
# "JOINT PNUMBER/D=<STAGE>[:year]"), whatever the lead party.
|
|
85
|
+
return :ieee if ieee_draft.to_s.start_with?("D=")
|
|
86
|
+
|
|
80
87
|
case lead_party
|
|
81
88
|
when "IEEE", "AIEE"
|
|
82
89
|
:ieee
|
|
@@ -128,24 +135,44 @@ module Pubid
|
|
|
128
135
|
# Publishers (slash-separated)
|
|
129
136
|
parts << publishers.join("/") if publishers && !publishers.empty?
|
|
130
137
|
|
|
131
|
-
#
|
|
132
|
-
#
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
138
|
+
# The stage word is the ISO format's own position convention —
|
|
139
|
+
# it prints whenever the identifier carries one, regardless of
|
|
140
|
+
# lead party (the format face decides, not the arrangement). A
|
|
141
|
+
# stage-tracked D= designator decomposes into its stage word
|
|
142
|
+
# and date ("D=CD.2-2020" → "CD2", 2020); the iteration glues
|
|
143
|
+
# onto the word only for the stages whose printed ISO spellings
|
|
144
|
+
# carry it (CD2, DIS2 — the grammar's multi-digit families);
|
|
145
|
+
# the P project stage is IEEE convention and never prints here.
|
|
146
|
+
# The printed word is always the bare stage ("CD4" prints "CD",
|
|
147
|
+
# "DIS3" prints "DIS" — every iso_stage_spellings_spec
|
|
148
|
+
# expectation); the iteration is draft machinery, not ISO-face
|
|
149
|
+
# identity.
|
|
150
|
+
stage_word = iso_stage.to_s.sub(/\A([A-Z]+?)\d+\z/, '\1')
|
|
151
|
+
stage_word = nil if stage_word.empty?
|
|
152
|
+
draft_year = nil
|
|
153
|
+
if stage_word.nil? &&
|
|
154
|
+
ieee_draft.to_s.match(/\AD=([A-Z]+)(?:\.(\d+[a-z]?))?(?:[-:](\d{4}))?\z/)
|
|
155
|
+
stage_word = Regexp.last_match(1)
|
|
156
|
+
draft_year = Regexp.last_match(3)
|
|
139
157
|
end
|
|
158
|
+
parts << stage_word if stage_word
|
|
140
159
|
|
|
141
|
-
#
|
|
142
|
-
|
|
160
|
+
# The P project marker is identity-bearing and prints on both
|
|
161
|
+
# faces (the standing trademark_leaf_to_s_spec contract:
|
|
162
|
+
# "ISO/IEC/IEEE P26511:2018").
|
|
163
|
+
code_str = code.to_s
|
|
143
164
|
code_str += mark unless code_str.empty?
|
|
144
165
|
parts << code_str if code_str && !code_str.empty?
|
|
145
166
|
|
|
146
|
-
# Join with space and add year with colon
|
|
167
|
+
# Join with space and add year with colon (the ISO position
|
|
168
|
+
# convention; a decomposed D= date rides here as the year).
|
|
147
169
|
result = parts.join(" ")
|
|
148
|
-
result += ":#{year}" if year
|
|
170
|
+
result += ":#{year || draft_year}" if year || draft_year
|
|
171
|
+
# Only the language/edition marker ("(E)", "(E/F)") prints; a
|
|
172
|
+
# trailing relationship narrative is metadata, not identity.
|
|
173
|
+
if parenthetical_content&.match?(%r{\A[A-Z](?:\s*[/&]\s*[A-Z])*\z})
|
|
174
|
+
result += " (#{parenthetical_content})"
|
|
175
|
+
end
|
|
149
176
|
|
|
150
177
|
result
|
|
151
178
|
end
|
|
@@ -159,29 +186,45 @@ module Pubid
|
|
|
159
186
|
# Publishers (slash-separated)
|
|
160
187
|
parts << publishers.join("/") if publishers && !publishers.empty?
|
|
161
188
|
|
|
162
|
-
# Build code part
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
# Add P prefix for projects (IEEE format always shows P for drafts)
|
|
166
|
-
if typed_stage&.project_status || type == "P"
|
|
167
|
-
code_str = "P#{code_str}"
|
|
168
|
-
end
|
|
189
|
+
# Build code part — the P-state prints as spelled (P = project
|
|
190
|
+
# draft; no P = standard). Never added or stripped.
|
|
191
|
+
code_str = code.to_s
|
|
169
192
|
|
|
170
193
|
# Mark after the number, before the draft and the year
|
|
171
194
|
code_str += mark unless code_str.empty?
|
|
172
195
|
|
|
173
|
-
# Add IEEE draft notation if available (e.g., /D8)
|
|
174
|
-
|
|
196
|
+
# Add IEEE draft notation if available (e.g., /D8). An ISO stage
|
|
197
|
+
# word renders in IEEE's stage-tracked position as the ordinal-less
|
|
198
|
+
# stage draft (docs/IEEE-DRAFT-STAGES.md §1.3, spelling 7):
|
|
199
|
+
# "IEEE/ISO/IEC CD P42010:2020" → "IEEE/ISO/IEC P42010/D=CD-2020".
|
|
200
|
+
# The iso_stage branch is checked FIRST — the typed_stage registry
|
|
201
|
+
# lookup for a stage word answers a draft-equivalent ordinal ("D2"),
|
|
202
|
+
# which is not the canonical stage-tracked spelling.
|
|
203
|
+
if ieee_draft.to_s.start_with?("D=") && year
|
|
204
|
+
# The ordinal-less stage draft's canonical face (the
|
|
205
|
+
# UpdateCodes rewrite): the publication year colon-joins the
|
|
206
|
+
# code and the designator trails — "P16326:2017/D=WD.5".
|
|
207
|
+
code_str += ":#{year}"
|
|
208
|
+
code_str += "/#{ieee_draft}"
|
|
209
|
+
@designator_carries_year = true
|
|
210
|
+
elsif ieee_draft
|
|
175
211
|
code_str += "/#{ieee_draft}"
|
|
212
|
+
elsif iso_stage
|
|
213
|
+
# The ordinal-less stage draft: an iteration glued onto the
|
|
214
|
+
# printed word ("CD2") renders in the doctrine's ".iter" slot
|
|
215
|
+
# ("D=CD.2" — docs/IEEE-DRAFT-STAGES.md §1.3).
|
|
216
|
+
stage = iso_stage.match(/\A([A-Z]+?)(\d+)\z/)
|
|
217
|
+
code_str += stage ? "/D=#{stage[1]}.#{stage[2]}" : "/D=#{iso_stage}"
|
|
176
218
|
elsif typed_stage&.ieee_draft_equivalent
|
|
177
219
|
code_str += "/#{typed_stage.ieee_draft_equivalent}"
|
|
178
220
|
end
|
|
179
221
|
|
|
180
222
|
parts << code_str if code_str && !code_str.empty?
|
|
181
223
|
|
|
182
|
-
# Join with space and add year with dash
|
|
224
|
+
# Join with space and add year with dash — unless the D=
|
|
225
|
+
# designator face already carried it above.
|
|
183
226
|
result = parts.join(" ")
|
|
184
|
-
result += "-#{year}" if year
|
|
227
|
+
result += "-#{year}" if year && !@designator_carries_year
|
|
185
228
|
|
|
186
229
|
result
|
|
187
230
|
end
|
|
@@ -33,10 +33,17 @@ module Pubid
|
|
|
33
33
|
# object. The "P" is reflected in the typed_stage, not in the Code
|
|
34
34
|
# component itself. Accepts keyword args or a single positional hash (the
|
|
35
35
|
# base #exclude/matching rebuild passes the latter).
|
|
36
|
+
attribute :project_marker, :boolean, default: -> { false }
|
|
37
|
+
|
|
36
38
|
def initialize(args = {}, **kwargs)
|
|
37
39
|
args = kwargs.empty? ? args.dup : args.merge(kwargs)
|
|
38
|
-
# If code is provided with "P" prefix (e.g., "P1234"), strip it
|
|
40
|
+
# If code is provided with "P" prefix (e.g., "P1234"), strip it.
|
|
41
|
+
# P = project (the document is a draft): the marker is
|
|
42
|
+
# identity-bearing, so its presence is remembered for the render —
|
|
43
|
+
# stripping the letter must not strip the fact (docs/
|
|
44
|
+
# IEEE-DRAFT-STAGES.md §1.1).
|
|
39
45
|
if args[:code].is_a?(String) && args[:code].start_with?("P")
|
|
46
|
+
args[:project_marker] = true unless args.key?(:project_marker)
|
|
40
47
|
args[:code] = args[:code][1..] # Strip leading "P"
|
|
41
48
|
end
|
|
42
49
|
|
data/lib/pubid/ieee/parser.rb
CHANGED
|
@@ -269,6 +269,10 @@ module Pubid
|
|
|
269
269
|
rule(:draft_date) do
|
|
270
270
|
# Enhanced to handle: ", Sept 2008" or " Sept 2008" or ", Month Year"
|
|
271
271
|
((comma | space) >> month_name.as(:month) >> space >> year_digits.as(:year)) |
|
|
272
|
+
# Space-separated bare year after the draft designator
|
|
273
|
+
# ("IEEE Draft Std P14764/D1 2004, Nov 2004" - the "D1 2004" draft
|
|
274
|
+
# carries its own year, with the print date still trailing).
|
|
275
|
+
(space >> year_digits.as(:year)) |
|
|
272
276
|
# Numeric-month form ", 05 2007" / " 05 2007" — no text month name. The
|
|
273
277
|
# year separator may be a dash: preprocessing (parser.rb ~1278) rewrites
|
|
274
278
|
# a trailing " <digits> <year>" to "<digits>-<year>", so "05 2007"
|
|
@@ -302,6 +306,15 @@ module Pubid
|
|
|
302
306
|
rule(:draft) do
|
|
303
307
|
(draft_prefix >> draft_version.repeat(1, 2) >>
|
|
304
308
|
(dot >> digits.as(:revision)).maybe >>
|
|
309
|
+
# The compound both-systems form (docs/IEEE-DRAFT-STAGES.md
|
|
310
|
+
# §1.3): "=DDIS.3" - IEEE draft ordinal = draft of the ISO/IEC
|
|
311
|
+
# stage, with its iteration. The glued "=DDIS3" / "=DDIS-3"
|
|
312
|
+
# spellings are accepted aliases of "=DDIS.3".
|
|
313
|
+
(str("=") >> (str("D") >> (str("FDIS") | str("CDV") | str("PWI") |
|
|
314
|
+
str("DIS") | str("WD") | str("NP") | str("CD")) |
|
|
315
|
+
(str("FDIS") | str("CDV") | str("PWI") | str("DIS") | str("WD") |
|
|
316
|
+
str("NP") | str("CD"))).as(:draft_iso_stage) >>
|
|
317
|
+
(dot | dash).maybe >> digits.as(:draft_iso_iteration).maybe).maybe >>
|
|
305
318
|
draft_date.maybe).as(:draft)
|
|
306
319
|
end
|
|
307
320
|
|
|
@@ -532,7 +545,9 @@ module Pubid
|
|
|
532
545
|
|
|
533
546
|
# Additional parameters (inside parentheses)
|
|
534
547
|
rule(:additional_parameters) do
|
|
535
|
-
(space.maybe >> str("(") >> #
|
|
548
|
+
(space.maybe >> str("(") >> space.maybe >> # Space before/after '(' optional
|
|
549
|
+
# ("( Revision of …)" - a crawl space inside the paren must not push
|
|
550
|
+
# the narrative to the catch-all and into the render).
|
|
536
551
|
(reaffirmed |
|
|
537
552
|
# Handle "Revision of IEEE Std ..." with optional space after Std
|
|
538
553
|
(str("Revision of IEEE Std ") >> space.maybe >> match("[^)]").repeat(1).as(:revision_of)) |
|
|
@@ -580,17 +595,42 @@ module Pubid
|
|
|
580
595
|
# ISO/IEC/IEEE P26511/D8-2018 or ISO/IEEE P1003.1-2008 or IEC/IEEE P62582-1-2011
|
|
581
596
|
# ALSO handle: IEC/IEEE P60780-323, CDV1 2014 (comma before stage code)
|
|
582
597
|
# ALSO handle: IEEE/CSA P844.1/293.1/D2 (CSA dual numbering)
|
|
583
|
-
|
|
598
|
+
# ALSO handle: IEEE/ISO/IEC P42010/D=CD-2020 — the printed publisher
|
|
599
|
+
# order is the organization's perspective (pubid#469) and parses as
|
|
600
|
+
# printed; it is no longer rewritten to ISO-first.
|
|
601
|
+
(str("ISO/IEC/IEEE") | str("IEEE/ISO/IEC") | str("ISO/IEEE") | str("IEC/IEEE") | str("IEEE/CSA")).as(:joint_publishers) >>
|
|
584
602
|
space >>
|
|
585
|
-
|
|
603
|
+
# P = project (the document is a draft): identity-bearing, so it
|
|
604
|
+
# is captured and preserved, never silently consumed.
|
|
605
|
+
str("P").as(:project_marker) >>
|
|
586
606
|
digits.as(:number) >>
|
|
587
607
|
((dot | dash) >> digits.as(:part)).maybe >> # Optional part like .1 or -1
|
|
588
608
|
# CSA dual numbering: /293.1 (second number)
|
|
589
609
|
(slash >> digits >> (dot >> digits).maybe >> (dash >> digits.as(:draft_version)).maybe).maybe >>
|
|
590
610
|
(
|
|
591
|
-
# Variant
|
|
592
|
-
|
|
593
|
-
#
|
|
611
|
+
# Variant 1b: the ordinal-less stage draft "D=CDV-2020" -
|
|
612
|
+
# D (draft) = CDV (the IEC stage it drafts). The year rides in
|
|
613
|
+
# the draft clause (a distinct key, so the builder keeps the
|
|
614
|
+
# date inside the designator). The year follows IEEE format:
|
|
615
|
+
# dash-joined ("D=CD-2020", the ruled canonical); the colon
|
|
616
|
+
# spelling ("D=CDV:2020") stays accepted as the alias it was
|
|
617
|
+
# frozen with. A dash-year is guarded to 19xx/20xx so a
|
|
618
|
+
# YYMM monthcode tail can never be read as a year.
|
|
619
|
+
(slash >> str("D") >> str("=") >>
|
|
620
|
+
(str("CDV") | str("FDIS") | str("PWI") | str("WD") |
|
|
621
|
+
str("NP") | str("DIS") | str("CD")).as(:draft_iso_stage) >>
|
|
622
|
+
((str(":") | str("-")) >>
|
|
623
|
+
((str("19") | str("20")) >> digit >> digit).as(:draft_stage_year)).maybe) |
|
|
624
|
+
# Variant 1: /D8 notation (original), with the compound
|
|
625
|
+
# both-systems suffix "=DDIS.3" (docs/IEEE-DRAFT-STAGES.md §1.3)
|
|
626
|
+
(slash >> str("D") >> digits.as(:draft_version) >>
|
|
627
|
+
(str("=") >> (str("D") >> (str("FDIS") | str("CDV") | str("PWI") |
|
|
628
|
+
str("DIS") | str("WD") | str("NP") | str("CD")) |
|
|
629
|
+
(str("FDIS") | str("CDV") | str("PWI") | str("DIS") | str("WD") |
|
|
630
|
+
str("NP") | str("CD"))).as(:draft_iso_stage) >>
|
|
631
|
+
(dot | dash).maybe >> digits.as(:draft_iso_iteration).maybe).maybe) |
|
|
632
|
+
# Variant 2: , CDV1 notation (comma before stage code) —
|
|
633
|
+
# the stage draft of the named ISO/IEC stage, its iteration
|
|
594
634
|
(comma >> (str("CDV") | str("FDIS") | str("CD") | str("DIS")).as(:iec_stage) >> digits.maybe.as(:stage_iteration))
|
|
595
635
|
).maybe >>
|
|
596
636
|
# Optional edition, from relaton's "/E-<n>" suffix normalized to
|
|
@@ -636,18 +676,30 @@ module Pubid
|
|
|
636
676
|
str("").as(:iso_published) >> space.maybe)) |
|
|
637
677
|
(staged_only.as(:joint_publishers) >> space >>
|
|
638
678
|
iso_stage >> std_noise >> space)) >>
|
|
639
|
-
str("P").maybe >> #
|
|
679
|
+
str("P").as(:project_marker).maybe >> # project marker (P =
|
|
680
|
+
# project/draft; its
|
|
681
|
+
# presence is identity)
|
|
640
682
|
digits.as(:number) >>
|
|
641
|
-
# part must not swallow the trailing year (year_digits.absent?)
|
|
642
|
-
|
|
683
|
+
# part must not swallow the trailing year (year_digits.absent?). A
|
|
684
|
+
# DASH-joined part is tagged (:part_dash) - the catalogue-printed
|
|
685
|
+
# joint form spells the part with a dash ("21451-7") where the ISO
|
|
686
|
+
# form uses the dot.
|
|
687
|
+
((dot >> year_digits.absent? >> digits.as(:part)) |
|
|
688
|
+
(dash >> str("").as(:part_dash) >> year_digits.absent? >>
|
|
689
|
+
digits.as(:part))).maybe >>
|
|
643
690
|
(
|
|
644
691
|
(str(":") >> year_digits.as(:year)) |
|
|
692
|
+
# The dash-year (and ", Month YYYY" text date below) spellings are
|
|
693
|
+
# the catalogue-PRINTED joint form; tag them (:printed_form) so the
|
|
694
|
+
# builder routes to a Standard instead of the ISO joint reference.
|
|
645
695
|
(dash >> year_digits.as(:year) >>
|
|
646
|
-
(dash >> month_numeric.as(:month)).maybe
|
|
696
|
+
(dash >> month_numeric.as(:month)).maybe >>
|
|
697
|
+
str("").as(:printed_dash_year)) |
|
|
647
698
|
# Trailing text date ", April 2015" / " April 2015" (build_joint_development
|
|
648
699
|
# already reads :month/:year). No :year collision — the iso rule has no
|
|
649
700
|
# other :year capture (edition uses :edition_year).
|
|
650
|
-
((comma | space) >> month_name.as(:month) >> space >>
|
|
701
|
+
((comma | space) >> month_name.as(:month) >> space >>
|
|
702
|
+
year_digits.as(:year) >> str("").as(:printed_month_year))
|
|
651
703
|
).maybe >>
|
|
652
704
|
# Optional /D<draft> tail. normalize_relaton_suffixes repositions the
|
|
653
705
|
# historical "…/D-3-2017" onto the number as "…-2017/D3", so by the
|
|
@@ -658,11 +710,26 @@ module Pubid
|
|
|
658
710
|
# keys (:draft_month/:draft_year), because a plain :month/:year
|
|
659
711
|
# here collides with the date clause above and parslet drops the
|
|
660
712
|
# subtree with a "Duplicate subtrees" warning.
|
|
713
|
+
# The ISO/IEC edition marker may sit between the year and an
|
|
714
|
+
# amendment/draft tail: "8802.11:2012 (E)/Amd 1-2014". A distinct
|
|
715
|
+
# key - a second :parameters capture here collides with the
|
|
716
|
+
# trailing parenthetical slot (parslet drops duplicate subtrees).
|
|
717
|
+
(space.maybe >> str("(") >>
|
|
718
|
+
match("[^)]").repeat(1).as(:edition_marker) >> str(")")).maybe >>
|
|
719
|
+
# The stage-draft clause of the ISO-led print: "/D=WD.5" -
|
|
720
|
+
# D (draft) = the ISO/IEC stage it drafts, with its iteration
|
|
721
|
+
# (docs/IEEE-DRAFT-STAGES.md §1.2).
|
|
722
|
+
((slash >> str("D") >> str("=") >>
|
|
723
|
+
(str("FDIS") | str("FCD") | str("CDV") |
|
|
724
|
+
(str("DIS") >> digit.maybe) |
|
|
725
|
+
(str("CD") >> digit.maybe) |
|
|
726
|
+
str("WD") | str("PWI") | str("NP")).as(:draft_iso_stage) >>
|
|
727
|
+
(dot >> (digits >> match("[A-Za-z]").repeat(0, 1)).as(:draft_iso_iteration)).maybe) |
|
|
661
728
|
(slash >> str("D") >> dash.maybe >>
|
|
662
729
|
match('[0-9.]').repeat(1).as(:draft_version) >>
|
|
663
730
|
(((comma | space) >> month_name.as(:draft_month) >> space >>
|
|
664
731
|
year_digits.as(:draft_year)) |
|
|
665
|
-
(comma >> year_digits.as(:draft_year))).maybe).maybe >>
|
|
732
|
+
(comma >> year_digits.as(:draft_year))).maybe).maybe).maybe >>
|
|
666
733
|
# Optional amendment tail (pubid#317:
|
|
667
734
|
# "8802-11:2012/Amd.1:2014(E)") - the flat tree keys reuse
|
|
668
735
|
# build_flat_amendment.
|
|
@@ -678,7 +745,6 @@ module Pubid
|
|
|
678
745
|
# The crawl sometimes spaces it ("…(E), January 2017" family,
|
|
679
746
|
# pubid#216), and a relationship parenthetical may follow
|
|
680
747
|
# ("…CD2 P15288-2013-09 (Revision of …)").
|
|
681
|
-
space.maybe >> (str("(E)") | str("(F)")).maybe >>
|
|
682
748
|
parenthetical.maybe
|
|
683
749
|
end
|
|
684
750
|
|
|
@@ -692,6 +758,28 @@ module Pubid
|
|
|
692
758
|
# the trailing `.FDIS` is the ISO stage, NOT a second part. Routes through
|
|
693
759
|
# the same build_joint_development (via :joint_publishers/:iso_stage), so the
|
|
694
760
|
# stage is modeled correctly and the numeric part stays separate.
|
|
761
|
+
# The stage-less ISO/IEC label with a colon year and the ISO/IEC
|
|
762
|
+
# edition marker: "ISO/IEC 13210:1994 (E)" - the ISO/IEC portion of a
|
|
763
|
+
# double-labeled standard. The (E) parenthetical is REQUIRED: without
|
|
764
|
+
# it this spelling is the ISO flavor's own form and must not be
|
|
765
|
+
# stolen. Routes through build_joint_development like every ISO-led
|
|
766
|
+
# joint reference.
|
|
767
|
+
rule(:joint_development_iso_iec_edition) do
|
|
768
|
+
str("ISO/IEC").as(:joint_publishers) >> space >>
|
|
769
|
+
str("").as(:iso_published) >>
|
|
770
|
+
str("P").as(:project_marker).maybe >>
|
|
771
|
+
digits.as(:number) >>
|
|
772
|
+
# The part may be dot- or dash-joined ("8802-9"); a dash-year
|
|
773
|
+
# ("1234-2012") is not a part.
|
|
774
|
+
# A distinct key: the iso-format route's :part_dash prints as a
|
|
775
|
+
# dot in the joint code (the "P24748.2:2018" convention); only
|
|
776
|
+
# the ISO/IEC LABEL keeps its printed dash.
|
|
777
|
+
((dot | (dash >> str("").as(:iec_label_dash) >> year_digits.absent?)) >>
|
|
778
|
+
digits.as(:part)).maybe >>
|
|
779
|
+
(str(":") >> space.maybe >> year_digits.as(:year)) >>
|
|
780
|
+
space.maybe >> parenthetical
|
|
781
|
+
end
|
|
782
|
+
|
|
695
783
|
rule(:joint_development_embedded_stage) do
|
|
696
784
|
# publisher set mirrors joint_development_iso_format (incl. bare IEEE);
|
|
697
785
|
# longest token first.
|
|
@@ -699,7 +787,9 @@ module Pubid
|
|
|
699
787
|
str("ISO/IEEE") | str("IEC/IEEE") | str("IEEE/IEC") | str("ISO/IEC") |
|
|
700
788
|
str("IEEE")).as(:joint_publishers) >>
|
|
701
789
|
space >>
|
|
702
|
-
str("P").maybe >> #
|
|
790
|
+
str("P").as(:project_marker).maybe >> # project marker (P =
|
|
791
|
+
# project/draft; its
|
|
792
|
+
# presence is identity)
|
|
703
793
|
digits.as(:number) >>
|
|
704
794
|
# optional numeric part (dot or dash); must not swallow a year
|
|
705
795
|
((dot | dash) >> year_digits.absent? >> digits.as(:part)).maybe >>
|
|
@@ -814,7 +904,17 @@ module Pubid
|
|
|
814
904
|
((space >> month_name.as(:trailing_month) >> space >> year_digits.as(:trailing_year)) |
|
|
815
905
|
(space >> month_numeric.as(:trailing_month) >> (space | dash) >> year_digits.as(:trailing_year))).maybe >>
|
|
816
906
|
draft.maybe >>
|
|
907
|
+
# A print date may trail a draft that carries its own date
|
|
908
|
+
# ("IEEE Unapproved Draft 24765/D1 2009, Oct 2009" - the draft's
|
|
909
|
+
# year is "2009", the print date is ", Oct 2009").
|
|
910
|
+
(comma >> space? >> month_name.as(:trailing_month) >> space >>
|
|
911
|
+
year_digits.as(:trailing_year)).maybe >>
|
|
817
912
|
revision_suffix.maybe >>
|
|
913
|
+
# …and the print date may also trail the repositioned revision
|
|
914
|
+
# ("IEEE Unapproved Draft P802.16Rev2/D9a, March 2009" reaches the
|
|
915
|
+
# grammar as "…/D9a/R-2, March 2009" via normalize_revision_notation).
|
|
916
|
+
(comma >> space? >> month_name.as(:trailing_month) >> space >>
|
|
917
|
+
year_digits.as(:trailing_year)).maybe >>
|
|
818
918
|
# Trailing corrigendum after the draft ("…/D2.0/Cor. 1", or
|
|
819
919
|
# "…/D1.0, Dec 2007/Cor. 1" where the draft's own draft_date consumes
|
|
820
920
|
# the date, leaving "/Cor. N"). The flat corrigendum+draft tree (no
|
|
@@ -899,10 +999,17 @@ module Pubid
|
|
|
899
999
|
# Draft NESC pattern
|
|
900
1000
|
(str("Draft") >> space >> (str("NESC") | str("National Electrical Safety Code"))) |
|
|
901
1001
|
# Name-first pattern (NEW)
|
|
902
|
-
(str("National Electrical Safety Code") >> str(",") >> space >> str("C2-"))
|
|
1002
|
+
(str("National Electrical Safety Code") >> str(",") >> space >> str("C2-")) |
|
|
1003
|
+
# Catalogue form: "IEEE Std YYYY NESC ..." / "IEEE Std YYYY National
|
|
1004
|
+
# Electrical Safety Code" - the prefix is consumed here (the NESC
|
|
1005
|
+
# renderer prepends "IEEE Std" itself) but must not fall through to
|
|
1006
|
+
# the generic standard grammar, which would read YYYY as a number.
|
|
1007
|
+
(str("IEEE") >> space >> str("Std") >> space >> year_digits >> space >>
|
|
1008
|
+
(str("NESC") | str("National Electrical Safety Code")))
|
|
903
1009
|
).present? >>
|
|
904
1010
|
# Delegate to NESC parser if pattern detected
|
|
905
|
-
|
|
1011
|
+
((str("IEEE") >> space >> str("Std") >> space).maybe >>
|
|
1012
|
+
Nesc::Parser.new.nesc_identifier).as(:nesc)
|
|
906
1013
|
end
|
|
907
1014
|
|
|
908
1015
|
# Draft notation for PSI (e.g., /D2, /D3, rawbib's /D-2)
|
|
@@ -1056,13 +1163,13 @@ module Pubid
|
|
|
1056
1163
|
str("CSA") >> space >>
|
|
1057
1164
|
# CSA number formats (various patterns observed)
|
|
1058
1165
|
(
|
|
1059
|
-
# Format 1: C22.2 No. 293.1-17 (with NO
|
|
1060
|
-
(str("C") >> digit.repeat(2) >> dot >> digit >> space >> str("No") >> dot >> space >>
|
|
1166
|
+
# Format 1: C22.2 No. 293.1-17 (with NO., either case)
|
|
1167
|
+
(str("C") >> digit.repeat(2) >> dot >> digit >> space >> (str("No") | str("NO")) >> dot >> space >>
|
|
1061
1168
|
match("[0-9.]").repeat(1) >> (dash | str(":")) >> digit.repeat(2)) |
|
|
1062
1169
|
# Format 2: C293.2-17 (without NO., dash year)
|
|
1063
1170
|
(str("C") >> match("[0-9.]").repeat(1) >> dash >> digit.repeat(2)) |
|
|
1064
|
-
# Format 3: C22.2 No. 293.3:19 (with NO., colon year)
|
|
1065
|
-
(str("C") >> digit.repeat(2) >> dot >> digit >> space >> str("No") >> dot >> space >>
|
|
1171
|
+
# Format 3: C22.2 No. 293.3:19 (with NO., either case, colon year)
|
|
1172
|
+
(str("C") >> digit.repeat(2) >> dot >> digit >> space >> (str("No") | str("NO")) >> dot >> space >>
|
|
1066
1173
|
match("[0-9.]").repeat(1) >> str(":") >> digit.repeat(2)) |
|
|
1067
1174
|
# Format 4: C293.4:19 (without NO., colon year)
|
|
1068
1175
|
(str("C") >> match("[0-9.]").repeat(1) >> str(":") >> digit.repeat(2))
|
|
@@ -1085,6 +1192,8 @@ module Pubid
|
|
|
1085
1192
|
conformance_identifier | # NEW: Try conformance identifier before generic patterns
|
|
1086
1193
|
joint_development_ieee_format |
|
|
1087
1194
|
joint_development_iso_format |
|
|
1195
|
+
joint_development_iso_iec_edition | # stage-less ISO/IEC label with (E) - double-label portion
|
|
1196
|
+
|
|
1088
1197
|
joint_development_embedded_stage | # stage-LAST embedded form (before generic)
|
|
1089
1198
|
iec_ieee_copublished |
|
|
1090
1199
|
number_first_identifier |
|
|
@@ -1110,6 +1219,15 @@ module Pubid
|
|
|
1110
1219
|
# never collides with the base -YYYY identity year (see
|
|
1111
1220
|
# ieee_p_identifier). The builder promotes it only when no base year.
|
|
1112
1221
|
trailing_month_year.maybe >>
|
|
1222
|
+
# The ASHRAE joint suffix may also trail a draft+date
|
|
1223
|
+
# ("IEEE P1635/D13, December, 2017/ASHRAE Guideline 21"), so a
|
|
1224
|
+
# second slot catches it after the date.
|
|
1225
|
+
ashrae_copub.maybe >>
|
|
1226
|
+
# A bracketed narrative may sit between the base and a trailing
|
|
1227
|
+
# corrigendum: "IEEE Std 671-1985 [Corrigendum to IEEE Std 671-1985
|
|
1228
|
+
# (Reaff 2008)]/Cor. 1-2010" captures the bracket as the base's
|
|
1229
|
+
# nickname before the wrapper is parsed.
|
|
1230
|
+
book_nickname.maybe >>
|
|
1113
1231
|
# Trailing corrigendum after the draft+date ("IEEE Approved P1015/D1,
|
|
1114
1232
|
# Jan 2007/Cor. 1"): the generic bucket is the only path a status-word
|
|
1115
1233
|
# form reaches. Routes via build_flat_corrigendum (disjoint from the
|
|
@@ -1333,9 +1451,12 @@ module Pubid
|
|
|
1333
1451
|
# Slash-stage carrying a dash-date ("…P15288/CD2-2013-09 …" — the
|
|
1334
1452
|
# dash-year tail is what the joint grammar reads after the number, so
|
|
1335
1453
|
# this cannot steal the plain "/FDIS, June 2021" spellings
|
|
1336
|
-
# ieee_p_identifier finishes): → "…CD2 P15288-2013-09 …"
|
|
1454
|
+
# ieee_p_identifier finishes): → "…CD2 P15288-2013-09 …". The date
|
|
1455
|
+
# must be a plausible year — a 4-digit monthcode (YYMM, e.g.
|
|
1456
|
+
# "…P24748-4/DIS-1404" = April 2014) is a DRAFT designator, not a
|
|
1457
|
+
# dash-date, and rewriting it onto the number breaks the parse.
|
|
1337
1458
|
cleaned = cleaned.sub(
|
|
1338
|
-
%r{\A#{pubs}#{num}/ ?#{stage}(
|
|
1459
|
+
%r{\A#{pubs}#{num}/ ?#{stage}(-(?:19|20)\d\d(?:-\d\d)?)},
|
|
1339
1460
|
'\1\3 \2\4',
|
|
1340
1461
|
)
|
|
1341
1462
|
|
|
@@ -1355,7 +1476,10 @@ module Pubid
|
|
|
1355
1476
|
cleaned
|
|
1356
1477
|
end
|
|
1357
1478
|
|
|
1358
|
-
|
|
1479
|
+
# Pre-parse ingestion normalizations (R2): every parse path —
|
|
1480
|
+
# parslet and PG artifact alike — feeds the grammar the same
|
|
1481
|
+
# normalized string.
|
|
1482
|
+
def self.normalize_input(string)
|
|
1359
1483
|
# Strip .pdf extension if present (Pattern 3: File Extensions)
|
|
1360
1484
|
cleaned = string.sub(/\.pdf$/i, "")
|
|
1361
1485
|
|
|
@@ -1709,11 +1833,10 @@ module Pubid
|
|
|
1709
1833
|
# Fix 2H: "IEC XXXX First edition YYYY-MM; IEEE NNNN" -> normalize semicolon
|
|
1710
1834
|
# Already handled by earlier semicolon normalization
|
|
1711
1835
|
|
|
1712
|
-
# Fix 2I: "IEEE/ISO/IEC PXXX
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
'IEC/ISO/IEEE \1')
|
|
1836
|
+
# (Fix 2I removed: "IEEE/ISO/IEC PXXX/…" is no longer rewritten to
|
|
1837
|
+
# ISO-first — the printed publisher order is the organization's
|
|
1838
|
+
# perspective (pubid#469) and the joint P-form rule parses it as
|
|
1839
|
+
# printed.)
|
|
1717
1840
|
|
|
1718
1841
|
# Fix 2J: "IEEE/IEC PXXX D5" -> normalize space to slash before D
|
|
1719
1842
|
cleaned = cleaned.gsub(/^(IEEE\/IEC P[\w.-]+)\s+D(\d)/, '\1/D\2')
|
|
@@ -1812,7 +1935,11 @@ module Pubid
|
|
|
1812
1935
|
# Fix 2AF: "IEEE Std 1003.1/2003.l/lNT" -> fix typos
|
|
1813
1936
|
# .l -> .1 and lNT -> INT handled by existing fixes
|
|
1814
1937
|
|
|
1815
|
-
|
|
1938
|
+
cleaned
|
|
1939
|
+
end
|
|
1940
|
+
|
|
1941
|
+
def self.parse(string)
|
|
1942
|
+
new.parse(normalize_input(string))
|
|
1816
1943
|
end
|
|
1817
1944
|
end
|
|
1818
1945
|
end
|