@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,97 @@
|
|
|
1
|
+
import { match, str } from "../../grammar/engine.js";
|
|
2
|
+
import { ParseFailed, parseGrammar } from "../../grammar/engine.js";
|
|
3
|
+
import { BaseIdentifier, registerType } from "../../model/identifier.js";
|
|
4
|
+
import { extendAttributes, keyValue } from "../../model/attribute.js";
|
|
5
|
+
import { BaseUrnGenerator } from "../../model/urn-generator.js";
|
|
6
|
+
const KIND_TYPES = {
|
|
7
|
+
handbook: "pubid:plateau:handbook",
|
|
8
|
+
"technical-report": "pubid:plateau:technical-report",
|
|
9
|
+
};
|
|
10
|
+
function buildRules() {
|
|
11
|
+
const rules = {};
|
|
12
|
+
const rule = (name, build) => {
|
|
13
|
+
rules[name] = build();
|
|
14
|
+
};
|
|
15
|
+
const space = str(" ");
|
|
16
|
+
const digits = match("[0-9]").repeat(1, Infinity);
|
|
17
|
+
rule("doc_type", () => str("Handbook").or(str("Technical Report")).as("type"));
|
|
18
|
+
rule("number", () => str("#").then(digits.as("number")));
|
|
19
|
+
rule("annex", () => str("-").or(str("_")).then(digits.as("annex")));
|
|
20
|
+
rule("edition_part", () => str("第").then(digits.then(str("."), digits).as("edition"), str("版")));
|
|
21
|
+
rule("edition_latin", () => digits.then(str("."), digits).as("edition"));
|
|
22
|
+
rule("edition", () => space.then(rules["edition_part"].or(rules["edition_latin"])));
|
|
23
|
+
rule("annex_supplement", () => space.then(str("Annex")).then(space, match("[A-Z]").as("annex_letter")));
|
|
24
|
+
rule("handbook", () => str("PLATEAU")
|
|
25
|
+
.then(space, rules["doc_type"], space, rules["number"])
|
|
26
|
+
.then(rules["annex"].maybe())
|
|
27
|
+
.then(rules["edition"].maybe()));
|
|
28
|
+
rule("identifier", () => rules["handbook"]
|
|
29
|
+
.then(rules["annex_supplement"])
|
|
30
|
+
.as("base")
|
|
31
|
+
.or(rules["handbook"]));
|
|
32
|
+
rule("root", () => rules["identifier"]);
|
|
33
|
+
return rules;
|
|
34
|
+
}
|
|
35
|
+
export const plateauGrammar = { rules: buildRules(), root: "root" };
|
|
36
|
+
const pad2 = (n) => String(n).padStart(2, "0");
|
|
37
|
+
function plateauClass(kind) {
|
|
38
|
+
const isHandbook = kind === "handbook";
|
|
39
|
+
class PlateauKindIdentifier extends BaseIdentifier {
|
|
40
|
+
static polymorphicName = KIND_TYPES[kind];
|
|
41
|
+
static attributes = extendAttributes(BaseIdentifier, {
|
|
42
|
+
number: { type: "integer" },
|
|
43
|
+
annex: { type: "integer" },
|
|
44
|
+
edition: { type: "string" },
|
|
45
|
+
});
|
|
46
|
+
static mappings = keyValue({ wire: "number", to: "number" }, { wire: "edition", to: "edition" }, { wire: "annex", to: "annex" });
|
|
47
|
+
render() {
|
|
48
|
+
let result = `PLATEAU ${isHandbook ? "Handbook" : "Technical Report"} #${pad2(this.number)}`;
|
|
49
|
+
if (this.annex !== undefined)
|
|
50
|
+
result += `-${this.annex}`;
|
|
51
|
+
if (isHandbook && this.edition !== undefined)
|
|
52
|
+
result += ` 第${this.edition}版`;
|
|
53
|
+
return result;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
class PlateauUrnGenerator extends BaseUrnGenerator {
|
|
57
|
+
generate() {
|
|
58
|
+
const id = this.identifier;
|
|
59
|
+
const parts = ["urn", "plateau", isHandbook ? "handbook" : "tr", pad2(id.number)];
|
|
60
|
+
if (id.annex !== undefined)
|
|
61
|
+
parts.push(pad2(id.annex));
|
|
62
|
+
return parts.join(":");
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
PlateauKindIdentifier.urnGenerator = PlateauUrnGenerator;
|
|
66
|
+
registerType(PlateauKindIdentifier);
|
|
67
|
+
return PlateauKindIdentifier;
|
|
68
|
+
}
|
|
69
|
+
const KIND_CLASSES = {
|
|
70
|
+
handbook: plateauClass("handbook"),
|
|
71
|
+
"technical-report": plateauClass("technical-report"),
|
|
72
|
+
};
|
|
73
|
+
export function plateauGrammarImplementation() {
|
|
74
|
+
return {
|
|
75
|
+
parse(input) {
|
|
76
|
+
const tree = parseGrammar(plateauGrammar, input);
|
|
77
|
+
if (typeof tree !== "object" || tree === null || Array.isArray(tree)) {
|
|
78
|
+
throw new ParseFailed("PLATEAU: unexpected parse tree", 0);
|
|
79
|
+
}
|
|
80
|
+
const data = tree;
|
|
81
|
+
if (data["base"] !== undefined) {
|
|
82
|
+
throw new ParseFailed("PLATEAU: Annex supplements are unsupported upstream", 0);
|
|
83
|
+
}
|
|
84
|
+
const kind = String(data["type"]) === "Handbook" ? "handbook" : "technical-report";
|
|
85
|
+
const attrs = { number: Number(data["number"]) };
|
|
86
|
+
if (data["annex"] !== undefined && data["annex"] !== null) {
|
|
87
|
+
attrs["annex"] = Number(data["annex"]);
|
|
88
|
+
}
|
|
89
|
+
// A legacy Latin TR edition is captured by the shared handbook
|
|
90
|
+
// rule and dropped for Technical Report (Ruby builder parity).
|
|
91
|
+
if (data["edition"] !== undefined && data["edition"] !== null && kind === "handbook") {
|
|
92
|
+
attrs["edition"] = String(data["edition"]);
|
|
93
|
+
}
|
|
94
|
+
return new KIND_CLASSES[kind](attrs);
|
|
95
|
+
},
|
|
96
|
+
};
|
|
97
|
+
}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { match, str } from "../../grammar/engine.js";
|
|
2
|
+
import { ParseFailed, parseGrammar } from "../../grammar/engine.js";
|
|
3
|
+
import { BaseIdentifier, registerType } from "../../model/identifier.js";
|
|
4
|
+
import { extendAttributes, keyValue } from "../../model/attribute.js";
|
|
5
|
+
import { BaseUrnGenerator } from "../../model/urn-generator.js";
|
|
6
|
+
import { BaseBuilder } from "../../model/builder.js";
|
|
7
|
+
const KIND_PREFIXES = {
|
|
8
|
+
"technical-report": "TR",
|
|
9
|
+
"technical-specification": "TS",
|
|
10
|
+
};
|
|
11
|
+
function buildRules() {
|
|
12
|
+
const rules = {};
|
|
13
|
+
const rule = (name, build) => {
|
|
14
|
+
rules[name] = build();
|
|
15
|
+
};
|
|
16
|
+
const digits = match("[0-9]").repeat(1, Infinity);
|
|
17
|
+
const space = str(" ");
|
|
18
|
+
const any = match("[\\s\\S]");
|
|
19
|
+
rule("publisher_prefix", () => str("3GPP").then(space));
|
|
20
|
+
rule("type", () => str("TR").or(str("TS")).as("type"));
|
|
21
|
+
rule("number_core", () => digits.then(str("."), digits).as("number"));
|
|
22
|
+
rule("suffix", () => match("[A-Za-z]").repeat(1, Infinity).as("suffix"));
|
|
23
|
+
rule("part", () => str("-").then(digits.as("part")));
|
|
24
|
+
rule("parts", () => rules["part"].repeat(0, Infinity).as("parts"));
|
|
25
|
+
rule("version_core", () => digits.then(str("."), digits, str("."), digits));
|
|
26
|
+
rule("release", () => rules["version_core"]
|
|
27
|
+
.then(any.absent())
|
|
28
|
+
.absent()
|
|
29
|
+
.then(match("[^/:]").repeat(1, Infinity).as("release")));
|
|
30
|
+
rule("version", () => rules["version_core"].as("version"));
|
|
31
|
+
rule("identifier", () => rules["publisher_prefix"]
|
|
32
|
+
.maybe()
|
|
33
|
+
.then(rules["type"], space, rules["number_core"])
|
|
34
|
+
.then(rules["suffix"].maybe())
|
|
35
|
+
.then(rules["parts"])
|
|
36
|
+
.then(str(":").then(rules["release"]).maybe())
|
|
37
|
+
.then(str("/").then(rules["version"]).maybe()));
|
|
38
|
+
rule("root", () => rules["identifier"]);
|
|
39
|
+
return rules;
|
|
40
|
+
}
|
|
41
|
+
export const tgppGrammar = { rules: buildRules(), root: "root" };
|
|
42
|
+
function tgppClass(kind) {
|
|
43
|
+
const prefix = KIND_PREFIXES[kind];
|
|
44
|
+
class TgppKindIdentifier extends BaseIdentifier {
|
|
45
|
+
static polymorphicName = `pubid:3gpp:${kind}`;
|
|
46
|
+
static attributes = extendAttributes(BaseIdentifier, {
|
|
47
|
+
number: { type: "string" },
|
|
48
|
+
suffix: { type: "string" },
|
|
49
|
+
parts: { type: "string", collection: true, initializeEmpty: true },
|
|
50
|
+
release: { type: "string" },
|
|
51
|
+
version: { type: "string" },
|
|
52
|
+
});
|
|
53
|
+
static mappings = keyValue({ wire: "number", to: "number" }, { wire: "suffix", to: "suffix" }, { wire: "parts", to: "parts" }, { wire: "release", to: "release" }, { wire: "version", to: "version" });
|
|
54
|
+
code() {
|
|
55
|
+
let result = this.number + (this.suffix ?? "");
|
|
56
|
+
if (this.parts.length > 0)
|
|
57
|
+
result += this.parts.map((p) => `-${p}`).join("");
|
|
58
|
+
return result;
|
|
59
|
+
}
|
|
60
|
+
render() {
|
|
61
|
+
let result = `${prefix} ${this.code()}`;
|
|
62
|
+
if (this.release !== undefined && this.release !== "")
|
|
63
|
+
result += `:${this.release}`;
|
|
64
|
+
if (this.version !== undefined && this.version !== "")
|
|
65
|
+
result += `/${this.version}`;
|
|
66
|
+
return result;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
class TgppUrnGenerator extends BaseUrnGenerator {
|
|
70
|
+
generate() {
|
|
71
|
+
const id = this.identifier;
|
|
72
|
+
const tail = [id.release, id.version];
|
|
73
|
+
while (tail.length > 0 && (tail[tail.length - 1] === undefined || tail[tail.length - 1] === "")) {
|
|
74
|
+
tail.pop();
|
|
75
|
+
}
|
|
76
|
+
return ["urn", "3gpp", prefix.toLowerCase(), id.code(), ...tail.map((s) => s ?? "")].join(":");
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
TgppKindIdentifier.urnGenerator = TgppUrnGenerator;
|
|
80
|
+
registerType(TgppKindIdentifier);
|
|
81
|
+
return TgppKindIdentifier;
|
|
82
|
+
}
|
|
83
|
+
const KIND_CLASSES = {
|
|
84
|
+
"technical-report": tgppClass("technical-report"),
|
|
85
|
+
"technical-specification": tgppClass("technical-specification"),
|
|
86
|
+
};
|
|
87
|
+
function isObj(v) {
|
|
88
|
+
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
89
|
+
}
|
|
90
|
+
function extractParts(raw) {
|
|
91
|
+
if (Array.isArray(raw)) {
|
|
92
|
+
return raw.map((p) => (isObj(p) ? String(p["part"]) : String(p)));
|
|
93
|
+
}
|
|
94
|
+
if (isObj(raw) && raw["part"] !== undefined)
|
|
95
|
+
return [String(raw["part"])];
|
|
96
|
+
return [];
|
|
97
|
+
}
|
|
98
|
+
class TgppBuilder extends BaseBuilder {
|
|
99
|
+
selectClass(data) {
|
|
100
|
+
return KIND_CLASSES[String(data["type"]) === "TR" ? "technical-report" : "technical-specification"];
|
|
101
|
+
}
|
|
102
|
+
defaultIdentifierClass() {
|
|
103
|
+
return KIND_CLASSES["technical-specification"];
|
|
104
|
+
}
|
|
105
|
+
cast(key, value) {
|
|
106
|
+
if (key === "parts")
|
|
107
|
+
return { parts: extractParts(value) };
|
|
108
|
+
return value;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
export function tgppGrammarImplementation() {
|
|
112
|
+
const builder = new TgppBuilder();
|
|
113
|
+
return {
|
|
114
|
+
parse(input) {
|
|
115
|
+
const tree = parseGrammar(tgppGrammar, input);
|
|
116
|
+
if (typeof tree !== "object" || tree === null || Array.isArray(tree)) {
|
|
117
|
+
throw new ParseFailed("3GPP: unexpected parse tree", 0);
|
|
118
|
+
}
|
|
119
|
+
return builder.build(tree);
|
|
120
|
+
},
|
|
121
|
+
};
|
|
122
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Grammar } from "../../grammar/engine.js";
|
|
2
|
+
import type { FlavorImplementation } from "../../conformance/implementation.js";
|
|
3
|
+
import { BaseIdentifier } from "../../model/identifier.js";
|
|
4
|
+
export declare const unGrammar: Grammar;
|
|
5
|
+
export declare class UnIdentifier extends BaseIdentifier {
|
|
6
|
+
static polymorphicName: string;
|
|
7
|
+
static attributes: import("../../model/attribute.js").AttributeTable;
|
|
8
|
+
static mappings: import("../../model/attribute.js").FieldMapping[];
|
|
9
|
+
readonly path: string[];
|
|
10
|
+
readonly number: string;
|
|
11
|
+
render(): string;
|
|
12
|
+
}
|
|
13
|
+
export declare function unGrammarImplementation(): FlavorImplementation;
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { match, str } from "../../grammar/engine.js";
|
|
2
|
+
import { ParseFailed, parseGrammar } from "../../grammar/engine.js";
|
|
3
|
+
import { BaseIdentifier, registerType } from "../../model/identifier.js";
|
|
4
|
+
import { extendAttributes, keyValue } from "../../model/attribute.js";
|
|
5
|
+
import { BaseBuilder } from "../../model/builder.js";
|
|
6
|
+
import { PubidDate } from "../../model/component.js";
|
|
7
|
+
/**
|
|
8
|
+
* 1:1 port of lib/pubid/un/ on the unified model. The builder derives a
|
|
9
|
+
* runtime `date` (a 4-digit path token) exactly like Ruby; un's key_value
|
|
10
|
+
* maps ONLY path/number, so the date never serializes (the mapping
|
|
11
|
+
* whitelist) while the base URN generator still reads it: the year-only
|
|
12
|
+
* render of a degenerate PubidDate yields "urn:un:<number>[:<year>]".
|
|
13
|
+
*/
|
|
14
|
+
function buildRules() {
|
|
15
|
+
const rules = {};
|
|
16
|
+
const rule = (name, build) => {
|
|
17
|
+
rules[name] = build();
|
|
18
|
+
};
|
|
19
|
+
const slash = str("/");
|
|
20
|
+
const token = match("[A-Z0-9.]").repeat(1, Infinity);
|
|
21
|
+
rule("un_prefix", () => str("UN").then(str(" ")).maybe());
|
|
22
|
+
rule("identifier", () => rules["un_prefix"]
|
|
23
|
+
.then(token.as("token"), slash.then(token.as("token")).repeat(1, Infinity)));
|
|
24
|
+
rule("root", () => rules["identifier"]);
|
|
25
|
+
return rules;
|
|
26
|
+
}
|
|
27
|
+
export const unGrammar = { rules: buildRules(), root: "root" };
|
|
28
|
+
export class UnIdentifier extends BaseIdentifier {
|
|
29
|
+
static polymorphicName = "pubid:un:document";
|
|
30
|
+
static attributes = extendAttributes(BaseIdentifier, {
|
|
31
|
+
path: { type: "string", collection: true, default: [] },
|
|
32
|
+
number: { type: "string" },
|
|
33
|
+
});
|
|
34
|
+
static mappings = keyValue({ wire: "path", to: "path" }, { wire: "number", to: "number" });
|
|
35
|
+
render() {
|
|
36
|
+
return [...this.path, this.number].join("/");
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
registerType(UnIdentifier);
|
|
40
|
+
class UnBuilder extends BaseBuilder {
|
|
41
|
+
defaultIdentifierClass() {
|
|
42
|
+
return UnIdentifier;
|
|
43
|
+
}
|
|
44
|
+
cast(key, value) {
|
|
45
|
+
if (key !== "token")
|
|
46
|
+
return value;
|
|
47
|
+
void value;
|
|
48
|
+
return null; // handled in handleKey below (needs the full token list)
|
|
49
|
+
}
|
|
50
|
+
handleKey(_identifier, key, value) {
|
|
51
|
+
return key === "token";
|
|
52
|
+
}
|
|
53
|
+
build(data) {
|
|
54
|
+
// The parslet tree is a top-level ARRAY of {token: …} hashes (the
|
|
55
|
+
// repeat-of-captures shape); extract directly — merging would
|
|
56
|
+
// collide the repeated key (Ruby's builder iterates the array too).
|
|
57
|
+
const tokens = this.extractTokens(Array.isArray(data) ? data : data["token"]);
|
|
58
|
+
if (tokens.length === 0)
|
|
59
|
+
throw new ParseFailed("UN identifier has no tokens", 0);
|
|
60
|
+
const path = tokens.slice(0, -1);
|
|
61
|
+
// Only a PATH token is the date year ("TRADE/WP.4/1068" has none —
|
|
62
|
+
// a 4-digit NUMBER is not a year).
|
|
63
|
+
const yearToken = [...path].reverse().find((t) => /^\d{4}$/.test(t));
|
|
64
|
+
const attrs = {
|
|
65
|
+
number: tokens[tokens.length - 1],
|
|
66
|
+
path,
|
|
67
|
+
};
|
|
68
|
+
if (yearToken)
|
|
69
|
+
attrs["date"] = new PubidDate({ year: yearToken });
|
|
70
|
+
return new UnIdentifier(attrs);
|
|
71
|
+
}
|
|
72
|
+
extractTokens(raw) {
|
|
73
|
+
const toStrings = (v) => Array.isArray(v)
|
|
74
|
+
? v.flatMap(toStrings)
|
|
75
|
+
: typeof v === "object" && v !== null
|
|
76
|
+
? toStrings(v["token"])
|
|
77
|
+
: v === undefined || v === null
|
|
78
|
+
? []
|
|
79
|
+
: [String(v)];
|
|
80
|
+
return toStrings(raw);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
export function unGrammarImplementation() {
|
|
84
|
+
const builder = new UnBuilder();
|
|
85
|
+
return {
|
|
86
|
+
parse(input) {
|
|
87
|
+
return builder.build(parseGrammar(unGrammar, input));
|
|
88
|
+
},
|
|
89
|
+
};
|
|
90
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Grammar } from "../../grammar/engine.js";
|
|
2
|
+
import type { FlavorImplementation } from "../../conformance/implementation.js";
|
|
3
|
+
/**
|
|
4
|
+
* 1:1 port of lib/pubid/w3c/ on the unified model. "W3C [TYPE-]slug[-date]";
|
|
5
|
+
* the grammar splits only the maturity token, the builder applies the
|
|
6
|
+
* fixed-width trailing-date split (8/6/4 digits — slugs like "url-1" or
|
|
7
|
+
* "DSIG-label-971024.html" never mis-split). Eleven kinds, one per W3C
|
|
8
|
+
* maturity level; `date` is a plain string in Ruby (never a PubidDate).
|
|
9
|
+
*/
|
|
10
|
+
declare const W3C_KINDS: readonly ["standard", "note", "draft-note", "working-draft", "candidate-recommendation", "candidate-recommendation-draft", "recommendation", "proposed-recommendation", "proposed-edited-recommendation", "superseded-recommendation", "obsolete-recommendation"];
|
|
11
|
+
export type W3cKind = (typeof W3C_KINDS)[number];
|
|
12
|
+
export declare const w3cGrammar: Grammar;
|
|
13
|
+
export declare function w3cGrammarImplementation(): FlavorImplementation;
|
|
14
|
+
export {};
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { match, str } from "../../grammar/engine.js";
|
|
2
|
+
import { ParseFailed, parseGrammar } from "../../grammar/engine.js";
|
|
3
|
+
import { BaseIdentifier, registerType } from "../../model/identifier.js";
|
|
4
|
+
import { extendAttributes, keyValue } from "../../model/attribute.js";
|
|
5
|
+
import { BaseUrnGenerator } from "../../model/urn-generator.js";
|
|
6
|
+
import { BaseBuilder } from "../../model/builder.js";
|
|
7
|
+
/**
|
|
8
|
+
* 1:1 port of lib/pubid/w3c/ on the unified model. "W3C [TYPE-]slug[-date]";
|
|
9
|
+
* the grammar splits only the maturity token, the builder applies the
|
|
10
|
+
* fixed-width trailing-date split (8/6/4 digits — slugs like "url-1" or
|
|
11
|
+
* "DSIG-label-971024.html" never mis-split). Eleven kinds, one per W3C
|
|
12
|
+
* maturity level; `date` is a plain string in Ruby (never a PubidDate).
|
|
13
|
+
*/
|
|
14
|
+
const W3C_KINDS = [
|
|
15
|
+
"standard",
|
|
16
|
+
"note",
|
|
17
|
+
"draft-note",
|
|
18
|
+
"working-draft",
|
|
19
|
+
"candidate-recommendation",
|
|
20
|
+
"candidate-recommendation-draft",
|
|
21
|
+
"recommendation",
|
|
22
|
+
"proposed-recommendation",
|
|
23
|
+
"proposed-edited-recommendation",
|
|
24
|
+
"superseded-recommendation",
|
|
25
|
+
"obsolete-recommendation",
|
|
26
|
+
];
|
|
27
|
+
// Printed token -> kind; DNOTE before NOTE, CRD before CR, PER before PR.
|
|
28
|
+
const TOKEN_KINDS = [
|
|
29
|
+
["DNOTE", "draft-note"],
|
|
30
|
+
["NOTE", "note"],
|
|
31
|
+
["WD", "working-draft"],
|
|
32
|
+
["CRD", "candidate-recommendation-draft"],
|
|
33
|
+
["CR", "candidate-recommendation"],
|
|
34
|
+
["REC", "recommendation"],
|
|
35
|
+
["PER", "proposed-edited-recommendation"],
|
|
36
|
+
["PR", "proposed-recommendation"],
|
|
37
|
+
["SPSD", "superseded-recommendation"],
|
|
38
|
+
["OBSL", "obsolete-recommendation"],
|
|
39
|
+
];
|
|
40
|
+
const KIND_TOKENS = {
|
|
41
|
+
standard: undefined,
|
|
42
|
+
note: "NOTE",
|
|
43
|
+
"draft-note": "DNOTE",
|
|
44
|
+
"working-draft": "WD",
|
|
45
|
+
"candidate-recommendation": "CR",
|
|
46
|
+
"candidate-recommendation-draft": "CRD",
|
|
47
|
+
recommendation: "REC",
|
|
48
|
+
"proposed-recommendation": "PR",
|
|
49
|
+
"proposed-edited-recommendation": "PER",
|
|
50
|
+
"superseded-recommendation": "SPSD",
|
|
51
|
+
"obsolete-recommendation": "OBSL",
|
|
52
|
+
};
|
|
53
|
+
function buildRules() {
|
|
54
|
+
const rules = {};
|
|
55
|
+
const [first, ...others] = TOKEN_KINDS;
|
|
56
|
+
const typeToken = others.reduce((acc, [token]) => acc.or(str(token)), str(first[0]));
|
|
57
|
+
ruleInit(rules, "prefix", () => str("W3C").then(str(" ")));
|
|
58
|
+
// A leading token is only a type when immediately followed by "-".
|
|
59
|
+
ruleInit(rules, "type_part", () => typeToken.as("type").then(str("-")));
|
|
60
|
+
ruleInit(rules, "rest", () => match("[\\s\\S]").repeat(1, Infinity).as("rest"));
|
|
61
|
+
ruleInit(rules, "identifier", () => rules["prefix"]
|
|
62
|
+
.then(rules["type_part"].maybe())
|
|
63
|
+
.then(rules["rest"]));
|
|
64
|
+
ruleInit(rules, "root", () => rules["identifier"]);
|
|
65
|
+
return rules;
|
|
66
|
+
}
|
|
67
|
+
function ruleInit(rules, name, build) {
|
|
68
|
+
rules[name] = build();
|
|
69
|
+
}
|
|
70
|
+
export const w3cGrammar = { rules: buildRules(), root: "root" };
|
|
71
|
+
const KIND_CLASSES = {};
|
|
72
|
+
function w3cClass(kind) {
|
|
73
|
+
const token = KIND_TOKENS[kind];
|
|
74
|
+
class W3cKindIdentifier extends BaseIdentifier {
|
|
75
|
+
static polymorphicName = `pubid:w3c:${kind}`;
|
|
76
|
+
static attributes = extendAttributes(BaseIdentifier, {
|
|
77
|
+
number: { type: "string" },
|
|
78
|
+
date: { type: "string" },
|
|
79
|
+
});
|
|
80
|
+
static mappings = keyValue({ wire: "number", to: "number" }, { wire: "date", to: "date" });
|
|
81
|
+
render() {
|
|
82
|
+
let body = token === undefined ? "" : `${token}-`;
|
|
83
|
+
body += this.number;
|
|
84
|
+
if (this.date !== undefined)
|
|
85
|
+
body += `-${this.date}`;
|
|
86
|
+
return `W3C ${body}`;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
registerType(W3cKindIdentifier);
|
|
90
|
+
return W3cKindIdentifier;
|
|
91
|
+
}
|
|
92
|
+
for (const kind of W3C_KINDS) {
|
|
93
|
+
KIND_CLASSES[kind] = w3cClass(kind);
|
|
94
|
+
}
|
|
95
|
+
class W3cUrnGenerator extends BaseUrnGenerator {
|
|
96
|
+
generate() {
|
|
97
|
+
const id = this.identifier;
|
|
98
|
+
const kind = (this.identifier.constructor.polymorphicName.slice("pubid:w3c:".length));
|
|
99
|
+
const parts = ["urn", "w3c"];
|
|
100
|
+
const token = KIND_TOKENS[kind];
|
|
101
|
+
if (token !== undefined)
|
|
102
|
+
parts.push(token.toLowerCase());
|
|
103
|
+
parts.push(id.number);
|
|
104
|
+
if (id.date !== undefined)
|
|
105
|
+
parts.push(id.date);
|
|
106
|
+
return parts.join(":");
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
for (const kind of W3C_KINDS) {
|
|
110
|
+
KIND_CLASSES[kind].urnGenerator = W3cUrnGenerator;
|
|
111
|
+
}
|
|
112
|
+
const DATE_RE = /^(.+)-(\d{8}|\d{6}|\d{4})$/;
|
|
113
|
+
function kindForToken(token) {
|
|
114
|
+
if (token === undefined)
|
|
115
|
+
return "standard";
|
|
116
|
+
const entry = TOKEN_KINDS.find(([t]) => t === token);
|
|
117
|
+
if (!entry)
|
|
118
|
+
throw new ParseFailed(`W3C: unknown type token ${token}`, 0);
|
|
119
|
+
return entry[1];
|
|
120
|
+
}
|
|
121
|
+
class W3cBuilder extends BaseBuilder {
|
|
122
|
+
selectClass(data) {
|
|
123
|
+
const type = data["type"];
|
|
124
|
+
return KIND_CLASSES[kindForToken(type === undefined || type === null ? undefined : String(type))];
|
|
125
|
+
}
|
|
126
|
+
defaultIdentifierClass() {
|
|
127
|
+
return KIND_CLASSES["standard"];
|
|
128
|
+
}
|
|
129
|
+
cast(key, value) {
|
|
130
|
+
if (key !== "rest")
|
|
131
|
+
return value;
|
|
132
|
+
const rest = String(value);
|
|
133
|
+
const m = DATE_RE.exec(rest);
|
|
134
|
+
return m ? { number: m[1], date: m[2] } : { number: rest };
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
export function w3cGrammarImplementation() {
|
|
138
|
+
const builder = new W3cBuilder();
|
|
139
|
+
return {
|
|
140
|
+
parse(input) {
|
|
141
|
+
const tree = parseGrammar(w3cGrammar, input);
|
|
142
|
+
if (typeof tree !== "object" || tree === null || Array.isArray(tree)) {
|
|
143
|
+
throw new ParseFailed("W3C: unexpected parse tree", 0);
|
|
144
|
+
}
|
|
145
|
+
return builder.build(tree);
|
|
146
|
+
},
|
|
147
|
+
};
|
|
148
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Grammar } from "../../grammar/engine.js";
|
|
2
|
+
import type { FlavorImplementation } from "../../conformance/implementation.js";
|
|
3
|
+
import { BaseIdentifier } from "../../model/identifier.js";
|
|
4
|
+
import { BaseUrnGenerator } from "../../model/urn-generator.js";
|
|
5
|
+
export declare const xsfGrammar: Grammar;
|
|
6
|
+
declare class XsfUrnGenerator extends BaseUrnGenerator<XsfIdentifier> {
|
|
7
|
+
generate(): string;
|
|
8
|
+
}
|
|
9
|
+
export declare class XsfIdentifier extends BaseIdentifier {
|
|
10
|
+
static polymorphicName: string;
|
|
11
|
+
static attributes: import("../../model/attribute.js").AttributeTable;
|
|
12
|
+
static mappings: import("../../model/attribute.js").FieldMapping[];
|
|
13
|
+
static urnGenerator: typeof XsfUrnGenerator;
|
|
14
|
+
readonly number: string;
|
|
15
|
+
render(): string;
|
|
16
|
+
}
|
|
17
|
+
export declare function xsfGrammarImplementation(): FlavorImplementation;
|
|
18
|
+
export {};
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { match, str } from "../../grammar/engine.js";
|
|
2
|
+
import { ParseFailed, parseGrammar } from "../../grammar/engine.js";
|
|
3
|
+
import { BaseIdentifier, registerType } from "../../model/identifier.js";
|
|
4
|
+
import { extendAttributes, keyValue } from "../../model/attribute.js";
|
|
5
|
+
import { BaseUrnGenerator } from "../../model/urn-generator.js";
|
|
6
|
+
import { BaseBuilder } from "../../model/builder.js";
|
|
7
|
+
/**
|
|
8
|
+
* 1:1 port of lib/pubid/xsf/ on the unified model. XEP numbers, plus the
|
|
9
|
+
* two named documents ("XEP README", "XEP xxxx") kept verbatim. URN:
|
|
10
|
+
* urn:xsf:xep:<number> (the Ruby flavor's own generator).
|
|
11
|
+
*/
|
|
12
|
+
// The editor README and the xep-xxxx template reach pubid as real
|
|
13
|
+
// primary docids.
|
|
14
|
+
const SPECIAL_NUMBERS = ["README", "xxxx"];
|
|
15
|
+
function buildRules() {
|
|
16
|
+
const rules = {};
|
|
17
|
+
const rule = (name, build) => {
|
|
18
|
+
rules[name] = build();
|
|
19
|
+
};
|
|
20
|
+
const specialNumber = SPECIAL_NUMBERS.map((name) => str(name)).reduce((a, b) => a.or(b));
|
|
21
|
+
rule("special_number", () => specialNumber);
|
|
22
|
+
const digits = match("[0-9]").repeat(1, Infinity);
|
|
23
|
+
rule("digits", () => digits);
|
|
24
|
+
rule("identifier", () => str("XEP").then(str(" "), digits.or(specialNumber).as("number")));
|
|
25
|
+
rule("root", () => rules["identifier"]);
|
|
26
|
+
return rules;
|
|
27
|
+
}
|
|
28
|
+
export const xsfGrammar = {
|
|
29
|
+
rules: buildRules(),
|
|
30
|
+
root: "root",
|
|
31
|
+
};
|
|
32
|
+
class XsfUrnGenerator extends BaseUrnGenerator {
|
|
33
|
+
generate() {
|
|
34
|
+
return ["urn", "xsf", "xep", this.identifier.number].join(":");
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
export class XsfIdentifier extends BaseIdentifier {
|
|
38
|
+
static polymorphicName = "pubid:xsf:xep";
|
|
39
|
+
static attributes = extendAttributes(BaseIdentifier, {
|
|
40
|
+
number: { type: "string" },
|
|
41
|
+
});
|
|
42
|
+
static mappings = keyValue({ wire: "number", to: "number" });
|
|
43
|
+
static urnGenerator = XsfUrnGenerator;
|
|
44
|
+
render() {
|
|
45
|
+
return `XEP ${this.number}`;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
registerType(XsfIdentifier);
|
|
49
|
+
class XsfBuilder extends BaseBuilder {
|
|
50
|
+
defaultIdentifierClass() {
|
|
51
|
+
return XsfIdentifier;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
export function xsfGrammarImplementation() {
|
|
55
|
+
const builder = new XsfBuilder();
|
|
56
|
+
return {
|
|
57
|
+
parse(input) {
|
|
58
|
+
const tree = parseGrammar(xsfGrammar, input);
|
|
59
|
+
if (typeof tree !== "object" || tree === null || Array.isArray(tree)) {
|
|
60
|
+
throw new ParseFailed("XSF: unexpected parse tree", 0);
|
|
61
|
+
}
|
|
62
|
+
return builder.build(tree);
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A parslet-compatible parser-combinator engine.
|
|
3
|
+
*
|
|
4
|
+
* The Ruby pubid grammars are declarative parslet rule trees; porting a
|
|
5
|
+
* flavor 1:1 requires the TypeScript engine to reproduce parslet's tree
|
|
6
|
+
* semantics exactly, because the Ruby builders read those trees. The
|
|
7
|
+
* semantics below were pinned empirically against parslet 2.0 (see the
|
|
8
|
+
* porting guide in docs/PORTING.md):
|
|
9
|
+
*
|
|
10
|
+
* - atoms produce a string, a capture hash, an array, or nil
|
|
11
|
+
* - sequences fold with `combine`: string+string concat; a plain string
|
|
12
|
+
* is DISCARDED when combined with a capture; hash+hash merges and a
|
|
13
|
+
* duplicate key raises; nil is transparent
|
|
14
|
+
* - `.as(key)` wraps the result: {key: result}
|
|
15
|
+
* - `.repeat` is greedy and does NOT backtrack a successful iteration to
|
|
16
|
+
* satisfy an outer minimum (parslet: "Expected at least N of ...");
|
|
17
|
+
* results are an array when any iteration captured, else a concat string
|
|
18
|
+
* - `.maybe` is special-cased like parslet's Maybe: one attempt, nil on
|
|
19
|
+
* failure (not an empty array)
|
|
20
|
+
* - `absent?`/`present?` are zero-width lookaheads
|
|
21
|
+
* - full input consumption is enforced the way parslet 2.0 does it: a
|
|
22
|
+
* `consumeAll` flag is threaded down the parse spine — the root starts
|
|
23
|
+
* with it, a Sequence hands it ONLY to its last child, Alternatives
|
|
24
|
+
* pass it to every branch, and Repetition iterations never get it. An
|
|
25
|
+
* atom that succeeds while unconsumed input remains FAILS (parslet
|
|
26
|
+
* Base#apply's "Don't know what to do with ..." check). Because that
|
|
27
|
+
* failure is an ordinary match failure, an enclosing Alternative
|
|
28
|
+
* retries its next branch — so `a | b` DOES re-try `b` when `a`
|
|
29
|
+
* matched but left trailing input (pinned against parslet: bare
|
|
30
|
+
* "080442957X" reaches ISBN's second body alternative this way).
|
|
31
|
+
*/
|
|
32
|
+
export declare class ParseFailed extends Error {
|
|
33
|
+
readonly pos: number;
|
|
34
|
+
constructor(message: string, pos: number);
|
|
35
|
+
}
|
|
36
|
+
export type Tree = string | number | TreeObject | Tree[] | null | undefined;
|
|
37
|
+
export interface TreeObject {
|
|
38
|
+
[key: string]: Tree;
|
|
39
|
+
}
|
|
40
|
+
/** Context threaded through every match attempt. */
|
|
41
|
+
declare class Ctx {
|
|
42
|
+
input: string;
|
|
43
|
+
pos: number;
|
|
44
|
+
constructor(input: string);
|
|
45
|
+
}
|
|
46
|
+
export interface Atom {
|
|
47
|
+
/** Attempt a match at ctx.pos; failure throws Fail. */
|
|
48
|
+
_match(ctx: Ctx, consumeAll: boolean): Tree | undefined;
|
|
49
|
+
}
|
|
50
|
+
/** Builder-side sugar: chainable wrapper. */
|
|
51
|
+
export declare class P {
|
|
52
|
+
readonly atom: Atom;
|
|
53
|
+
constructor(atom: Atom);
|
|
54
|
+
then(...next: (P | Atom)[]): P;
|
|
55
|
+
or(...others: (P | Atom)[]): P;
|
|
56
|
+
repeat(min?: number, max?: number): P;
|
|
57
|
+
maybe(): P;
|
|
58
|
+
as(key: string): P;
|
|
59
|
+
absent(): P;
|
|
60
|
+
present(): P;
|
|
61
|
+
}
|
|
62
|
+
export declare function unwrap(p: P | Atom): Atom;
|
|
63
|
+
export declare function str(s: string): P;
|
|
64
|
+
/** parslet's match: a single-character regex match, e.g. match("[a-z]"). */
|
|
65
|
+
export declare function match(pattern: string): P;
|
|
66
|
+
/** A named rule reference (lazily resolved — grammars are recursive). */
|
|
67
|
+
export declare function ref(rules: Record<string, P | Atom>, name: string): P;
|
|
68
|
+
export interface Grammar {
|
|
69
|
+
rules: Record<string, P | Atom>;
|
|
70
|
+
root: string;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Parse the whole input with the grammar's root rule, parslet-style:
|
|
74
|
+
* full consumption is enforced by the root's consumeAll flag, so an
|
|
75
|
+
* Alternative at the spine retries a branch that left trailing input.
|
|
76
|
+
*/
|
|
77
|
+
export declare function parseGrammar(grammar: Grammar, input: string): Tree;
|
|
78
|
+
export {};
|