fauton
Version:
A library to test any finite automaton with arbitrary alphabets
88 lines (87 loc) • 4.79 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.normalize = void 0;
const utils_1 = require("../../../utils");
function expandCharacterRangesForArray(characterRanges, appendedString) {
const uniqueSymbols = new Set();
characterRanges.forEach((characterRange) => {
(0, utils_1.expandCharacterRanges)(characterRange.toString()).forEach((expandedCharacterRange) => {
uniqueSymbols.add((appendedString ?? '') + expandedCharacterRange);
});
});
return Array.from(uniqueSymbols);
}
function normalize(finiteAutomaton) {
const appendedString = finiteAutomaton.append ?? '';
if (appendedString) {
delete finiteAutomaton.append;
}
finiteAutomaton.final_states = expandCharacterRangesForArray(finiteAutomaton.final_states, appendedString);
finiteAutomaton.alphabets = expandCharacterRangesForArray(finiteAutomaton.alphabets);
finiteAutomaton.states = expandCharacterRangesForArray(finiteAutomaton.states, appendedString);
finiteAutomaton.start_state = appendedString + finiteAutomaton.start_state.toString();
if (finiteAutomaton.epsilon_transitions) {
Object.entries(finiteAutomaton.epsilon_transitions).forEach(([epsilonTransitionStartState, epsilonTransitionTargetStates]) => {
const newEpsilonTransitionTargetStates = new Set();
epsilonTransitionTargetStates.forEach((epsilonTransitionTargetState) => {
(0, utils_1.expandCharacterRanges)(epsilonTransitionTargetState.toString()).forEach((stateString) => {
newEpsilonTransitionTargetStates.add(stateString.toString());
});
});
finiteAutomaton.epsilon_transitions[epsilonTransitionStartState] = Array.from(newEpsilonTransitionTargetStates);
});
}
function attachToStateRecord(transitionStateRecord, alphabetIndex, state) {
if (!transitionStateRecord[finiteAutomaton.alphabets[alphabetIndex]]) {
transitionStateRecord[finiteAutomaton.alphabets[alphabetIndex]] = [state];
}
else {
transitionStateRecord[finiteAutomaton.alphabets[alphabetIndex]].push(state);
}
}
Object.entries(finiteAutomaton.transitions).forEach(([transitionKey, transitionStates]) => {
const transitionStateRecord = {};
if (typeof transitionStates !== 'string' && Array.isArray(transitionStates)) {
transitionStates.forEach((transitionState, transitionStateIndex) => {
if (transitionState !== null && transitionState !== undefined) {
const newEpsilonTransitionTargetStates = new Set();
if (Array.isArray(transitionState)) {
transitionState.forEach((state) => {
(0, utils_1.expandCharacterRanges)(state.toString()).forEach((stateString) => {
newEpsilonTransitionTargetStates.add(stateString);
});
});
if (!transitionStateRecord[finiteAutomaton.alphabets[transitionStateIndex]]) {
transitionStateRecord[finiteAutomaton.alphabets[transitionStateIndex]] = Array.from(newEpsilonTransitionTargetStates);
}
else {
transitionStateRecord[finiteAutomaton.alphabets[transitionStateIndex]].push(...Array.from(newEpsilonTransitionTargetStates));
}
}
else {
(0, utils_1.expandCharacterRanges)(transitionState.toString()).forEach((expandedState) => {
attachToStateRecord(transitionStateRecord, transitionStateIndex, appendedString + expandedState.toString());
});
}
}
});
finiteAutomaton.transitions[appendedString + transitionKey] =
transitionStateRecord;
if (appendedString) {
delete finiteAutomaton.transitions[transitionKey];
}
}
else if (transitionStates === 'loop') {
finiteAutomaton.alphabets.forEach((_, alphabetIndex) => {
attachToStateRecord(transitionStateRecord, alphabetIndex, appendedString + transitionKey.toString());
});
finiteAutomaton.transitions[appendedString + transitionKey] =
transitionStateRecord;
if (appendedString) {
delete finiteAutomaton.transitions[transitionKey];
}
}
});
return finiteAutomaton;
}
exports.normalize = normalize;