The frontend now does a depth first ordering of states and then sorts states
authorthurston <thurston@052ea7fc-9027-0410-9066-f65837a77df0>
Sat, 3 Feb 2007 21:29:15 +0000 (21:29 +0000)
committerthurston <thurston@052ea7fc-9027-0410-9066-f65837a77df0>
Sat, 3 Feb 2007 21:29:15 +0000 (21:29 +0000)
based on final state status before assigning ids.

git-svn-id: http://svn.complang.org/ragel/trunk@69 052ea7fc-9027-0410-9066-f65837a77df0

ragel/fsmbase.cpp
ragel/fsmgraph.h
ragel/fsmmin.cpp
ragel/parsedata.cpp
ragel/xmlcodegen.cpp

index 16841d0..9976fae 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2001 Adrian Thurston <thurston@cs.queensu.ca>
+ *  Copyright 2001-2007 Adrian Thurston <thurston@cs.queensu.ca>
  */
 
 /*  This file is part of Ragel.
@@ -414,14 +414,6 @@ void FsmAp::copyInEntryPoints( FsmAp *other )
                entryPoints.insertMulti( en->key, en->value );
 }
 
-void FsmAp::setStateNumbers()
-{
-       int curNum = 0;
-       StateList::Iter state = stateList;
-       for ( ; state.lte(); state++ )
-               state->alg.stateNum = curNum++;
-}
-
 
 void FsmAp::unsetAllFinStates()
 {
@@ -483,3 +475,68 @@ void FsmAp::verifyNoDeadEndStates()
                st->stateBits &= ~ SB_ISMARKED;
        }
 }
+
+void FsmAp::depthFirstOrdering( StateAp *state )
+{
+       /* Nothing to do if the state is already on the list. */
+       if ( state->stateBits & SB_ONLIST )
+               return;
+
+       /* Doing depth first, put state on the list. */
+       state->stateBits |= SB_ONLIST;
+       stateList.append( state );
+       
+       /* Recurse on everything ranges. */
+       for ( TransList::Iter tel = state->outList; tel.lte(); tel++ ) {
+               if ( tel->toState != 0 )
+                       depthFirstOrdering( tel->toState );
+       }
+}
+
+/* Ordering states by transition connections. */
+void FsmAp::depthFirstOrdering()
+{
+       /* Init on state list flags. */
+       for ( StateList::Iter st = stateList; st.lte(); st++ )
+               st->stateBits &= ~SB_ONLIST;
+       
+       /* Clear out the state list, we will rebuild it. */
+       int stateListLen = stateList.length();
+       stateList.abandon();
+
+       /* Add back to the state list from the start state and all other entry
+        * points. */
+       depthFirstOrdering( startState );
+       for ( EntryMap::Iter en = entryPoints; en.lte(); en++ )
+               depthFirstOrdering( en->value );
+       
+       /* Make sure we put everything back on. */
+       assert( stateListLen == stateList.length() );
+}
+
+/* Stable sort the states by final state status. */
+void FsmAp::sortStatesByFinal()
+{
+       /* Move forward through the list and throw final states onto the end. */
+       StateAp *state = 0;
+       StateAp *next = stateList.head;
+       StateAp *last = stateList.tail;
+       while ( state != last ) {
+               /* Move forward and load up the next. */
+               state = next;
+               next = state->next;
+
+               /* Throw to the end? */
+               if ( state->isFinState() ) {
+                       stateList.detach( state );
+                       stateList.append( state );
+               }
+       }
+}
+
+void FsmAp::setStateNumbers( int base )
+{
+       for ( StateList::Iter state = stateList; state.lte(); state++ )
+               state->alg.stateNum = base++;
+}
+
index 1a8e80c..3b29856 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2001-2004 Adrian Thurston <thurston@cs.queensu.ca>
+ *  Copyright 2001-2007 Adrian Thurston <thurston@cs.queensu.ca>
  */
 
 /*  This file is part of Ragel.
@@ -44,6 +44,7 @@
 #define SB_BOTH       0x03
 #define SB_ISFINAL    0x04
 #define SB_ISMARKED   0x08
+#define SB_ONLIST     0x10
 
 struct TransAp;
 struct StateAp;
@@ -1261,8 +1262,13 @@ struct FsmAp
         * copied into this machine. */
        void copyInEntryPoints( FsmAp *other );
 
-       /* Set State numbers starting at 0. */
-       void setStateNumbers();
+       /* Ordering states. */
+       void depthFirstOrdering( StateAp *state );
+       void depthFirstOrdering();
+       void sortStatesByFinal();
+
+       /* Set sqequential state numbers starting at 0. */
+       void setStateNumbers( int base );
 
        /* Unset all final states. */
        void unsetAllFinStates();
index c57de6f..046d11a 100644 (file)
@@ -407,7 +407,7 @@ bool FsmAp::markRound( MarkIndex &markIndex )
 void FsmAp::minimizeStable()
 {
        /* Set the state numbers. */
-       setStateNumbers();
+       setStateNumbers( 0 );
 
        /* This keeps track of which pairs have been marked. */
        MarkIndex markIndex( stateList.length() );
index 4dca439..9d16c2f 100644 (file)
@@ -1308,6 +1308,17 @@ void ParseData::prepareMachineGen( GraphDictEl *graphDictEl )
 
        /* Depends on the graph analysis. */
        setLongestMatchData( sectionGraph );
+
+       /* State numbers need to be assigned such that all final states have a
+        * larger state id number than all non-final states. This enables the
+        * first_final mechanism to function correctly. We also want states to be
+        * ordered in a predictable fashion. So we first apply a depth-first
+        * search, then do a stable sort by final state status, then assign
+        * numbers. */
+
+       sectionGraph->depthFirstOrdering();
+       sectionGraph->sortStatesByFinal();
+       sectionGraph->setStateNumbers( 1 );
 }
 
 void ParseData::generateXML( ostream &out )
index bc9c155..3831c3e 100644 (file)
@@ -583,8 +583,6 @@ void XMLCodeGen::writeEntryPoints()
 
 void XMLCodeGen::writeMachine()
 {
-       fsm->setStateNumbers();
-
        /* Open the machine. */
        out << "  <machine>\n";