/* * Make a DFA-ish automaton from the NFA-like structure of the regex */ public TokenAutomaton ConstructAutomaton() { Dictionary<ISet<Node>, TokenAutomaton.Node> DFAStates = new Dictionary<ISet<Node>, TokenAutomaton.Node>(new SetEqualityComparer<Node>()); TokenAutomaton.Node DFAStartState = new TokenAutomaton.Node(); // set of nodes accessible from NFA start state ISet<Node> NFAStartStates = start.EpsilonMove(); DFAStates.Add(NFAStartStates, DFAStartState); Stack<ISet<Node>> s = new Stack<ISet<Node>>(); s.Push(NFAStartStates); while (s.Count != 0) { // pop a NFA state ISet<Node> currentNFAStates = s.Pop(); // get the corresponding DFA state TokenAutomaton.Node currentDFAState = DFAStates[currentNFAStates]; ISet<char> nextChars = new HashSet<char>(); // find which characters we can move with from currentNFAStates foreach (Node n in currentNFAStates) nextChars.UnionWith(n.transitions.Keys); foreach (char c in nextChars) { // set of NFA states that can be reached from the current set with input c ISet<Node> nextNFAStates = Node.Move(currentNFAStates, c); if (nextNFAStates.Count != 0) { // include NFA states that can be reached with an epsilon transition HashSet<Node> epsilonClosure = new HashSet<Node>(); epsilonClosure.UnionWith(nextNFAStates); epsilonClosure.UnionWith(Node.EpsilonMove(nextNFAStates)); TokenAutomaton.Node nextDFAState; if (!DFAStates.TryGetValue(epsilonClosure, out nextDFAState)) { // no DFA state exists for this set of NFA states yet, so we create one nextDFAState = new TokenAutomaton.Node(); // set accepted token types for the DFA state foreach (Node n in epsilonClosure) { if (n.tokenType != null && (nextDFAState.acceptedTokenType == null || (n.tokenType.TokenPriority == TokenType.Priority.Keyword))) { nextDFAState.acceptedTokenType = n.tokenType; } } DFAStates.Add(epsilonClosure, nextDFAState); s.Push(epsilonClosure); } // create transition currentDFAState.transitions.Add(c, nextDFAState); } } } return new TokenAutomaton(DFAStartState); }
/* * Make a DFA-ish automaton from the NFA-like structure of the regex */ public TokenAutomaton ConstructAutomaton() { Dictionary <ISet <Node>, TokenAutomaton.Node> DFAStates = new Dictionary <ISet <Node>, TokenAutomaton.Node>(new SetEqualityComparer <Node>()); TokenAutomaton.Node DFAStartState = new TokenAutomaton.Node(); // set of nodes accessible from NFA start state ISet <Node> NFAStartStates = start.EpsilonMove(); DFAStates.Add(NFAStartStates, DFAStartState); Stack <ISet <Node> > s = new Stack <ISet <Node> >(); s.Push(NFAStartStates); while (s.Count != 0) { // pop a NFA state ISet <Node> currentNFAStates = s.Pop(); // get the corresponding DFA state TokenAutomaton.Node currentDFAState = DFAStates[currentNFAStates]; ISet <char> nextChars = new HashSet <char>(); // find which characters we can move with from currentNFAStates foreach (Node n in currentNFAStates) { nextChars.UnionWith(n.transitions.Keys); } foreach (char c in nextChars) { // set of NFA states that can be reached from the current set with input c ISet <Node> nextNFAStates = Node.Move(currentNFAStates, c); if (nextNFAStates.Count != 0) { // include NFA states that can be reached with an epsilon transition HashSet <Node> epsilonClosure = new HashSet <Node>(); epsilonClosure.UnionWith(nextNFAStates); epsilonClosure.UnionWith(Node.EpsilonMove(nextNFAStates)); TokenAutomaton.Node nextDFAState; if (!DFAStates.TryGetValue(epsilonClosure, out nextDFAState)) { // no DFA state exists for this set of NFA states yet, so we create one nextDFAState = new TokenAutomaton.Node(); // set accepted token types for the DFA state foreach (Node n in epsilonClosure) { if (n.tokenType != null && (nextDFAState.acceptedTokenType == null || (n.tokenType.TokenPriority == TokenType.Priority.Keyword))) { nextDFAState.acceptedTokenType = n.tokenType; } } DFAStates.Add(epsilonClosure, nextDFAState); s.Push(epsilonClosure); } // create transition currentDFAState.transitions.Add(c, nextDFAState); } } } return(new TokenAutomaton(DFAStartState)); }