UNPKG

fauton

Version:

A library to test any finite automaton with arbitrary alphabets

101 lines (100 loc) 5.12 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.merge = void 0; function merge(sourceAutomaton, targetAutomaton, mergeOperation, generatedAutomatonOptions) { const { separator = '.', label, description, } = generatedAutomatonOptions ?? {}; const sourceAutomatonFinalStates = new Set(sourceAutomaton.automaton.final_states); const targetAutomatonFinalStates = new Set(targetAutomaton ? targetAutomaton.automaton.final_states : []); const newStates = []; const newTransitions = {}; const newFinalStates = new Set(); const isComposite = targetAutomaton && targetAutomaton.automatonId !== sourceAutomaton.automatonId; const newDfaId = isComposite ? sourceAutomaton.automatonId + separator + targetAutomaton.automatonId : sourceAutomaton.automatonId; const newStartState = isComposite ? sourceAutomaton.automaton.start_state + separator + targetAutomaton.automaton.start_state : sourceAutomaton.automaton.start_state; function inner(targetAutomatonState) { sourceAutomaton.automaton.states.forEach((sourceAutomatonState) => { const newState = isComposite ? `${sourceAutomatonState}${separator}${targetAutomatonState}` : sourceAutomatonState; if (isComposite && targetAutomatonState) { newStates.push(newState); newTransitions[newState] = {}; sourceAutomaton.automaton.alphabets.forEach((symbol) => { newTransitions[newState][symbol] = [ sourceAutomaton.automaton.transitions[sourceAutomatonState][symbol] + separator + targetAutomaton.automaton.transitions[targetAutomatonState][symbol], ]; }); if (mergeOperation === 'or' && (targetAutomatonFinalStates.has(targetAutomatonState) || sourceAutomatonFinalStates.has(sourceAutomatonState))) { newFinalStates.add(newState); } else if (mergeOperation === 'and' && targetAutomatonFinalStates.has(targetAutomatonState) && sourceAutomatonFinalStates.has(sourceAutomatonState)) { newFinalStates.add(newState); } } else if (mergeOperation === 'or' && (targetAutomatonFinalStates.has(newState) || sourceAutomatonFinalStates.has(newState))) { newFinalStates.add(newState); } else if (mergeOperation === 'and' && targetAutomatonFinalStates.has(newState) && sourceAutomatonFinalStates.has(newState)) { newFinalStates.add(newState); } else if (mergeOperation === 'not' && !sourceAutomatonFinalStates.has(newState)) { newFinalStates.add(newState); } }); } if (targetAutomaton) { targetAutomaton.automaton.states.forEach((targetAutomatonState) => { inner(targetAutomatonState); }); } else { inner(); } return { testLogic: (inputString, automatonTestResult) => { if (mergeOperation === 'or') { return (targetAutomaton.testLogic(inputString, automatonTestResult) || sourceAutomaton.testLogic(inputString, automatonTestResult)); } if (mergeOperation === 'and') { return (targetAutomaton.testLogic(inputString, automatonTestResult) && sourceAutomaton.testLogic(inputString, automatonTestResult)); } return !sourceAutomaton.testLogic(inputString, automatonTestResult); }, automaton: { final_states: Array.from(newFinalStates), label: label ?? `${mergeOperation}(` + `${sourceAutomaton.automaton.label}${mergeOperation !== 'not' ? ', ' : ''}${targetAutomaton ? targetAutomaton.automaton.label : ''}` + `)`, description: description ?? `${mergeOperation.toUpperCase()}(` + `${sourceAutomaton.automaton.description}${mergeOperation !== 'not' ? ', ' : ''}${targetAutomaton ? targetAutomaton.automaton.description : ''}` + `)`, start_state: isComposite ? newStartState : sourceAutomaton.automaton.start_state, states: isComposite ? newStates : [...sourceAutomaton.automaton.states], transitions: (isComposite ? newTransitions : JSON.parse(JSON.stringify(sourceAutomaton.automaton.transitions))), alphabets: sourceAutomaton.automaton.alphabets, epsilon_transitions: null, }, automatonId: isComposite ? newDfaId : sourceAutomaton.automatonId, }; } exports.merge = merge;