Skip to content

Commit 82c47f9

Browse files
committed
Parser
1 parent 73855ea commit 82c47f9

File tree

1 file changed

+112
-0
lines changed

1 file changed

+112
-0
lines changed

src/build/utils/kdl.ts

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
import { parse } from "kdljs";
2+
import { Enum, Event, Method, Property } from "../types";
3+
import { readFile } from "fs/promises";
4+
5+
interface MethodDescriptor {
6+
[x: string]: Omit<Method, "signature">;
7+
}
8+
9+
interface EnumDescriptor {
10+
[x: string]: Enum;
11+
}
12+
interface PropertyDescriptor {
13+
[x: string]: Omit<Property, "type">;
14+
}
15+
16+
interface InterfaceMixin {
17+
[x: string]: {
18+
events?: { event: Event[] };
19+
methods?: { method: MethodDescriptor };
20+
};
21+
}
22+
23+
/**
24+
* Converts KDL text describing interface-mixins into JSON format.
25+
* Uses kdljs v3.
26+
*/
27+
export function parseKDL(kdlText: string) {
28+
const { output, errors } = parse(kdlText);
29+
30+
if (errors.length) {
31+
throw new Error(
32+
`KDL parse errors:\n${errors.map((e) => e.message).join("\n")}`,
33+
);
34+
}
35+
36+
const nodes = output!;
37+
const enums: EnumDescriptor = {};
38+
const interfaces: InterfaceMixin = {};
39+
40+
for (const node of nodes) {
41+
if (node.name === "enum") {
42+
// Handle enum
43+
const enumName = node.values?.[0]?.toString() ?? "";
44+
let name = enumName;
45+
const values: string[] = [];
46+
47+
for (const child of node.children ?? []) {
48+
if (
49+
child.name === "value" &&
50+
child.values &&
51+
child.values[0] !== undefined
52+
) {
53+
values.push(child.values[0]!.toString());
54+
} else if (child.name === "name") {
55+
name = child.values?.[0]?.toString() ?? enumName;
56+
}
57+
}
58+
59+
enums[enumName] = { name, value: values };
60+
} else {
61+
// Handle interface-mixin
62+
const name = node.values?.[0]?.toString() ?? "";
63+
const iface: {
64+
events?: { event: Event[] };
65+
methods?: { method: MethodDescriptor };
66+
properties?: { property: PropertyDescriptor };
67+
} = {};
68+
69+
const events: Event[] = [];
70+
const methods: MethodDescriptor = {};
71+
const properties: PropertyDescriptor = {};
72+
73+
for (const child of node.children ?? []) {
74+
const name = child.values?.[0]?.toString() ?? "";
75+
if (child.name === "event") {
76+
events.push({
77+
name,
78+
type: child.properties?.type?.toString() ?? "",
79+
});
80+
} else if (child.name === "method") {
81+
methods[name] = {
82+
name,
83+
overrideSignatures: [
84+
child.properties?.overrideSignatures?.toString() ?? "",
85+
],
86+
};
87+
} else if (child.name === "property") {
88+
properties[name] = {
89+
name,
90+
exposed: child.properties?.exposed?.toString(),
91+
};
92+
}
93+
}
94+
95+
if (events.length) iface.events = { event: events };
96+
if (Object.keys(methods).length) iface.methods = { method: methods };
97+
if (Object.keys(properties).length)
98+
iface.properties = { property: properties };
99+
100+
interfaces[name] = iface;
101+
}
102+
}
103+
104+
return { mixins: { mixin: interfaces }, enums: { enum: enums } };
105+
}
106+
export default async function readInputKDL(
107+
path: string,
108+
inputFolder: string,
109+
): Promise<any> {
110+
const text = await readFile(new URL(path, inputFolder), "utf8");
111+
return parseKDL(text);
112+
}

0 commit comments

Comments
 (0)