UNPKG

fuzzy-rater

Version:

Tooling for fuzzily rating text according to some query

180 lines 14.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.NFA = exports.emptyCode = void 0; const DFA_1 = require("../DFA"); exports.emptyCode = "et"; /** * A class to represent non-deterministic finite automata and their operations */ class NFA { /** * Creates a new nfa according to the given specification * @param template The nfa template */ constructor(template) { this.initialize(template); } /** * Retrieves the character code of a given transition * @param transition The transition to get a code for the transition character for * @returns The character code */ getCharacterCode(transition) { return transition.type == "character" && transition.character ? transition.character : transition.type == "empty" ? exports.emptyCode : DFA_1.remainingCode; } /** * Initializes the NFA structure * @param template The NFA template */ initialize(template) { // Map each node to an index, since node IDs can be very long and therefore inefficient const nodeMap = new Map(template.map((node, i) => [node.ID, i])); this.nodes = template; this.transitions = template.map((node, i) => Object.fromEntries(node.transitions.reduce((cur, trans) => { const char = this.getCharacterCode(trans); const group = cur.find(([i]) => i == char); const node = nodeMap.get(trans.to); if (group) { group[1].push(node); return cur; } else { return [...cur, [char, [node]]]; } }, []))); // Extra data to perform a faster traced search this.traceTransitions = template.map((node, i) => Object.fromEntries(node.transitions.reduce((cur, trans) => { const char = this.getCharacterCode(trans); const group = cur.find(([i]) => i == char); const node = nodeMap.get(trans.to); if (group) { group[1].push({ state: node, metadata: trans.metadata }); return cur; } else { return [ ...cur, [char, [{ state: node, metadata: trans.metadata }]], ]; } }, []))); // Get all the initial states, following empty transitions const initial = template .filter(node => node.initial) .map(node => nodeMap.get(node.ID)) .filter((node) => node !== undefined); if (initial.length == 0) throw Error("Initial state can't be found"); this.initial = initial; } /** * Executes the NFA on the given input, and returns the metadata of the final node, if any * @param input The input to execute the NFA on * @returns The metadata of the states teh automaton finished in */ execute(input) { let state = this.followEmptyTransitions(this.initial); // Step through all characters for (let i = 0; i < input.length; i++) { const char = input[i]; const newState = []; state.forEach(s => { const transitions = this.transitions[s]; const charTrans = transitions[char]; let trans; if (charTrans) trans = charTrans; else trans = transitions[DFA_1.remainingCode] || []; trans.forEach(t => { if (!newState.includes(t)) newState.push(t); }); }); state = this.followEmptyTransitions(newState); } // Return the result return state.map(s => this.nodes[s].metadata); } /** * Follows empty transitions from a node, and adds * @param nodes The indices of the nodes for which to follow the empty transitions * @returns The indices of all nodes reachable in 0 steps */ followEmptyTransitions(nodes) { var _a; const reachable = [...nodes]; for (let i = 0; i < reachable.length; i++) { const node = reachable[i]; ((_a = this.transitions[node][exports.emptyCode]) !== null && _a !== void 0 ? _a : []).forEach(nextNode => { if (!reachable.includes(nextNode)) reachable.push(nextNode); }); } return reachable; } /** * Executes the NFA on the given input, and returns the metadata of the trace. * If multiple paths to the same final state exist, only a single path is returned * @param input The input to execute the NFA on * @returns The metadata of the states teh automaton finished in */ executeTraced(input) { let state = this.initial.map(node => ({ node, path: [] })); // Step through all characters for (let i = 0; i < input.length; i++) { const char = input[i]; const newState = []; state.forEach(({ node, path }) => { const transitions = this.traceTransitions[node]; const charTrans = transitions[char]; let trans; if (charTrans) trans = charTrans; else trans = transitions[DFA_1.remainingCode] || []; trans.forEach(({ state, metadata }) => { newState.push({ node: state, path: [...path, { node, transition: metadata }], }); }); }); state = this.followEmptyTransitionsTraced(newState); } // Return the result return state.map(({ node, path }) => ({ final: this.nodes[node].metadata, path: path.map(({ node, transition }) => ({ fromNode: this.nodes[node].metadata, transition, })), })); } /** * Follows empty transitions from a node, and adds * @param nodes The indices of the nodes for which to follow the empty transitions * @returns The indices of all nodes reachable in 0 steps */ followEmptyTransitionsTraced(nodes) { var _a; const reachable = [...nodes]; for (let i = 0; i < reachable.length; i++) { const { node, path } = reachable[i]; ((_a = this.traceTransitions[node][exports.emptyCode]) !== null && _a !== void 0 ? _a : []).forEach(({ state, metadata }) => { if (!reachable.find(({ node }) => node == state)) reachable.push({ node: state, path: [...path, { node, transition: metadata }], }); }); } return reachable; } } exports.NFA = NFA; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiTkZBLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL05GQS9ORkEudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBSUEsZ0NBQXFDO0FBRXhCLFFBQUEsU0FBUyxHQUFHLElBQUksQ0FBQztBQUU5Qjs7R0FFRztBQUNILE1BQWEsR0FBRztJQU9aOzs7T0FHRztJQUNILFlBQW1CLFFBQXNDO1FBQ3JELElBQUksQ0FBQyxVQUFVLENBQUMsUUFBUSxDQUFDLENBQUM7SUFDOUIsQ0FBQztJQUVEOzs7O09BSUc7SUFDTyxnQkFBZ0IsQ0FBQyxVQUF1QztRQUM5RCxPQUFPLFVBQVUsQ0FBQyxJQUFJLElBQUksV0FBVyxJQUFJLFVBQVUsQ0FBQyxTQUFTO1lBQ3pELENBQUMsQ0FBQyxVQUFVLENBQUMsU0FBUztZQUN0QixDQUFDLENBQUMsVUFBVSxDQUFDLElBQUksSUFBSSxPQUFPO2dCQUM1QixDQUFDLENBQUMsaUJBQVM7Z0JBQ1gsQ0FBQyxDQUFDLG1CQUFhLENBQUM7SUFDeEIsQ0FBQztJQUVEOzs7T0FHRztJQUNPLFVBQVUsQ0FBQyxRQUFzQztRQUN2RCx1RkFBdUY7UUFDdkYsTUFBTSxPQUFPLEdBQUcsSUFBSSxHQUFHLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxDQUFDLElBQUksRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsSUFBSSxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFFakUsSUFBSSxDQUFDLEtBQUssR0FBRyxRQUFRLENBQUM7UUFDdEIsSUFBSSxDQUFDLFdBQVcsR0FBRyxRQUFRLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxFQUFFLENBQUMsRUFBRSxFQUFFLENBQ3hDLE1BQU0sQ0FBQyxXQUFXLENBQ2QsSUFBSSxDQUFDLFdBQVcsQ0FBQyxNQUFNLENBQUMsQ0FBQyxHQUFHLEVBQUUsS0FBSyxFQUFFLEVBQUU7WUFDbkMsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLGdC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