Beispiel #1
0
        /**
         * Constructs an NFA accepting the complement of the language
         * of a given NFA.
         *
         * Converts the NFA into a DFA, then negates that DFA.
         * Exponential state blowup possible and common.
         *
         * @param the NFA to construct the complement for.
         *
         * @return a pair of integers denoting the index of start
         *         and end state of the complement NFA.
         */
        private IntPair complement(IntPair nfa)
        {
            if (Options.DEBUG)
            {
                Out.debug("complement for " + nfa);
                Out.debug("NFA is :" + Out.NL + this);
            }

            int dfaStart = nfa.end + 1;

            // fixme: only need epsilon closure of states reachable from nfa.start
            epsilonFill();

            Hashtable dfaStates = new PrettyHashtable(numStates);
            ArrayList dfaVector = new PrettyArrayList(numStates);

            int numDFAStates    = 0;
            int currentDFAState = 0;

            StateSet currentState, newState;

            newState            = epsilon[nfa.start];
            dfaStates[newState] = new Integer(numDFAStates);
            dfaVector.Add(newState);

            if (Options.DEBUG)
            {
                Out.debug("pos DFA start state is :" + Out.NL + dfaStates + Out.NL + Out.NL + "ordered :" + Out.NL + dfaVector);
            }

            currentDFAState = 0;

            while (currentDFAState <= numDFAStates)
            {
                currentState = (StateSet)dfaVector[currentDFAState];

                for (char input = (char)0; input < numInput; input++)
                {
                    newState = DFAEdge(currentState, input);

                    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 = (Integer)dfaStates[newState];

                        if (nextDFAState != null)
                        {
                            // Out.debug("FOUND!");
                            addTransition(dfaStart + currentDFAState, input, dfaStart + nextDFAState.intValue());
                        }
                        else
                        {
                            if (Options.dump)
                            {
                                Out.print("+");
                            }
                            // Out.debug("NOT FOUND!");
                            // Out.debug("Table was "+dfaStates);
                            numDFAStates++;

                            dfaStates[newState] = new Integer(numDFAStates);
                            dfaVector.Add(newState);

                            addTransition(dfaStart + currentDFAState, input, dfaStart + numDFAStates);
                        }
                    }
                }

                currentDFAState++;
            }

            // We have a dfa accepting the positive regexp.

            // Now the complement:
            if (Options.DEBUG)
            {
                Out.debug("dfa finished, nfa is now :" + Out.NL + this);
            }

            int start = dfaStart + numDFAStates + 1;
            int error = dfaStart + numDFAStates + 2;
            int end   = dfaStart + numDFAStates + 3;

            addEpsilonTransition(start, dfaStart);

            for (int i = 0; i < numInput; i++)
            {
                addTransition(error, i, error);
            }

            addEpsilonTransition(error, end);

            for (int s = 0; s <= numDFAStates; s++)
            {
                currentState = (StateSet)dfaVector[s];

                currentDFAState = dfaStart + s;

                // if it was not a final state, it is now in the complement
                if (!currentState.isElement(nfa.end))
                {
                    addEpsilonTransition(currentDFAState, end);
                }

                // all inputs not present (formerly leading to an implicit error)
                // now lead to an explicit (final) state accepting everything.
                for (int i = 0; i < numInput; i++)
                {
                    if (table[currentDFAState][i] == null)
                    {
                        addTransition(currentDFAState, i, error);
                    }
                }
            }

            // eliminate transitions leading to dead states
            if (live == null || live.Length < numStates)
            {
                live    = new bool [2 * numStates];
                visited = new bool [2 * numStates];
            }

            _end       = end;
            _dfaStates = dfaVector;
            _dfaStart  = dfaStart;
            removeDead(dfaStart);

            if (Options.DEBUG)
            {
                Out.debug("complement finished, nfa (" + start + "," + end + ") is now :" + this);
            }

            return(new IntPair(start, end));
        }
Beispiel #2
0
        /**
         * Returns an DFA that accepts the same language as this NFA.
         * This DFA is usualy not minimal.
         */
        public DFA getDFA()
        {
            Hashtable dfaStates = new PrettyHashtable(numStates);
            ArrayList dfaVector = new PrettyArrayList(numStates);

            DFA dfa = new DFA(2 * numLexStates, numInput);

            int numDFAStates    = 0;
            int currentDFAState = 0;

            Out.println("Converting NFA to DFA : ");

            epsilonFill();

            StateSet currentState, newState;

            for (int i = 0; i < 2 * numLexStates; i++)
            {
                newState = epsilon[i];

                dfaStates[newState] = new Integer(numDFAStates);
                dfaVector.Add(newState);

                dfa.setLexState(i, numDFAStates);

                dfa.setFinal(numDFAStates, containsFinal(newState));
                dfa.setPushback(numDFAStates, containsPushback(newState));
                dfa.setAction(numDFAStates, getAction(newState));

                numDFAStates++;
            }

            numDFAStates--;

            if (Options.DEBUG)
            {
                Out.debug("DFA start states are :" + Out.NL + dfaStates + Out.NL + Out.NL + "ordered :" + Out.NL + dfaVector);
            }

            currentDFAState = 0;

            StateSet           tempStateSet = NFA.tempStateSet;
            StateSetEnumerator states       = NFA.states;

            // will be reused
            newState = new StateSet(numStates);

            while (currentDFAState <= numDFAStates)
            {
                currentState = (StateSet)dfaVector[currentDFAState];

                for (char input = (char)0; input < 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(table[states.nextElement()][input]);
                    }

                    newState.copy(tempStateSet);

                    states.reset(tempStateSet);
                    while (states.hasMoreElements())
                    {
                        newState.add(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 = (Integer)dfaStates[newState];

                        if (nextDFAState != null)
                        {
                            // Out.debug("FOUND!");
                            dfa.addTransition(currentDFAState, input, nextDFAState.intValue());
                        }
                        else
                        {
                            if (Options.progress)
                            {
                                Out.print(".");
                            }
                            // Out.debug("NOT FOUND!");
                            // Out.debug("Table was "+dfaStates);
                            numDFAStates++;

                            // make a new copy of newState to store in dfaStates
                            StateSet storeState = new StateSet(newState);

                            dfaStates[storeState] = new Integer(numDFAStates);
                            dfaVector.Add(storeState);

                            dfa.addTransition(currentDFAState, input, numDFAStates);
                            dfa.setFinal(numDFAStates, containsFinal(storeState));
                            dfa.setPushback(numDFAStates, containsPushback(storeState));
                            dfa.setAction(numDFAStates, getAction(storeState));
                        }
                    }
                }

                currentDFAState++;
            }

            if (Options.verbose)
            {
                Out.println("");
            }

            return(dfa);
        }