60 lines
2.1 KiB
TypeScript
60 lines
2.1 KiB
TypeScript
import { Rule } from "./rule.ts";
|
|
import { PairElts, StructOfArr } from "./types.ts";
|
|
import { Extractor } from "./extractor.ts"
|
|
import { split_once } from "./utils.ts";
|
|
|
|
export function extr<A extends string[]>(...args: A): Extractor<StructOfArr<PairElts<A>, string>> {
|
|
const seps = [] as string[];
|
|
const vars = [] as string[];
|
|
|
|
let pair = true;
|
|
for (const arg of args) {
|
|
if (pair) seps.push(arg);
|
|
else vars.push(arg);
|
|
pair = !pair;
|
|
}
|
|
|
|
const vars_ = vars as PairElts<A>;
|
|
const rule = new Rule(seps, vars_);
|
|
return new Extractor(text => rule.get(text))
|
|
}
|
|
|
|
Deno.test("extr_types", async () => {
|
|
const { assertEquals } = await import("https://deno.land/std@0.224.0/assert/assert_equals.ts");
|
|
const vars = extr()
|
|
.or(extr("bonjour, ", 'animal', ", poilu"))
|
|
.or(extr("bonjour, ", 'arbre', ", feuillu"))
|
|
.get("bonjour, le chêne, feuillu");
|
|
assertEquals({ vars }, { vars: { "arbre": "le chêne" } })
|
|
})
|
|
|
|
type ArrForDef<D extends string> =
|
|
D extends "" ? [] :
|
|
D extends `${infer W extends string}{{${infer V extends string}}}${infer R extends string}` ? [W, V, ...ArrForDef<R>] :
|
|
D extends `${infer W extends string}` ? [W] :
|
|
never;
|
|
|
|
export function def<D extends string>(def: D): Extractor<StructOfArr<PairElts<ArrForDef<D>>, string>> {
|
|
const result = [] as string[];
|
|
let rest = def as string;
|
|
while (true) {
|
|
const [word, var_rest] = split_once(rest, "{{");
|
|
if (var_rest === null) break;
|
|
const [var_, rest_] = split_once(var_rest, "}}");
|
|
if (rest_ === null) throw new Error(`Invalid rule near '${rest}'`);
|
|
result.push(word, var_);
|
|
rest = rest_;
|
|
}
|
|
if (rest.length > 0) result.push(rest);
|
|
const args = result as ArrForDef<D>;
|
|
return extr(...args);
|
|
}
|
|
|
|
Deno.test("def_types", async () => {
|
|
const { assertEquals } = await import("https://deno.land/std@0.224.0/assert/assert_equals.ts");
|
|
const vars = extr()
|
|
.or(def("bonjour, {{animal}}, poilu"))
|
|
.or(def("bonjour, {{arbre}}, feuillu"))
|
|
.get("bonjour, le chêne, feuillu");
|
|
assertEquals({ vars }, { vars: { "arbre": "le chêne" } })
|
|
})
|