fauton
Version:
A library to test any finite automaton with arbitrary alphabets
101 lines (100 loc) • 5.12 kB
JavaScript
;
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;