Stub out Idv parser

This commit is contained in:
Tangent 2024-07-07 21:00:20 -04:00
parent a2df9a4142
commit e90727a06c
4 changed files with 118 additions and 1 deletions

72
lib/idv.ts Normal file
View 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");