jflex.dfa.DfaFactory Maven / Gradle / Ivy
package jflex.dfa;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import jflex.core.NFA;
import jflex.logging.Out;
import jflex.option.Options;
import jflex.state.StateSet;
import jflex.state.StateSetEnumerator;
public class DfaFactory {
/**
* Returns a DFA that accepts the same language as the NFA.
*
* This DFA is usually not minimal.
*
* @return a DFA that accepts the same language as the NFA.
*/
public static DFA createFromNfa(NFA nfa) {
int numStates = nfa.numStates();
Map dfaStates = new HashMap<>(numStates);
List dfaList = new ArrayList<>(numStates);
DFA dfa = new DFA(nfa.numEntryStates(), nfa.numInput(), nfa.numLexStates());
int numDFAStates = 0;
int currentDFAState = 0;
Out.println("Converting NFA to DFA : ");
nfa.epsilonFill();
StateSet currentState;
// will be reused
StateSet newState;
// create the initial states of the DFA
for (int i = 0; i < nfa.numEntryStates(); i++) {
newState = nfa.epsilon(i);
dfaStates.put(newState, numDFAStates);
dfaList.add(newState);
dfa.setEntryState(i, numDFAStates);
dfa.setFinal(numDFAStates, nfa.containsFinal(newState));
dfa.setAction(numDFAStates, nfa.getAction(newState));
numDFAStates++;
}
numDFAStates--;
// if (Build.DEBUG)
// Out.debug(
// "DFA start states are :"
// + Out.NL
// + dfaStates
// + Out.NL
// + Out.NL
// + "ordered :"
// + Out.NL
// + dfaList);
StateSet tempStateSet = nfa.tempStateSet();
StateSetEnumerator states = nfa.states();
newState = new StateSet(numStates);
while (currentDFAState <= numDFAStates) {
currentState = dfaList.get(currentDFAState);
for (int input = 0; input < nfa.numInput(); input++) {
// newState = DFAEdge(currentState, input);
// inlining DFAEdge for performance:
// Out.debug("Calculating DFAEdge for state set "+currentState+" and input '"+input+"'");
tempStateSet.clear();
states.reset(currentState);
while (states.hasMoreElements())
tempStateSet.add(nfa.reachableStates(states.nextElement(), input));
newState.copy(tempStateSet);
states.reset(tempStateSet);
while (states.hasMoreElements()) newState.add(nfa.epsilon(states.nextElement()));
// Out.debug("DFAEdge is : "+newState);
if (newState.containsElements()) {
// Out.debug("DFAEdge for input "+(int)input+" and state set "+currentState+" is
// "+newState);
// Out.debug("Looking for state set "+newState);
Integer nextDFAState = dfaStates.get(newState);
if (nextDFAState != null) {
dfa.addTransition(currentDFAState, input, nextDFAState);
} else {
if (Options.progress) Out.print(".");
// Out.debug("Table was "+dfaStates);
numDFAStates++;
// make a new copy of newState to store in dfaStates
StateSet storeState = new StateSet(newState);
dfaStates.put(storeState, numDFAStates);
dfaList.add(storeState);
dfa.addTransition(currentDFAState, input, numDFAStates);
dfa.setFinal(numDFAStates, nfa.containsFinal(storeState));
dfa.setAction(numDFAStates, nfa.getAction(storeState));
}
}
}
currentDFAState++;
}
if (Options.verbose) Out.println("");
return dfa;
}
private DfaFactory() {}
}