2 * Copyright 2002 Adrian Thurston <thurston@cs.queensu.ca>
5 /* This file is part of Ragel.
7 * Ragel is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * Ragel is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Ragel; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 /* Construct a mark index for a specified number of states. Must new up
30 * an array that is states^2 in size. */
31 MarkIndex::MarkIndex( int states ) : numStates(states)
33 /* Total pairs is states^2. Actually only use half of these, but we allocate
34 * them all to make indexing into the array easier. */
35 int total = states * states;
37 /* New up chars so that individual DListEl constructors are
38 * not called. Zero out the mem manually. */
39 array = new bool[total];
40 memset( array, 0, sizeof(bool) * total );
43 /* Free the array used to store state pairs. */
44 MarkIndex::~MarkIndex()
49 /* Mark a pair of states. States are specified by their number. The
50 * marked states are moved from the unmarked list to the marked list. */
51 void MarkIndex::markPair(int state1, int state2)
53 int pos = ( state1 >= state2 ) ?
54 ( state1 * numStates ) + state2 :
55 ( state2 * numStates ) + state1;
60 /* Returns true if the pair of states are marked. Returns false otherwise.
61 * Ordering of states given does not matter. */
62 bool MarkIndex::isPairMarked(int state1, int state2)
64 int pos = ( state1 >= state2 ) ?
65 ( state1 * numStates ) + state2 :
66 ( state2 * numStates ) + state1;
71 /* Create a new fsm state. State has not out transitions or in transitions, not
72 * out out transition data and not number. */
75 /* No out or in transitions. */
79 /* No entry points, or epsilon trans. */
86 /* No transitions in from other states. */
89 /* Only used during merging. Normally null. */
93 /* No state identification bits. */
96 /* No Priority data. */
100 toStateActionTable(),
101 fromStateActionTable(),
109 /* Copy everything except actual the transitions. That is left up to the
110 * FsmAp copy constructor. */
111 StateAp::StateAp(const StateAp &other)
113 /* All lists are cleared. They will be filled in when the
114 * individual transitions are duplicated and attached. */
118 /* Duplicate the entry id set and epsilon transitions. These
119 * are sets of integers and as such need no fixing. */
120 entryIds(other.entryIds),
121 epsilonTrans(other.epsilonTrans),
123 /* Copy in the elements of the conditions. */
124 stateCondList( other.stateCondList ),
126 /* No transitions in from other states. */
129 /* This is only used during merging. Normally null. */
133 /* Fsm state data. */
134 stateBits(other.stateBits),
136 /* Copy in priority data. */
137 outPriorTable(other.outPriorTable),
139 /* Copy in action data. */
140 toStateActionTable(other.toStateActionTable),
141 fromStateActionTable(other.fromStateActionTable),
142 outActionTable(other.outActionTable),
143 outCondSet(other.outCondSet),
144 errActionTable(other.errActionTable),
145 eofActionTable(other.eofActionTable)
147 /* Duplicate all the transitions. */
148 for ( TransList::Iter trans = other.outList; trans.lte(); trans++ ) {
149 /* Dupicate and store the orginal target in the transition. This will
150 * be corrected once all the states have been created. */
151 TransAp *newTrans = new TransAp(*trans);
152 newTrans->toState = trans->toState;
153 outList.append( newTrans );
157 /* If there is a state dict element, then delete it. Everything else is left
158 * up to the FsmGraph destructor. */
161 if ( stateDictEl != 0 )
165 /* Compare two states using pointers to the states. With the approximate
166 * compare the idea is that if the compare finds them the same, they can
167 * immediately be merged. */
168 int ApproxCompare::compare( const StateAp *state1 , const StateAp *state2 )
172 /* Test final state status. */
173 if ( (state1->stateBits & SB_ISFINAL) && !(state2->stateBits & SB_ISFINAL) )
175 else if ( !(state1->stateBits & SB_ISFINAL) && (state2->stateBits & SB_ISFINAL) )
178 /* Test epsilon transition sets. */
179 compareRes = CmpEpsilonTrans::compare( state1->epsilonTrans,
180 state2->epsilonTrans );
181 if ( compareRes != 0 )
184 /* Compare the out transitions. */
185 compareRes = FsmAp::compareStateData( state1, state2 );
186 if ( compareRes != 0 )
189 /* Use a pair iterator to get the transition pairs. */
190 PairIter<TransAp> outPair( state1->outList.head, state2->outList.head );
191 for ( ; !outPair.end(); outPair++ ) {
192 switch ( outPair.userState ) {
195 compareRes = FsmAp::compareFullPtr( outPair.s1Tel.trans, 0 );
196 if ( compareRes != 0 )
201 compareRes = FsmAp::compareFullPtr( 0, outPair.s2Tel.trans );
202 if ( compareRes != 0 )
207 compareRes = FsmAp::compareFullPtr(
208 outPair.s1Tel.trans, outPair.s2Tel.trans );
209 if ( compareRes != 0 )
219 /* Got through the entire state comparison, deem them equal. */
223 /* Compare class for the sort that does the intial partition of compaction. */
224 int InitPartitionCompare::compare( const StateAp *state1 , const StateAp *state2 )
228 /* Test final state status. */
229 if ( (state1->stateBits & SB_ISFINAL) && !(state2->stateBits & SB_ISFINAL) )
231 else if ( !(state1->stateBits & SB_ISFINAL) && (state2->stateBits & SB_ISFINAL) )
234 /* Test epsilon transition sets. */
235 compareRes = CmpEpsilonTrans::compare( state1->epsilonTrans,
236 state2->epsilonTrans );
237 if ( compareRes != 0 )
240 /* Compare the out transitions. */
241 compareRes = FsmAp::compareStateData( state1, state2 );
242 if ( compareRes != 0 )
245 /* Use a pair iterator to test the condition pairs. */
246 PairIter<StateCond> condPair( state1->stateCondList.head, state2->stateCondList.head );
247 for ( ; !condPair.end(); condPair++ ) {
248 switch ( condPair.userState ) {
255 CondSpace *condSpace1 = condPair.s1Tel.trans->condSpace;
256 CondSpace *condSpace2 = condPair.s2Tel.trans->condSpace;
257 if ( condSpace1 < condSpace2 )
259 else if ( condSpace1 > condSpace2 )
269 /* Use a pair iterator to test the transition pairs. */
270 PairIter<TransAp> outPair( state1->outList.head, state2->outList.head );
271 for ( ; !outPair.end(); outPair++ ) {
272 switch ( outPair.userState ) {
275 compareRes = FsmAp::compareDataPtr( outPair.s1Tel.trans, 0 );
276 if ( compareRes != 0 )
281 compareRes = FsmAp::compareDataPtr( 0, outPair.s2Tel.trans );
282 if ( compareRes != 0 )
287 compareRes = FsmAp::compareDataPtr(
288 outPair.s1Tel.trans, outPair.s2Tel.trans );
289 if ( compareRes != 0 )
302 /* Compare class for the sort that does the partitioning. */
303 int PartitionCompare::compare( const StateAp *state1, const StateAp *state2 )
307 /* Use a pair iterator to get the transition pairs. */
308 PairIter<TransAp> outPair( state1->outList.head, state2->outList.head );
309 for ( ; !outPair.end(); outPair++ ) {
310 switch ( outPair.userState ) {
313 compareRes = FsmAp::comparePartPtr( outPair.s1Tel.trans, 0 );
314 if ( compareRes != 0 )
319 compareRes = FsmAp::comparePartPtr( 0, outPair.s2Tel.trans );
320 if ( compareRes != 0 )
325 compareRes = FsmAp::comparePartPtr(
326 outPair.s1Tel.trans, outPair.s2Tel.trans );
327 if ( compareRes != 0 )
340 /* Compare class for the sort that does the partitioning. */
341 bool MarkCompare::shouldMark( MarkIndex &markIndex, const StateAp *state1,
342 const StateAp *state2 )
344 /* Use a pair iterator to get the transition pairs. */
345 PairIter<TransAp> outPair( state1->outList.head, state2->outList.head );
346 for ( ; !outPair.end(); outPair++ ) {
347 switch ( outPair.userState ) {
350 if ( FsmAp::shouldMarkPtr( markIndex, outPair.s1Tel.trans, 0 ) )
355 if ( FsmAp::shouldMarkPtr( markIndex, 0, outPair.s2Tel.trans ) )
360 if ( FsmAp::shouldMarkPtr( markIndex,
361 outPair.s1Tel.trans, outPair.s2Tel.trans ) )
375 * Transition Comparison.
378 /* Compare target partitions. Either pointer may be null. */
379 int FsmAp::comparePartPtr( TransAp *trans1, TransAp *trans2 )
382 /* If trans1 is set then so should trans2. The initial partitioning
383 * guarantees this for us. */
384 if ( trans1->toState == 0 && trans2->toState != 0 )
386 else if ( trans1->toState != 0 && trans2->toState == 0 )
388 else if ( trans1->toState != 0 ) {
389 /* Both of targets are set. */
390 return CmpOrd< MinPartition* >::compare(
391 trans1->toState->alg.partition, trans2->toState->alg.partition );
398 /* Compares two transition pointers according to priority and functions.
399 * Either pointer may be null. Does not consider to state or from state. */
400 int FsmAp::compareDataPtr( TransAp *trans1, TransAp *trans2 )
402 if ( trans1 == 0 && trans2 != 0 )
404 else if ( trans1 != 0 && trans2 == 0 )
406 else if ( trans1 != 0 ) {
407 /* Both of the transition pointers are set. */
408 int compareRes = compareTransData( trans1, trans2 );
409 if ( compareRes != 0 )
415 /* Compares two transitions according to target state, priority and functions.
416 * Does not consider from state. Either of the pointers may be null. */
417 int FsmAp::compareFullPtr( TransAp *trans1, TransAp *trans2 )
419 if ( (trans1 != 0) ^ (trans2 != 0) ) {
420 /* Exactly one of the transitions is set. */
426 else if ( trans1 != 0 ) {
427 /* Both of the transition pointers are set. Test target state,
428 * priority and funcs. */
429 if ( trans1->toState < trans2->toState )
431 else if ( trans1->toState > trans2->toState )
433 else if ( trans1->toState != 0 ) {
434 /* Test transition data. */
435 int compareRes = compareTransData( trans1, trans2 );
436 if ( compareRes != 0 )
444 bool FsmAp::shouldMarkPtr( MarkIndex &markIndex, TransAp *trans1,
447 if ( (trans1 != 0) ^ (trans2 != 0) ) {
448 /* Exactly one of the transitions is set. The initial mark round
449 * should rule out this case. */
452 else if ( trans1 != 0 ) {
453 /* Both of the transitions are set. If the target pair is marked, then
454 * the pair we are considering gets marked. */
455 return markIndex.isPairMarked( trans1->toState->alg.stateNum,
456 trans2->toState->alg.stateNum );
459 /* Neither of the transitiosn are set. */