Stub out Idv parser
This commit is contained in:
parent
a2df9a4142
commit
e90727a06c
4 changed files with 118 additions and 1 deletions
|
@ -6,6 +6,7 @@
|
|||
<script src="js/debug.js"></script>
|
||||
<script>
|
||||
document.body.append(...TickDebug());
|
||||
document.body.append(...IdvDebug());
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
3
debug.ts
3
debug.ts
|
@ -1,3 +1,4 @@
|
|||
import { TickDebug } from "./debug/tick";
|
||||
import { IdvDebug } from "./debug/idv";
|
||||
|
||||
Object.assign(globalThis, { TickDebug });
|
||||
Object.assign(globalThis, { TickDebug, IdvDebug });
|
||||
|
|
43
debug/idv.ts
Normal file
43
debug/idv.ts
Normal file
|
@ -0,0 +1,43 @@
|
|||
import { h } from "../lib/html";
|
||||
import { Idv, StringFromDocument } from "../lib/idv";
|
||||
|
||||
export function IdvDebug() {
|
||||
const textarea = h(
|
||||
"textarea",
|
||||
{
|
||||
cols: 80,
|
||||
rows: 40,
|
||||
oninput(ev) {
|
||||
parse();
|
||||
},
|
||||
},
|
||||
`# Idv Testing Ground
|
||||
Uid: 0
|
||||
Shell: tclsh
|
||||
Group: users
|
||||
Group: sudo
|
||||
`
|
||||
);
|
||||
|
||||
const pre = h("pre");
|
||||
|
||||
function parse() {
|
||||
try {
|
||||
const idv = Idv.parse(textarea.value);
|
||||
|
||||
pre.textContent = JSON.stringify(
|
||||
{
|
||||
shell: idv.getProperty("Shell", String, StringFromDocument),
|
||||
groups: idv.getList("Group", String, StringFromDocument),
|
||||
},
|
||||
null,
|
||||
2
|
||||
);
|
||||
} catch (e) {
|
||||
pre.textContent = String(e);
|
||||
}
|
||||
}
|
||||
parse();
|
||||
|
||||
return [textarea, pre];
|
||||
}
|
72
lib/idv.ts
Normal file
72
lib/idv.ts
Normal file
|
@ -0,0 +1,72 @@
|
|||
export type DistinguisherParser<T> = (distinguisher: string) => T;
|
||||
export type DocumentParser<T> = (document: string[]) => T;
|
||||
|
||||
const LEADING_WHITESPACE = /^([ \t]+)/;
|
||||
const ENTRY = /^(.+?):\s*(.*)/;
|
||||
|
||||
export class Idv {
|
||||
collections: Record<string, undefined | [string, string[]][]> = {};
|
||||
|
||||
public static parse(input: string): Idv {
|
||||
const lines = input.split("\n").map((line) => line.trimEnd());
|
||||
return Idv.parseLines(lines);
|
||||
}
|
||||
static parseLines(input: string[]): Idv {
|
||||
const idv = new Idv();
|
||||
let currentDocument: string[] = [];
|
||||
|
||||
input.forEach((line) => {
|
||||
const indent = LEADING_WHITESPACE.exec(line)?.[1];
|
||||
if (indent) {
|
||||
// TODO
|
||||
} else if (line == "") {
|
||||
// TODO
|
||||
} else if (line[0] == "#") {
|
||||
// skip
|
||||
} else {
|
||||
const matches = ENTRY.exec(line);
|
||||
if (matches) {
|
||||
const [, collection, distinguisher] = matches;
|
||||
|
||||
if (idv.collections[collection] == undefined) {
|
||||
idv.collections[collection] = [];
|
||||
}
|
||||
|
||||
currentDocument = [];
|
||||
idv.collections[collection].push([distinguisher, currentDocument]);
|
||||
} else {
|
||||
throw new Error("Failed to parse a property");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return idv;
|
||||
}
|
||||
|
||||
public getProperty<T>(
|
||||
name: string,
|
||||
parseDistinguisher: DistinguisherParser<T>,
|
||||
parseDocument: DocumentParser<T>
|
||||
): T | null {
|
||||
const firstEntry = this.collections[name]?.[0];
|
||||
return firstEntry && firstEntry[1].length > 0
|
||||
? parseDocument(firstEntry[1])
|
||||
: firstEntry?.[0]
|
||||
? parseDistinguisher(firstEntry[0])
|
||||
: null;
|
||||
}
|
||||
|
||||
public getList<T>(
|
||||
name: string,
|
||||
parseDistinguisher: DistinguisherParser<T>,
|
||||
parseDocument: DocumentParser<T>
|
||||
): T[] {
|
||||
return (this.collections[name] ?? []).map(([distinguisher, document]) =>
|
||||
document.length > 0
|
||||
? parseDocument(document)
|
||||
: parseDistinguisher(distinguisher)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export const StringFromDocument = (lines: string[]) => lines.join("\n");
|
Loading…
Add table
Reference in a new issue