@pubid/pubid 0.1.3 → 0.1.5
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.
- package/artifact/corpus.json.gz +0 -0
- package/dist/conformance/cli.js +5 -1
- package/dist/flavors/amca/grammar.d.ts +4 -0
- package/dist/flavors/amca/grammar.js +87 -0
- package/dist/flavors/amca/index.d.ts +4 -0
- package/dist/flavors/amca/index.js +76 -0
- package/dist/flavors/amca/model.d.ts +29 -0
- package/dist/flavors/amca/model.js +146 -0
- package/dist/flavors/ansi/index.d.ts +24 -0
- package/dist/flavors/ansi/index.js +147 -0
- package/dist/flavors/api/grammar.d.ts +4 -0
- package/dist/flavors/api/grammar.js +79 -0
- package/dist/flavors/api/index.d.ts +4 -0
- package/dist/flavors/api/index.js +71 -0
- package/dist/flavors/api/model.d.ts +27 -0
- package/dist/flavors/api/model.js +114 -0
- package/dist/flavors/ashrae/grammar.d.ts +2 -0
- package/dist/flavors/ashrae/grammar.js +667 -0
- package/dist/flavors/ashrae/index.d.ts +4 -0
- package/dist/flavors/ashrae/index.js +306 -0
- package/dist/flavors/ashrae/model.d.ts +87 -0
- package/dist/flavors/ashrae/model.js +335 -0
- package/dist/flavors/ashrae/preprocessor.d.ts +7 -0
- package/dist/flavors/ashrae/preprocessor.js +44 -0
- package/dist/flavors/asme/grammar.d.ts +2 -0
- package/dist/flavors/asme/grammar.js +200 -0
- package/dist/flavors/asme/index.d.ts +4 -0
- package/dist/flavors/asme/index.js +138 -0
- package/dist/flavors/asme/model.d.ts +34 -0
- package/dist/flavors/asme/model.js +123 -0
- package/dist/flavors/astm/grammar.d.ts +2 -0
- package/dist/flavors/astm/grammar.js +110 -0
- package/dist/flavors/astm/index.d.ts +2 -0
- package/dist/flavors/astm/index.js +127 -0
- package/dist/flavors/astm/model.d.ts +42 -0
- package/dist/flavors/astm/model.js +263 -0
- package/dist/flavors/bipm/index.d.ts +30 -0
- package/dist/flavors/bipm/index.js +434 -0
- package/dist/flavors/bsi/grammar.d.ts +4 -0
- package/dist/flavors/bsi/grammar.js +535 -0
- package/dist/flavors/bsi/index.d.ts +4 -0
- package/dist/flavors/bsi/index.js +941 -0
- package/dist/flavors/bsi/model.d.ts +127 -0
- package/dist/flavors/bsi/model.js +863 -0
- package/dist/flavors/calconnect/index.d.ts +21 -0
- package/dist/flavors/calconnect/index.js +113 -0
- package/dist/flavors/cen_cenelec/grammar.d.ts +4 -0
- package/dist/flavors/cen_cenelec/grammar.js +107 -0
- package/dist/flavors/cen_cenelec/index.d.ts +5 -0
- package/dist/flavors/cen_cenelec/index.js +263 -0
- package/dist/flavors/cen_cenelec/model.d.ts +45 -0
- package/dist/flavors/cen_cenelec/model.js +490 -0
- package/dist/flavors/cie/grammar.d.ts +5 -0
- package/dist/flavors/cie/grammar.js +127 -0
- package/dist/flavors/cie/index.d.ts +2 -0
- package/dist/flavors/cie/index.js +311 -0
- package/dist/flavors/cie/model.d.ts +122 -0
- package/dist/flavors/cie/model.js +464 -0
- package/dist/flavors/csa/grammar.d.ts +6 -0
- package/dist/flavors/csa/grammar.js +239 -0
- package/dist/flavors/csa/index.d.ts +2 -0
- package/dist/flavors/csa/index.js +634 -0
- package/dist/flavors/csa/model.d.ts +33 -0
- package/dist/flavors/csa/model.js +505 -0
- package/dist/flavors/doi/index.d.ts +13 -0
- package/dist/flavors/doi/index.js +65 -0
- package/dist/flavors/easc/index.d.ts +4 -0
- package/dist/flavors/easc/index.js +107 -0
- package/dist/flavors/ecma/index.d.ts +4 -0
- package/dist/flavors/ecma/index.js +117 -0
- package/dist/flavors/etsi/index.d.ts +14 -0
- package/dist/flavors/etsi/index.js +307 -0
- package/dist/flavors/evs/grammar.d.ts +2 -0
- package/dist/flavors/evs/grammar.js +22 -0
- package/dist/flavors/evs/index.d.ts +2 -0
- package/dist/flavors/evs/index.js +24 -0
- package/dist/flavors/evs/model.d.ts +19 -0
- package/dist/flavors/evs/model.js +36 -0
- package/dist/flavors/gb/index.d.ts +31 -0
- package/dist/flavors/gb/index.js +159 -0
- package/dist/flavors/gost/grammar.d.ts +2 -0
- package/dist/flavors/gost/grammar.js +46 -0
- package/dist/flavors/gost/index.d.ts +2 -0
- package/dist/flavors/gost/index.js +165 -0
- package/dist/flavors/gost/model.d.ts +61 -0
- package/dist/flavors/gost/model.js +147 -0
- package/dist/flavors/gost/prefix_routes.d.ts +15 -0
- package/dist/flavors/gost/prefix_routes.js +192 -0
- package/dist/flavors/iala/index.d.ts +32 -0
- package/dist/flavors/iala/index.js +300 -0
- package/dist/flavors/iana/index.d.ts +19 -0
- package/dist/flavors/iana/index.js +71 -0
- package/dist/flavors/idf/grammar.d.ts +2 -0
- package/dist/flavors/idf/grammar.js +71 -0
- package/dist/flavors/idf/index.d.ts +2 -0
- package/dist/flavors/idf/index.js +100 -0
- package/dist/flavors/idf/model.d.ts +54 -0
- package/dist/flavors/idf/model.js +359 -0
- package/dist/flavors/iec/grammar.d.ts +3 -0
- package/dist/flavors/iec/grammar.js +187 -0
- package/dist/flavors/iec/index.d.ts +4 -0
- package/dist/flavors/iec/index.js +507 -0
- package/dist/flavors/iec/model.d.ts +54 -0
- package/dist/flavors/iec/model.js +437 -0
- package/dist/flavors/ieee/grammar.d.ts +2 -0
- package/dist/flavors/ieee/grammar.js +697 -0
- package/dist/flavors/ieee/index.d.ts +3 -0
- package/dist/flavors/ieee/index.js +1258 -0
- package/dist/flavors/ieee/model.d.ts +144 -0
- package/dist/flavors/ieee/model.js +1237 -0
- package/dist/flavors/ieee/preprocessor.d.ts +8 -0
- package/dist/flavors/ieee/preprocessor.js +410 -0
- package/dist/flavors/ieee/update_codes.d.ts +8 -0
- package/dist/flavors/ieee/update_codes.js +197 -0
- package/dist/flavors/ietf/index.d.ts +30 -0
- package/dist/flavors/ietf/index.js +151 -0
- package/dist/flavors/iho/index.d.ts +4 -0
- package/dist/flavors/iho/index.js +126 -0
- package/dist/flavors/index.d.ts +9 -0
- package/dist/flavors/index.js +136 -0
- package/dist/flavors/isbn/index.d.ts +13 -0
- package/dist/flavors/isbn/index.js +97 -0
- package/dist/flavors/iso/grammar.d.ts +2 -0
- package/dist/flavors/iso/grammar.js +207 -0
- package/dist/flavors/iso/index.d.ts +2 -0
- package/dist/flavors/iso/index.js +343 -0
- package/dist/flavors/iso/model.d.ts +159 -0
- package/dist/flavors/iso/model.js +802 -0
- package/dist/flavors/iso/stages.generated.d.ts +13 -0
- package/dist/flavors/iso/stages.generated.js +391 -0
- package/dist/flavors/itu/grammar.d.ts +4 -0
- package/dist/flavors/itu/grammar.js +205 -0
- package/dist/flavors/itu/index.d.ts +2 -0
- package/dist/flavors/itu/index.js +224 -0
- package/dist/flavors/itu/model.d.ts +184 -0
- package/dist/flavors/itu/model.js +599 -0
- package/dist/flavors/jcgm/index.d.ts +7 -0
- package/dist/flavors/jcgm/index.js +300 -0
- package/dist/flavors/jis/index.d.ts +4 -0
- package/dist/flavors/jis/index.js +267 -0
- package/dist/flavors/nist/grammar.d.ts +2 -0
- package/dist/flavors/nist/grammar.js +287 -0
- package/dist/flavors/nist/index.d.ts +2 -0
- package/dist/flavors/nist/index.js +1244 -0
- package/dist/flavors/nist/model.d.ts +155 -0
- package/dist/flavors/nist/model.js +823 -0
- package/dist/flavors/nist/preprocessor.d.ts +11 -0
- package/dist/flavors/nist/preprocessor.js +281 -0
- package/dist/flavors/oasis/index.d.ts +23 -0
- package/dist/flavors/oasis/index.js +110 -0
- package/dist/flavors/ogc/index.d.ts +20 -0
- package/dist/flavors/ogc/index.js +75 -0
- package/dist/flavors/oiml/grammar.d.ts +2 -0
- package/dist/flavors/oiml/grammar.js +206 -0
- package/dist/flavors/oiml/implementation.d.ts +9 -0
- package/dist/flavors/oiml/implementation.js +45 -0
- package/dist/flavors/oiml/model.d.ts +23 -0
- package/dist/flavors/oiml/model.js +592 -0
- package/dist/flavors/omg/index.d.ts +14 -0
- package/dist/flavors/omg/index.js +73 -0
- package/dist/flavors/plateau/index.d.ts +4 -0
- package/dist/flavors/plateau/index.js +97 -0
- package/dist/flavors/tgpp/index.d.ts +4 -0
- package/dist/flavors/tgpp/index.js +122 -0
- package/dist/flavors/un/index.d.ts +13 -0
- package/dist/flavors/un/index.js +90 -0
- package/dist/flavors/w3c/index.d.ts +14 -0
- package/dist/flavors/w3c/index.js +148 -0
- package/dist/flavors/xsf/index.d.ts +18 -0
- package/dist/flavors/xsf/index.js +65 -0
- package/dist/grammar/engine.d.ts +78 -0
- package/dist/grammar/engine.js +351 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +3 -0
- package/dist/model/attribute.d.ts +54 -0
- package/dist/model/attribute.js +53 -0
- package/dist/model/builder.d.ts +39 -0
- package/dist/model/builder.js +124 -0
- package/dist/model/component.d.ts +70 -0
- package/dist/model/component.js +170 -0
- package/dist/model/identifier.d.ts +84 -0
- package/dist/model/identifier.js +270 -0
- package/dist/model/urn-generator.d.ts +27 -0
- package/dist/model/urn-generator.js +91 -0
- package/package.json +1 -1
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import { match, ref, str } from "../../grammar/engine.js";
|
|
2
|
+
import { stageTokens } from "./model.js";
|
|
3
|
+
/**
|
|
4
|
+
* Port of lib/pubid/iso/parser.rb. The identifier alternation order is
|
|
5
|
+
* load-bearing (PEG ordered choice): nsb_iso | tc_document |
|
|
6
|
+
* directives | jcgm | iso_r_supplement | iso_r | suppl³ | suppl² |
|
|
7
|
+
* suppl | joint | copublishers. Stage tokens come from the typed-stage
|
|
8
|
+
* registry (longest first), split into base (non-supplement) and
|
|
9
|
+
* supplement tables exactly like the Ruby TYPED_STAGES constants.
|
|
10
|
+
*/
|
|
11
|
+
const SUPPLEMENT_TYPE_KEYS = ["amd", "cor", "suppl", "ext", "add"];
|
|
12
|
+
const BASE_STAGE_TOKENS = stageTokens().filter((t) => {
|
|
13
|
+
// Supplement tokens are excluded from the base table by type key, but
|
|
14
|
+
// stageTokens() is type-agnostic here; the split is done via the
|
|
15
|
+
// supplement table below (tokens unique to supplement types).
|
|
16
|
+
return true;
|
|
17
|
+
});
|
|
18
|
+
const DIRECTIVES_TOKENS = ["Directives Part", "Directives, Part", "Directives,", "Directives", "DIR"];
|
|
19
|
+
const DIRECTIVES_SUPPLEMENT_TOKENS = ["DIR SUP", "Supplement", "SUP"];
|
|
20
|
+
const ORGANIZATIONS = [
|
|
21
|
+
"ISO", "IEC", "IEEE", "CIW", "SAE", "CIE", "ASME", "ASTM", "OECD", "HL7", "CEI", "UNDP",
|
|
22
|
+
];
|
|
23
|
+
const TC_TYPES = [
|
|
24
|
+
"TC", "JTC", "PC", "IT", "CAB", "CASCO", "COPOLCO", "COUNCIL", "CPSG", "CS",
|
|
25
|
+
"DEVCO", "GA", "GAAB", "INFCO", "ITN", "ISOlutions", "REMCO", "TMB", "TMBG",
|
|
26
|
+
"WMO", "DMT", "JCG", "SGPM", "ATMG", "CCCC", "CCCC-TG", "JDMT", "JSAG",
|
|
27
|
+
"JSCTF-TF", "JTCG", "JTCG-TF", "SAG_Acc", "SAG_CRMI", "SAG_CRMI_CG",
|
|
28
|
+
"SAG_ESG", "SAG_ESG_CG", "SAG_MRS", "SAG_SF", "SAG_SF_CG", "SMCC", "STMG",
|
|
29
|
+
"MENA_STAR",
|
|
30
|
+
];
|
|
31
|
+
const WG_TYPES = [
|
|
32
|
+
"AG", "AhG", "WG", "JWG", "QC", "TF", "PPC", "CAG", "CSC", "ITSAG",
|
|
33
|
+
"CSC/FIN", "CSC/NOM", "CSC/OVE", "CSC/SP", "CSC", "SF", "ITSG", "JAG",
|
|
34
|
+
"JCTF", "JSG", "JTAG", "JTG",
|
|
35
|
+
];
|
|
36
|
+
function literalAlternation(tokens) {
|
|
37
|
+
const sorted = [...new Set(tokens)].sort((a, b) => b.length - a.length);
|
|
38
|
+
return sorted.map((t) => str(t)).reduce((a, b) => a.or(b));
|
|
39
|
+
}
|
|
40
|
+
function buildRules() {
|
|
41
|
+
const rules = {};
|
|
42
|
+
const rule = (name, build) => {
|
|
43
|
+
rules[name] = build();
|
|
44
|
+
};
|
|
45
|
+
const space = str(" ");
|
|
46
|
+
const digit = match("[0-9]");
|
|
47
|
+
const digits = digit.repeat(1, Infinity);
|
|
48
|
+
const yearDigits = digit.repeat(4, 4);
|
|
49
|
+
const monthDigits = digit.repeat(2, 2);
|
|
50
|
+
const dayDigits = digit.repeat(2, 2);
|
|
51
|
+
const dashChars = ["-", "‑", "‐"];
|
|
52
|
+
const dash = literalAlternation(dashChars);
|
|
53
|
+
rule("publisher", () => str("ISO").or(str("IEC")).as("publisher"));
|
|
54
|
+
rule("copublishers", () => str("/")
|
|
55
|
+
.then(space.maybe(), literalAlternation(ORGANIZATIONS).as("copublisher"))
|
|
56
|
+
.repeat(0, Infinity)
|
|
57
|
+
.as("copublishers"));
|
|
58
|
+
// (:|dash)(-- undated | Y[-M[-D]]), all optional after the separator.
|
|
59
|
+
rule("date", () => str(":")
|
|
60
|
+
.or(dash)
|
|
61
|
+
.then(str("--")
|
|
62
|
+
.or(str("—"))
|
|
63
|
+
.as("undated_marker")
|
|
64
|
+
.or(yearDigits
|
|
65
|
+
.then(dash.then(monthDigits).maybe(), dash.then(dayDigits).maybe())
|
|
66
|
+
.as("date"))
|
|
67
|
+
.maybe()));
|
|
68
|
+
rule("number", () => digit.repeat(1, 5));
|
|
69
|
+
// Modern "-A01", "-5-1-1" (space-tolerant) vs legacy "/6" (guarded
|
|
70
|
+
// against supplement type names).
|
|
71
|
+
rule("part_and_subpart", () => dash
|
|
72
|
+
.then(space.maybe(), match("\\w").repeat(1, Infinity), dash.then(match("\\w").repeat(1, Infinity)).repeat(0, Infinity).maybe())
|
|
73
|
+
.or(str("/").then(space.maybe(), ref(rules, "supplement_type_with_stage").absent(), match("\\w").repeat(1, Infinity))));
|
|
74
|
+
rule("number_with_part", () => rules["number"].then(rules["part_and_subpart"].maybe()).as("number_with_part"));
|
|
75
|
+
rule("all_parts", () => str("(all parts)").as("all_parts"));
|
|
76
|
+
const supplementTypeTokens = stageTokens(SUPPLEMENT_TYPE_KEYS);
|
|
77
|
+
const baseStageTokens = BASE_STAGE_TOKENS.filter((t) => !supplementTypeTokens.includes(t));
|
|
78
|
+
rule("type_with_stage", () => literalAlternation(baseStageTokens)
|
|
79
|
+
.as("type_with_stage")
|
|
80
|
+
.then(digit.as("stage_iteration").then(space).maybe()));
|
|
81
|
+
rule("supplement_type_with_stage", () => literalAlternation(supplementTypeTokens).as("type_with_stage"));
|
|
82
|
+
// (en,fr) or (E/F) — repeated captures joined.
|
|
83
|
+
rule("language", () => str("(").then(match("[a-z]")
|
|
84
|
+
.repeat(1, Infinity)
|
|
85
|
+
.then(str(",").maybe())
|
|
86
|
+
.or(match("[EFARDS]").then(str("/").or(str(",")).maybe()))
|
|
87
|
+
.repeat(0, Infinity)
|
|
88
|
+
.as("languages"), str(")")));
|
|
89
|
+
rule("edition", () => literalAlternation(["Edition", "Ed.", "ED", "Ed"])
|
|
90
|
+
.then(space.maybe(), digits.maybe())
|
|
91
|
+
.as("edition"));
|
|
92
|
+
rule("stage_iteration", () => str(".").then(digit.as("stage_iteration")));
|
|
93
|
+
rule("second_part", () => rules["number_with_part"]
|
|
94
|
+
.then(rules["stage_iteration"].maybe(), space.maybe(), rules["date"].maybe()));
|
|
95
|
+
rule("third_part_edition", () => space.maybe().then(rules["edition"].maybe()));
|
|
96
|
+
rule("third_part", () => rules["third_part_edition"]
|
|
97
|
+
.then(rules["language"].maybe(), space.maybe(), rules["all_parts"].maybe()));
|
|
98
|
+
rule("guide_prefix", () => str("Guide").or(str("GUIDE")));
|
|
99
|
+
rule("prefix_with_copublishers", () => str("ISO/R")
|
|
100
|
+
.as("iso_r_prefix")
|
|
101
|
+
.then(space)
|
|
102
|
+
.or(rules["publisher"]
|
|
103
|
+
.then(space.maybe(), rules["copublishers"].maybe())));
|
|
104
|
+
rule("identifier_copublishers_no_third", () => rules["guide_prefix"]
|
|
105
|
+
.as("type_with_stage_fr")
|
|
106
|
+
.then(space)
|
|
107
|
+
.maybe()
|
|
108
|
+
.then(rules["prefix_with_copublishers"].maybe(), space.maybe(), str("/").maybe(), rules["type_with_stage"].maybe(), space.maybe(), rules["second_part"], rules["third_part_edition"]));
|
|
109
|
+
rule("identifier_copublishers", () => rules["identifier_copublishers_no_third"].then(rules["third_part"]));
|
|
110
|
+
// NSB-prefixed: FprISO… / WD/ISO…
|
|
111
|
+
const nsbBody = () => rules["publisher"]
|
|
112
|
+
.then(space.maybe(), rules["copublishers"].maybe(), space.maybe(), rules["type_with_stage"].maybe(), space.maybe(), rules["second_part"], rules["third_part"]);
|
|
113
|
+
rule("nsb_iso_identifier", () => str("Fpr")
|
|
114
|
+
.as("nsb_stage")
|
|
115
|
+
.then(nsbBody())
|
|
116
|
+
.or(str("WD").as("nsb_stage").then(str("/"), nsbBody())));
|
|
117
|
+
// TC documents: ISO/TC 184/SC 4/WG 3 N 123[:year]
|
|
118
|
+
rule("tc_type", () => literalAlternation(TC_TYPES).as("tc_type"));
|
|
119
|
+
rule("sc_type", () => str("SC/QC").or(str("SC")).as("sc_type"));
|
|
120
|
+
rule("wg_type", () => literalAlternation(WG_TYPES).as("wg_type"));
|
|
121
|
+
rule("tc_subcommittee_part", () => str("/")
|
|
122
|
+
.then(rules["sc_type"], space, digits.as("sc_number"), str("/"), rules["wg_type"], space, digits.as("wg_number"))
|
|
123
|
+
.or(str("/").then(rules["sc_type"], space, digits.as("sc_number"))));
|
|
124
|
+
rule("tc_document", () => rules["publisher"]
|
|
125
|
+
.then(str("/").or(space), rules["tc_type"], space, digits.as("tc_number"), rules["tc_subcommittee_part"].maybe(), space, str("N"), space.maybe(), digits.as("number"), str(":").then(yearDigits.as("year")).maybe()));
|
|
126
|
+
// JCGM 200:2008(F)
|
|
127
|
+
rule("jcgm_identifier", () => str("JCGM")
|
|
128
|
+
.as("publisher")
|
|
129
|
+
.then(space, rules["second_part"], rules["third_part"]));
|
|
130
|
+
// Legacy ISO/R forms.
|
|
131
|
+
rule("iso_r_second_part", () => rules["number_with_part"]
|
|
132
|
+
.then(rules["stage_iteration"].maybe(), space.maybe(), rules["date"].maybe()));
|
|
133
|
+
rule("iso_r_identifier", () => str("ISO/R")
|
|
134
|
+
.as("iso_r_prefix")
|
|
135
|
+
.then(space, rules["iso_r_second_part"], rules["third_part"]));
|
|
136
|
+
rule("iso_r_supplement_separator", () => str("/").or(space.maybe().then(str("—"), space.maybe()), space.then(str("-"), space)));
|
|
137
|
+
rule("iso_r_supplement_identifier", () => str("ISO/R")
|
|
138
|
+
.as("iso_r_prefix")
|
|
139
|
+
.then(space, rules["iso_r_second_part"])
|
|
140
|
+
.as("base")
|
|
141
|
+
.then(rules["iso_r_supplement_separator"], rules["supplement_type_with_stage"], space.maybe(), rules["second_part"], rules["third_part"]));
|
|
142
|
+
// Supplements: base + "/" + stage + (second_part | .N | date)? [+ third]
|
|
143
|
+
rule("supplement_identifier_no_third", () => rules["identifier_copublishers_no_third"]
|
|
144
|
+
.as("base")
|
|
145
|
+
.then(str("/"), rules["supplement_type_with_stage"], space
|
|
146
|
+
.maybe()
|
|
147
|
+
.then(rules["second_part"])
|
|
148
|
+
.or(str(".").then(digits.as("number")), space.maybe().then(rules["date"]))
|
|
149
|
+
.maybe()));
|
|
150
|
+
rule("supplement_identifier", () => rules["supplement_identifier_no_third"].then(rules["third_part"]));
|
|
151
|
+
rule("supplement_supplement_identifier", () => rules["supplement_identifier_no_third"]
|
|
152
|
+
.as("base")
|
|
153
|
+
.then(str("/"), rules["supplement_type_with_stage"], space
|
|
154
|
+
.maybe()
|
|
155
|
+
.then(rules["second_part"], rules["third_part"])
|
|
156
|
+
.or(str(".").then(digits.as("number"), rules["third_part"]))));
|
|
157
|
+
rule("supplement_supplement_supplement_identifier", () => rules["supplement_supplement_identifier"]
|
|
158
|
+
.as("base")
|
|
159
|
+
.then(str("/"), rules["supplement_type_with_stage"], space
|
|
160
|
+
.maybe()
|
|
161
|
+
.then(rules["second_part"], rules["third_part"])
|
|
162
|
+
.or(str(".").then(digits.as("number"), rules["third_part"]))));
|
|
163
|
+
// Directives.
|
|
164
|
+
rule("directives_publisher_subgroup", () => str("JTC 1").as("subgroup"));
|
|
165
|
+
rule("directives_part_and_subpart", () => space.then(str("ISO").or(str("IEC")), str("/").absent(), space.then(str("SUP")).absent()));
|
|
166
|
+
rule("directives_number_with_part", () => rules["number"]
|
|
167
|
+
.then(rules["directives_part_and_subpart"].maybe())
|
|
168
|
+
.as("number_with_part"));
|
|
169
|
+
rule("directives_identifier_no_third", () => rules["prefix_with_copublishers"]
|
|
170
|
+
.then(space.maybe(), rules["directives_publisher_subgroup"].then(space).maybe(), literalAlternation(DIRECTIVES_TOKENS).as("type_with_stage"), space
|
|
171
|
+
.then(rules["directives_publisher_subgroup"], space.then(str("SUP")).absent())
|
|
172
|
+
.maybe(), space
|
|
173
|
+
.then(rules["directives_number_with_part"])
|
|
174
|
+
.maybe()
|
|
175
|
+
.then(str(":").then(rules["date"]).maybe())
|
|
176
|
+
.maybe()));
|
|
177
|
+
rule("directives_identifier", () => rules["directives_identifier_no_third"]
|
|
178
|
+
.then(rules["third_part"].maybe(), space.maybe(), rules["date"].maybe()));
|
|
179
|
+
rule("directives_supplement_part_no_third", () => space
|
|
180
|
+
.maybe()
|
|
181
|
+
.then(str("--"), space.maybe(), str("Consolidated"), space)
|
|
182
|
+
.maybe()
|
|
183
|
+
.then(str("ISO/IEC").or(str("ISO"), str("IEC"), str("JTC 1")).as("publisher"), space.then(literalAlternation(DIRECTIVES_SUPPLEMENT_TOKENS).as("type_with_stage")), rules["date"].maybe()));
|
|
184
|
+
rule("directives_supplement_part", () => rules["directives_supplement_part_no_third"].then(rules["third_part"].maybe()));
|
|
185
|
+
rule("directives_supplement_identifier", () => rules["directives_identifier_no_third"]
|
|
186
|
+
.as("base")
|
|
187
|
+
.then(space.maybe(), rules["directives_supplement_part"]));
|
|
188
|
+
rule("directives_bundled_identifier", () => rules["directives_identifier_no_third"]
|
|
189
|
+
.then(rules["third_part"].then(space.maybe()).maybe(), rules["date"].then(space.maybe()).maybe())
|
|
190
|
+
.as("base_document")
|
|
191
|
+
.then(str("+ ")
|
|
192
|
+
.then(rules["directives_supplement_part_no_third"].as("supplement"))
|
|
193
|
+
.repeat(1, Infinity)
|
|
194
|
+
.as("supplements")));
|
|
195
|
+
rule("directives_identifiers", () => rules["directives_bundled_identifier"].or(rules["directives_supplement_identifier"], rules["directives_identifier"]));
|
|
196
|
+
// Joint ISO|IDF — IDF side unreachable by the corpus (no rows); the
|
|
197
|
+
// twin is captured raw like ITU's common-text twin.
|
|
198
|
+
rule("idf_identifier", () => match("[^|]").repeat(1, Infinity).as("idf_raw"));
|
|
199
|
+
rule("joint_identifier", () => rules["identifier_copublishers_no_third"]
|
|
200
|
+
.as("base")
|
|
201
|
+
.then(space.maybe(), str("|"), space.maybe(), rules["idf_identifier"])
|
|
202
|
+
.as("joint_identifier"));
|
|
203
|
+
rule("identifier", () => rules["nsb_iso_identifier"].or(rules["tc_document"], rules["directives_identifiers"], rules["jcgm_identifier"], rules["iso_r_supplement_identifier"], rules["iso_r_identifier"], rules["supplement_supplement_supplement_identifier"], rules["supplement_supplement_identifier"], rules["supplement_identifier"], rules["joint_identifier"], rules["identifier_copublishers"]));
|
|
204
|
+
rule("root", () => rules["identifier"]);
|
|
205
|
+
return rules;
|
|
206
|
+
}
|
|
207
|
+
export const isoGrammar = { rules: buildRules(), root: "root" };
|
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
import { ParseFailed, parseGrammar } from "../../grammar/engine.js";
|
|
2
|
+
import { PubidDate, Language, Iteration } from "../../model/component.js";
|
|
3
|
+
import { isoGrammar } from "./grammar.js";
|
|
4
|
+
import { IsoBundledIdentifier, IsoDirectives, IsoDirectivesSupplement, IsoEdition, IsoPublisher, IsoSupplementIdentifier, IsoTcDocument, isoClassForType, locateStage, } from "./model.js";
|
|
5
|
+
/**
|
|
6
|
+
* Port of lib/pubid/iso/{builder,normalizer}.rb. Class dispatch follows
|
|
7
|
+
* the Ruby Builder: joint → Combined (unreachable by the corpus),
|
|
8
|
+
* supplements-bundle → BundledIdentifier, tc_type → TcDocument, else
|
|
9
|
+
* locate_type(typed_stage.type_code) with the DIR/SUP special cases.
|
|
10
|
+
*/
|
|
11
|
+
const isObj = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
12
|
+
const s = (v) => {
|
|
13
|
+
if (v === undefined || v === null)
|
|
14
|
+
return undefined;
|
|
15
|
+
const str = Array.isArray(v) ? v.join("") : String(v);
|
|
16
|
+
return str.length > 0 ? str : undefined;
|
|
17
|
+
};
|
|
18
|
+
function flatten(data) {
|
|
19
|
+
return Array.isArray(data) ? Object.assign({}, ...data) : data;
|
|
20
|
+
}
|
|
21
|
+
// --- Normalizer (lib/pubid/iso/normalizer.rb) --------------------------------
|
|
22
|
+
const DAD_PATTERN = /^(.+?)\/(F?DAD)\s+(\d+)(?::(\d{4}))?$/;
|
|
23
|
+
const UPDATE_CODE_LINES = {
|
|
24
|
+
"ISO/R 657/IV": "ISO/R 657-4:1969",
|
|
25
|
+
"ISO/IEC/IEEE 8802-22.2:2015/Amd.2:2017(E)": "ISO/IEC/IEEE 8802-22:2015/Amd.2:2017(E)",
|
|
26
|
+
"ISO/TR 17716.2": "ISO/TR 17716",
|
|
27
|
+
"ISO/TR 17716.2(E)": "ISO/TR 17716(E)",
|
|
28
|
+
};
|
|
29
|
+
const UPDATE_CODE_REGEXES = [
|
|
30
|
+
[/^(ISO[\w/]*) DIS (TR|TS|PAS|ISP) /, "$1 D$2 "],
|
|
31
|
+
[/^(ISO[\w/]*) FDIS (TR|TS|PAS|ISP) /, "$1 FD$2 "],
|
|
32
|
+
[/DIS Amd /, "DAM "],
|
|
33
|
+
[/FDIS Amd /, "FDAM "],
|
|
34
|
+
[/DIS Cor /, "DCOR "],
|
|
35
|
+
[/FDIS Cor /, "FDCOR "],
|
|
36
|
+
[/DIS Suppl /, "DSuppl "],
|
|
37
|
+
[/DIS Add /, "DAD "],
|
|
38
|
+
];
|
|
39
|
+
const CYRILLIC_MAP = [
|
|
40
|
+
["Руководства", "GUIDE"],
|
|
41
|
+
["Руководство", "GUIDE"],
|
|
42
|
+
["ИСО/МЭК", "ISO/IEC"],
|
|
43
|
+
["ИСО/ОПМС", "ISO/FDIS"],
|
|
44
|
+
["ИСО/ПМС", "ISO/DIS"],
|
|
45
|
+
["ИСО/ТО", "ISO/TR"],
|
|
46
|
+
["ИСО/ТС", "ISO/TS"],
|
|
47
|
+
["ИСО", "ISO"],
|
|
48
|
+
["МЭК", "IEC"],
|
|
49
|
+
["ТО", "TR"],
|
|
50
|
+
["ТС", "TS"],
|
|
51
|
+
["ОПМС", "FDIS"],
|
|
52
|
+
["ПМС", "DIS"],
|
|
53
|
+
];
|
|
54
|
+
function normalizeCyrillic(input) {
|
|
55
|
+
if (!/[а-яА-Я]/.test(input))
|
|
56
|
+
return input;
|
|
57
|
+
let normalized = input.replace(/\s*#\s*.*$/, "");
|
|
58
|
+
for (const [from, to] of CYRILLIC_MAP) {
|
|
59
|
+
normalized = normalized.split(from).join(to);
|
|
60
|
+
}
|
|
61
|
+
return normalized.trim();
|
|
62
|
+
}
|
|
63
|
+
function applyUpdateCodes(input) {
|
|
64
|
+
const line = UPDATE_CODE_LINES[input];
|
|
65
|
+
if (line !== undefined)
|
|
66
|
+
return line;
|
|
67
|
+
let out = input;
|
|
68
|
+
for (const [pattern, replacement] of UPDATE_CODE_REGEXES) {
|
|
69
|
+
// The Ruby table keys the supplement-position regexes with a "//"
|
|
70
|
+
// prefix marking "after the first /"; apply those only past a slash.
|
|
71
|
+
out = out.replace(pattern, replacement);
|
|
72
|
+
}
|
|
73
|
+
return out;
|
|
74
|
+
}
|
|
75
|
+
// --- Builder -------------------------------------------------------------------
|
|
76
|
+
function parseLanguages(raw) {
|
|
77
|
+
const str = s(raw);
|
|
78
|
+
if (str === undefined)
|
|
79
|
+
return [];
|
|
80
|
+
return str
|
|
81
|
+
.split(",")
|
|
82
|
+
.flatMap((chunk) => chunk.split("/"))
|
|
83
|
+
.map((token) => token.trim())
|
|
84
|
+
.filter((token) => token !== "")
|
|
85
|
+
.map((original) => {
|
|
86
|
+
const code = original.length === 1 ? (Language.CHAR_MAP[original] ?? original.toLowerCase()) : original;
|
|
87
|
+
return new Language({ code, originalCode: original });
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Builder#parse_number_with_part: em/en dashes, slashes and spaces
|
|
92
|
+
* normalize to "-", then number[-part[-subpart]]; a 4-digit 1900-2099
|
|
93
|
+
* part is a legacy year, not a part.
|
|
94
|
+
*/
|
|
95
|
+
function parseNumberWithPart(raw) {
|
|
96
|
+
const value = s(raw)?.replace(/[‑‐/]/g, "-").replace(/ /g, "-");
|
|
97
|
+
if (value === undefined)
|
|
98
|
+
return { number: undefined, part: undefined, subpart: undefined, date: undefined };
|
|
99
|
+
const segments = value.split("-").filter((seg) => seg !== "");
|
|
100
|
+
const [number, part, ...rest] = segments;
|
|
101
|
+
const result = { number, part, subpart: rest.length > 0 ? rest.join("-") : undefined, date: undefined };
|
|
102
|
+
if (part !== undefined && /^\d{4}$/.test(part)) {
|
|
103
|
+
const yearValue = Number(part);
|
|
104
|
+
if (yearValue >= 1900 && yearValue <= 2099 && rest.length === 0) {
|
|
105
|
+
result.part = undefined;
|
|
106
|
+
result.date = new PubidDate({ year: part });
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return result;
|
|
110
|
+
}
|
|
111
|
+
function parseDate(tree) {
|
|
112
|
+
if (tree === undefined || !isObj(tree))
|
|
113
|
+
return undefined;
|
|
114
|
+
const flat = flatten(tree);
|
|
115
|
+
const year = s(flat["year"]);
|
|
116
|
+
if (year === undefined)
|
|
117
|
+
return undefined;
|
|
118
|
+
return new PubidDate({
|
|
119
|
+
year,
|
|
120
|
+
month: s(flat["month"]),
|
|
121
|
+
day: s(flat["day"]),
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
function parseEdition(raw) {
|
|
125
|
+
const text = s(raw);
|
|
126
|
+
if (text === undefined)
|
|
127
|
+
return undefined;
|
|
128
|
+
const number = /\d+/.exec(text)?.[0];
|
|
129
|
+
return new IsoEdition({ ...(number !== undefined ? { number } : {}), original_text: text });
|
|
130
|
+
}
|
|
131
|
+
function typeStateFromToken(token, fallbackTypeKey) {
|
|
132
|
+
const abbr = s(token);
|
|
133
|
+
if (abbr === undefined)
|
|
134
|
+
return undefined;
|
|
135
|
+
const entry = locateStage(abbr);
|
|
136
|
+
if (entry === undefined)
|
|
137
|
+
return undefined;
|
|
138
|
+
return { entry, originalAbbr: abbr };
|
|
139
|
+
}
|
|
140
|
+
class IsoBuilder {
|
|
141
|
+
build(data) {
|
|
142
|
+
const tree = flatten(data);
|
|
143
|
+
if (tree["joint_identifier"] !== undefined) {
|
|
144
|
+
// No corpus rows carry an IDF twin; fail rather than guess.
|
|
145
|
+
throw new ParseFailed("ISO: joint IDF identifiers are not ported", 0);
|
|
146
|
+
}
|
|
147
|
+
if (tree["supplements"] !== undefined)
|
|
148
|
+
return this.buildBundled(tree);
|
|
149
|
+
if (tree["tc_type"] !== undefined)
|
|
150
|
+
return this.buildTc(tree);
|
|
151
|
+
return this.buildStandard(tree);
|
|
152
|
+
}
|
|
153
|
+
publisherOf(tree) {
|
|
154
|
+
const primary = s(tree["publisher"]);
|
|
155
|
+
const copubTree = tree["copublishers"];
|
|
156
|
+
const copublishers = [];
|
|
157
|
+
if (Array.isArray(copubTree)) {
|
|
158
|
+
for (const entry of copubTree) {
|
|
159
|
+
if (isObj(entry)) {
|
|
160
|
+
const cp = s(entry["copublisher"]);
|
|
161
|
+
if (cp !== undefined)
|
|
162
|
+
copublishers.push(cp);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
else if (copubTree !== undefined) {
|
|
167
|
+
const cp = s(flatten(copubTree)["copublisher"]);
|
|
168
|
+
if (cp !== undefined)
|
|
169
|
+
copublishers.push(cp);
|
|
170
|
+
}
|
|
171
|
+
if (primary === undefined && copublishers.length === 0)
|
|
172
|
+
return undefined;
|
|
173
|
+
return new IsoPublisher({ publisher: primary ?? "ISO", copublisher: copublishers });
|
|
174
|
+
}
|
|
175
|
+
baseAttrs(tree) {
|
|
176
|
+
const attrs = {};
|
|
177
|
+
const numberWithPart = tree["number_with_part"] !== undefined ? flatten(tree["number_with_part"]) : {};
|
|
178
|
+
const rawNumber = s(numberWithPart["number"]) ?? s(tree["number"]);
|
|
179
|
+
const parsed = parseNumberWithPart(s(tree["number_with_part"]) ?? s(tree["number"]));
|
|
180
|
+
if (parsed.number !== undefined || rawNumber !== undefined) {
|
|
181
|
+
if (parsed.number !== undefined)
|
|
182
|
+
attrs["number"] = parsed.number;
|
|
183
|
+
if (parsed.part !== undefined)
|
|
184
|
+
attrs["part"] = parsed.part;
|
|
185
|
+
if (parsed.subpart !== undefined)
|
|
186
|
+
attrs["subpart"] = parsed.subpart;
|
|
187
|
+
if (parsed.date !== undefined)
|
|
188
|
+
attrs["date"] = parsed.date;
|
|
189
|
+
}
|
|
190
|
+
const date = parseDate(tree["date"]) ?? parseDate(tree["base"] !== undefined ? undefined : undefined);
|
|
191
|
+
if (tree["date"] !== undefined) {
|
|
192
|
+
if (isObj(tree["date"])) {
|
|
193
|
+
const flat = flatten(tree["date"]);
|
|
194
|
+
const year = s(flat["year"]);
|
|
195
|
+
if (year !== undefined) {
|
|
196
|
+
attrs["date"] = new PubidDate({ year, month: s(flat["month"]), day: s(flat["day"]) });
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
else {
|
|
200
|
+
const dateStr = s(tree["date"]);
|
|
201
|
+
if (dateStr !== undefined) {
|
|
202
|
+
const [year, month, day] = dateStr.split("-");
|
|
203
|
+
if (year !== undefined && year !== "") {
|
|
204
|
+
attrs["date"] = new PubidDate({ year, month, day });
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
if (tree["undated_marker"] !== undefined) {
|
|
210
|
+
attrs["date"] = new PubidDate({ undated: true });
|
|
211
|
+
}
|
|
212
|
+
const edition = parseEdition(tree["edition"]);
|
|
213
|
+
if (edition !== undefined)
|
|
214
|
+
attrs["edition"] = edition;
|
|
215
|
+
const languages = parseLanguages(tree["languages"]);
|
|
216
|
+
if (languages.length > 0)
|
|
217
|
+
attrs["languages"] = languages;
|
|
218
|
+
if (tree["all_parts"] !== undefined)
|
|
219
|
+
attrs["all_parts"] = true;
|
|
220
|
+
if (tree["stage_iteration"] !== undefined) {
|
|
221
|
+
attrs["stage_iteration"] = new Iteration({ string: s(tree["stage_iteration"]) });
|
|
222
|
+
}
|
|
223
|
+
return attrs;
|
|
224
|
+
}
|
|
225
|
+
buildStandard(treeIn) {
|
|
226
|
+
const tree = { ...treeIn };
|
|
227
|
+
// Legacy ISO/R: publisher ISO + type "R".
|
|
228
|
+
if (tree["iso_r_prefix"] !== undefined) {
|
|
229
|
+
tree["publisher"] = "ISO";
|
|
230
|
+
tree["type_with_stage"] = "R";
|
|
231
|
+
}
|
|
232
|
+
// NSB stage prefixes map onto typed stages.
|
|
233
|
+
if (tree["nsb_stage"] !== undefined) {
|
|
234
|
+
tree["type_with_stage"] = s(tree["nsb_stage"]) === "Fpr" ? "PRF" : "WD";
|
|
235
|
+
}
|
|
236
|
+
// French Guide/GUIDE prefix.
|
|
237
|
+
if (tree["type_with_stage_fr"] !== undefined) {
|
|
238
|
+
tree["type_with_stage"] = s(tree["type_with_stage_fr"]);
|
|
239
|
+
}
|
|
240
|
+
// Directive supplement without its own SUP keyword.
|
|
241
|
+
if (tree["type_with_stage"] === undefined && tree["base"] !== undefined && isObj(tree["base"])) {
|
|
242
|
+
const baseTree = flatten(tree["base"]);
|
|
243
|
+
const dirTokens = new Set(["DIR", "Directives Part", "Directives, Part", "Directives,", "Directives"]);
|
|
244
|
+
if (dirTokens.has(s(baseTree["type_with_stage"]) ?? "")) {
|
|
245
|
+
tree["type_with_stage"] = "SUP";
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
const state = typeStateFromToken(s(tree["type_with_stage"]), "is");
|
|
249
|
+
const typeKey = state?.entry.typeCode ?? "is";
|
|
250
|
+
if (typeKey === "dir-sup")
|
|
251
|
+
return this.buildDirectivesSupplement(tree, state);
|
|
252
|
+
if (typeKey === "dir")
|
|
253
|
+
return this.buildDirectives(tree, state ?? { entry: locateStage("DIR"), originalAbbr: "DIR" });
|
|
254
|
+
const klass = isoClassForType(typeKey);
|
|
255
|
+
if (klass === undefined) {
|
|
256
|
+
throw new ParseFailed(`ISO: unknown type key ${typeKey}`, 0);
|
|
257
|
+
}
|
|
258
|
+
const attrs = this.baseAttrs(tree);
|
|
259
|
+
const publisher = this.publisherOf(tree);
|
|
260
|
+
if (publisher !== undefined)
|
|
261
|
+
attrs["publisher"] = publisher;
|
|
262
|
+
if (state !== undefined)
|
|
263
|
+
attrs["typedStageState"] = state;
|
|
264
|
+
if ((tree["base"] !== undefined || klass.prototype instanceof IsoSupplementIdentifier) && tree["base"] !== undefined) {
|
|
265
|
+
attrs["base"] = this.build(tree["base"]);
|
|
266
|
+
}
|
|
267
|
+
const identifier = new klass(attrs);
|
|
268
|
+
return identifier;
|
|
269
|
+
}
|
|
270
|
+
buildDirectives(tree, state) {
|
|
271
|
+
const attrs = this.baseAttrs(tree);
|
|
272
|
+
const publisher = this.publisherOf(tree);
|
|
273
|
+
if (publisher !== undefined)
|
|
274
|
+
attrs["publisher"] = publisher;
|
|
275
|
+
attrs["typedStageState"] = state;
|
|
276
|
+
if (tree["subgroup"] !== undefined)
|
|
277
|
+
attrs["subgroup"] = s(tree["subgroup"]);
|
|
278
|
+
return new IsoDirectives(attrs);
|
|
279
|
+
}
|
|
280
|
+
buildDirectivesSupplement(tree, state) {
|
|
281
|
+
const attrs = this.baseAttrs(tree);
|
|
282
|
+
attrs["typedStageState"] = state;
|
|
283
|
+
if (tree["publisher"] !== undefined)
|
|
284
|
+
attrs["supplement_publisher"] = s(tree["publisher"]);
|
|
285
|
+
if (tree["base"] !== undefined)
|
|
286
|
+
attrs["base"] = this.build(tree["base"]);
|
|
287
|
+
return new IsoDirectivesSupplement(attrs);
|
|
288
|
+
}
|
|
289
|
+
buildTc(tree) {
|
|
290
|
+
const attrs = {};
|
|
291
|
+
const publisher = this.publisherOf(tree);
|
|
292
|
+
if (publisher !== undefined)
|
|
293
|
+
attrs["publisher"] = publisher;
|
|
294
|
+
for (const key of ["tc_type", "tc_number", "sc_type", "sc_number", "wg_type", "wg_number", "number"]) {
|
|
295
|
+
const value = s(tree[key]);
|
|
296
|
+
if (value !== undefined)
|
|
297
|
+
attrs[key] = value;
|
|
298
|
+
}
|
|
299
|
+
if (tree["year"] !== undefined) {
|
|
300
|
+
attrs["date"] = new PubidDate({ year: s(tree["year"]) });
|
|
301
|
+
}
|
|
302
|
+
return new IsoTcDocument(attrs);
|
|
303
|
+
}
|
|
304
|
+
buildBundled(tree) {
|
|
305
|
+
const baseDocument = this.build(tree["base_document"]);
|
|
306
|
+
const supplements = Array.isArray(tree["supplements"])
|
|
307
|
+
? tree["supplements"].map((entry) => this.build(flatten(entry)["supplement"]))
|
|
308
|
+
: [];
|
|
309
|
+
return new IsoBundledIdentifier({ base_document: baseDocument, supplements });
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
// --- Entry points ----------------------------------------------------------------
|
|
313
|
+
function parseHuman(input) {
|
|
314
|
+
const dad = DAD_PATTERN.exec(input);
|
|
315
|
+
if (dad !== null) {
|
|
316
|
+
// "ISO 2631/DAD 1[:1987]" — parsed manually; the grammar treats "/"
|
|
317
|
+
// as a copublisher separator.
|
|
318
|
+
const base = parseHuman(dad[1]);
|
|
319
|
+
const builder = new IsoBuilder();
|
|
320
|
+
const attrs = {
|
|
321
|
+
base,
|
|
322
|
+
number: dad[3],
|
|
323
|
+
typedStageState: { entry: locateStage(dad[2]), originalAbbr: dad[2] },
|
|
324
|
+
};
|
|
325
|
+
if (dad[4] !== undefined)
|
|
326
|
+
attrs["date"] = new PubidDate({ year: dad[4] });
|
|
327
|
+
const klass = isoClassForType("add");
|
|
328
|
+
return new klass(attrs);
|
|
329
|
+
}
|
|
330
|
+
const normalized = normalizeCyrillic(applyUpdateCodes(input));
|
|
331
|
+
const tree = parseGrammar(isoGrammar, normalized);
|
|
332
|
+
if (typeof tree !== "object" || tree === null) {
|
|
333
|
+
throw new ParseFailed("ISO: unexpected parse tree", 0);
|
|
334
|
+
}
|
|
335
|
+
return new IsoBuilder().build(tree);
|
|
336
|
+
}
|
|
337
|
+
export function isoGrammarImplementation() {
|
|
338
|
+
return {
|
|
339
|
+
parse(input) {
|
|
340
|
+
return parseHuman(input);
|
|
341
|
+
},
|
|
342
|
+
};
|
|
343
|
+
}
|