Go back to 3.X semantics for >, % and error actions. The > operator also embeds
[external/ragel.git] / ragel / fsmgraph.h
1 /*
2  *  Copyright 2001-2007 Adrian Thurston <thurston@cs.queensu.ca>
3  */
4
5 /*  This file is part of Ragel.
6  *
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.
11  * 
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.
16  * 
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 
20  */
21
22 #ifndef _FSMGRAPH_H
23 #define _FSMGRAPH_H
24
25 #include "config.h"
26 #include <assert.h>
27 #include <iostream>
28 #include <string>
29 #include "common.h"
30 #include "vector.h"
31 #include "bstset.h"
32 #include "compare.h"
33 #include "avltree.h"
34 #include "dlist.h"
35 #include "bstmap.h"
36 #include "sbstmap.h"
37 #include "sbstset.h"
38 #include "sbsttable.h"
39 #include "avlset.h"
40 #include "avlmap.h"
41 #include "ragel.h"
42
43 //#define LOG_CONDS
44
45 /* Flags that control merging. */
46 #define SB_GRAPH1     0x01
47 #define SB_GRAPH2     0x02
48 #define SB_BOTH       0x03
49 #define SB_ISFINAL    0x04
50 #define SB_ISMARKED   0x08
51 #define SB_ONLIST     0x10
52
53 using std::ostream;
54
55 struct TransAp;
56 struct StateAp;
57 struct FsmAp;
58 struct Action;
59 struct LongestMatchPart;
60
61 /* State list element for unambiguous access to list element. */
62 struct FsmListEl 
63 {
64         StateAp *prev, *next;
65 };
66
67 /* This is the marked index for a state pair. Used in minimization. It keeps
68  * track of whether or not the state pair is marked. */
69 struct MarkIndex
70 {
71         MarkIndex(int states);
72         ~MarkIndex();
73
74         void markPair(int state1, int state2);
75         bool isPairMarked(int state1, int state2);
76
77 private:
78         int numStates;
79         bool *array;
80 };
81
82 extern KeyOps *keyOps;
83
84 /* Transistion Action Element. */
85 typedef SBstMapEl< int, Action* > ActionTableEl;
86
87 /* Nodes in the tree that use this action. */
88 struct NameInst;
89 struct InlineList;
90 typedef Vector<NameInst*> ActionRefs;
91
92 /* Element in list of actions. Contains the string for the code to exectute. */
93 struct Action 
94 :
95         public DListEl<Action>,
96         public AvlTreeEl<Action>
97 {
98 public:
99
100         Action( const InputLoc &loc, char *name, InlineList *inlineList, int condId )
101         :
102                 loc(loc),
103                 name(name),
104                 inlineList(inlineList), 
105                 actionId(-1),
106                 numTransRefs(0),
107                 numToStateRefs(0),
108                 numFromStateRefs(0),
109                 numEofRefs(0),
110                 numCondRefs(0),
111                 anyCall(false),
112                 isLmAction(false),
113                 condId(condId)
114         {
115         }
116
117         /* Key for action dictionary. */
118         char *getKey() const { return name; }
119
120         /* Data collected during parse. */
121         InputLoc loc;
122         char *name;
123         InlineList *inlineList;
124         int actionId;
125
126         void actionName( ostream &out )
127         {
128                 if ( name != 0 )
129                         out << name;
130                 else
131                         out << loc.line << ":" << loc.col;
132         }
133
134         /* Places in the input text that reference the action. */
135         ActionRefs actionRefs;
136
137         /* Number of references in the final machine. */
138         int numRefs() 
139                 { return numTransRefs + numToStateRefs + numFromStateRefs + numEofRefs; }
140         int numTransRefs;
141         int numToStateRefs;
142         int numFromStateRefs;
143         int numEofRefs;
144         int numCondRefs;
145         bool anyCall;
146
147         bool isLmAction;
148         int condId;
149 };
150
151 struct CmpCondId
152 {
153         static inline int compare( const Action *cond1, const Action *cond2 )
154         {
155                 if ( cond1->condId < cond2->condId )
156                         return -1;
157                 else if ( cond1->condId > cond2->condId )
158                         return 1;
159                 return 0;
160         }
161 };
162
163 /* A list of actions. */
164 typedef DList<Action> ActionList;
165 typedef AvlTree<Action, char *, CmpStr> ActionDict;
166
167 /* Structure for reverse action mapping. */
168 struct RevActionMapEl
169 {
170         char *name;
171         InputLoc location;
172 };
173
174
175 /* Transition Action Table.  */
176 struct ActionTable 
177         : public SBstMap< int, Action*, CmpOrd<int> >
178 {
179         void setAction( int ordering, Action *action );
180         void setActions( int *orderings, Action **actions, int nActs );
181         void setActions( const ActionTable &other );
182
183         bool hasAction( Action *action );
184 };
185
186 typedef SBstSet< Action*, CmpOrd<Action*> > ActionSet;
187 typedef CmpSTable< Action*, CmpOrd<Action*> > CmpActionSet;
188
189 /* Transistion Action Element. */
190 typedef SBstMapEl< int, LongestMatchPart* > LmActionTableEl;
191
192 /* Transition Action Table.  */
193 struct LmActionTable 
194         : public SBstMap< int, LongestMatchPart*, CmpOrd<int> >
195 {
196         void setAction( int ordering, LongestMatchPart *action );
197         void setActions( const LmActionTable &other );
198 };
199
200 /* Compare of a whole action table element (key & value). */
201 struct CmpActionTableEl
202 {
203         static int compare( const ActionTableEl &action1, 
204                         const ActionTableEl &action2 )
205         {
206                 if ( action1.key < action2.key )
207                         return -1;
208                 else if ( action1.key > action2.key )
209                         return 1;
210                 else if ( action1.value < action2.value )
211                         return -1;
212                 else if ( action1.value > action2.value )
213                         return 1;
214                 return 0;
215         }
216 };
217
218 /* Compare for ActionTable. */
219 typedef CmpSTable< ActionTableEl, CmpActionTableEl > CmpActionTable;
220
221 /* Compare of a whole lm action table element (key & value). */
222 struct CmpLmActionTableEl
223 {
224         static int compare( const LmActionTableEl &lmAction1, 
225                         const LmActionTableEl &lmAction2 )
226         {
227                 if ( lmAction1.key < lmAction2.key )
228                         return -1;
229                 else if ( lmAction1.key > lmAction2.key )
230                         return 1;
231                 else if ( lmAction1.value < lmAction2.value )
232                         return -1;
233                 else if ( lmAction1.value > lmAction2.value )
234                         return 1;
235                 return 0;
236         }
237 };
238
239 /* Compare for ActionTable. */
240 typedef CmpSTable< LmActionTableEl, CmpLmActionTableEl > CmpLmActionTable;
241
242 /* Action table element for error action tables. Adds the encoding of transfer
243  * point. */
244 struct ErrActionTableEl
245 {
246         ErrActionTableEl( Action *action, int ordering, int transferPoint )
247                 : ordering(ordering), action(action), transferPoint(transferPoint) { }
248
249         /* Ordering and id of the action embedding. */
250         int ordering;
251         Action *action;
252
253         /* Id of point of transfere from Error action table to transtions and
254          * eofActionTable. */
255         int transferPoint;
256
257         int getKey() const { return ordering; }
258 };
259
260 struct ErrActionTable
261         : public SBstTable< ErrActionTableEl, int, CmpOrd<int> >
262 {
263         void setAction( int ordering, Action *action, int transferPoint );
264         void setActions( const ErrActionTable &other );
265 };
266
267 /* Compare of an error action table element (key & value). */
268 struct CmpErrActionTableEl
269 {
270         static int compare( const ErrActionTableEl &action1, 
271                         const ErrActionTableEl &action2 )
272         {
273                 if ( action1.ordering < action2.ordering )
274                         return -1;
275                 else if ( action1.ordering > action2.ordering )
276                         return 1;
277                 else if ( action1.action < action2.action )
278                         return -1;
279                 else if ( action1.action > action2.action )
280                         return 1;
281                 else if ( action1.transferPoint < action2.transferPoint )
282                         return -1;
283                 else if ( action1.transferPoint > action2.transferPoint )
284                         return 1;
285                 return 0;
286         }
287 };
288
289 /* Compare for ErrActionTable. */
290 typedef CmpSTable< ErrActionTableEl, CmpErrActionTableEl > CmpErrActionTable;
291
292
293 /* Descibe a priority, shared among PriorEls. 
294  * Has key and whether or not used. */
295 struct PriorDesc
296 {
297         int key;
298         int priority;
299 };
300
301 /* Element in the arrays of priorities for transitions and arrays. Ordering is
302  * unique among instantiations of machines, desc is shared. */
303 struct PriorEl
304 {
305         PriorEl( int ordering, PriorDesc *desc ) 
306                 : ordering(ordering), desc(desc) { }
307
308         int ordering;
309         PriorDesc *desc;
310 };
311
312 /* Compare priority elements, which are ordered by the priority descriptor
313  * key. */
314 struct PriorElCmp
315 {
316         static inline int compare( const PriorEl &pel1, const PriorEl &pel2 ) 
317         {
318                 if ( pel1.desc->key < pel2.desc->key )
319                         return -1;
320                 else if ( pel1.desc->key > pel2.desc->key )
321                         return 1;
322                 else
323                         return 0;
324         }
325 };
326
327
328 /* Priority Table. */
329 struct PriorTable 
330         : public SBstSet< PriorEl, PriorElCmp >
331 {
332         void setPrior( int ordering, PriorDesc *desc );
333         void setPriors( const PriorTable &other );
334 };
335
336 /* Compare of prior table elements for distinguising state data. */
337 struct CmpPriorEl
338 {
339         static inline int compare( const PriorEl &pel1, const PriorEl &pel2 )
340         {
341                 if ( pel1.desc < pel2.desc )
342                         return -1;
343                 else if ( pel1.desc > pel2.desc )
344                         return 1;
345                 else if ( pel1.ordering < pel2.ordering )
346                         return -1;
347                 else if ( pel1.ordering > pel2.ordering )
348                         return 1;
349                 return 0;
350         }
351 };
352
353 /* Compare of PriorTable distinguising state data. Using a compare of the
354  * pointers is a little more strict than it needs be. It requires that
355  * prioritiy tables have the exact same set of priority assignment operators
356  * (from the input lang) to be considered equal. 
357  *
358  * Really only key-value pairs need be tested and ordering be merged. However
359  * this would require that in the fuseing of states, priority descriptors be
360  * chosen for the new fused state based on priority. Since the out transition
361  * lists and ranges aren't necessarily going to line up, this is more work for
362  * little gain. Final compression resets all priorities first, so this would
363  * only be useful for compression at every operator, which is only an
364  * undocumented test feature.
365  */
366 typedef CmpSTable<PriorEl, CmpPriorEl> CmpPriorTable;
367
368 /* Plain action list that imposes no ordering. */
369 typedef Vector<int> TransFuncList;
370
371 /* Comparison for TransFuncList. */
372 typedef CmpTable< int, CmpOrd<int> > TransFuncListCompare;
373
374 /* Transition class that implements actions and priorities. */
375 struct TransAp 
376 {
377         TransAp() : fromState(0), toState(0) {}
378         TransAp( const TransAp &other ) :
379                 lowKey(other.lowKey),
380                 highKey(other.highKey),
381                 fromState(0), toState(0),
382                 actionTable(other.actionTable),
383                 priorTable(other.priorTable)
384         {
385                 assert( lmActionTable.length() == 0 && other.lmActionTable.length() == 0 );
386         }
387
388         Key lowKey, highKey;
389         StateAp *fromState;
390         StateAp *toState;
391
392         /* Pointers for outlist. */
393         TransAp *prev, *next;
394
395         /* Pointers for in-list. */
396         TransAp *ilprev, *ilnext;
397
398         /* The function table and priority for the transition. */
399         ActionTable actionTable;
400         PriorTable priorTable;
401
402         LmActionTable lmActionTable;
403 };
404
405 /* In transition list. Like DList except only has head pointers, which is all
406  * that is required. Insertion and deletion is handled by the graph. This
407  * class provides the iterator of a single list. */
408 struct TransInList
409 {
410         TransInList() : head(0) { }
411
412         TransAp *head;
413
414         struct Iter
415         {
416                 /* Default construct. */
417                 Iter() : ptr(0) { }
418
419                 /* Construct, assign from a list. */
420                 Iter( const TransInList &il )  : ptr(il.head) { }
421                 Iter &operator=( const TransInList &dl ) { ptr = dl.head; return *this; }
422
423                 /* At the end */
424                 bool lte() const    { return ptr != 0; }
425                 bool end() const    { return ptr == 0; }
426
427                 /* At the first, last element. */
428                 bool first() const { return ptr && ptr->ilprev == 0; }
429                 bool last() const  { return ptr && ptr->ilnext == 0; }
430
431                 /* Cast, dereference, arrow ops. */
432                 operator TransAp*() const   { return ptr; }
433                 TransAp &operator *() const { return *ptr; }
434                 TransAp *operator->() const { return ptr; }
435
436                 /* Increment, decrement. */
437                 inline void operator++(int)   { ptr = ptr->ilnext; }
438                 inline void operator--(int)   { ptr = ptr->ilprev; }
439
440                 /* The iterator is simply a pointer. */
441                 TransAp *ptr;
442         };
443 };
444
445 typedef DList<TransAp> TransList;
446
447 /* Set of states, list of states. */
448 typedef BstSet<StateAp*> StateSet;
449 typedef DList<StateAp> StateList;
450
451 /* A element in a state dict. */
452 struct StateDictEl 
453 :
454         public AvlTreeEl<StateDictEl>
455 {
456         StateDictEl(const StateSet &stateSet) 
457                 : stateSet(stateSet) { }
458
459         const StateSet &getKey() { return stateSet; }
460         StateSet stateSet;
461         StateAp *targState;
462 };
463
464 /* Dictionary mapping a set of states to a target state. */
465 typedef AvlTree< StateDictEl, StateSet, CmpTable<StateAp*> > StateDict;
466
467 /* Data needed for a merge operation. */
468 struct MergeData
469 {
470         MergeData() 
471                 : stfillHead(0), stfillTail(0) { }
472
473         StateDict stateDict;
474
475         StateAp *stfillHead;
476         StateAp *stfillTail;
477
478         void fillListAppend( StateAp *state );
479 };
480
481 struct TransEl
482 {
483         /* Constructors. */
484         TransEl() { }
485         TransEl( Key lowKey, Key highKey ) 
486                 : lowKey(lowKey), highKey(highKey) { }
487         TransEl( Key lowKey, Key highKey, TransAp *value ) 
488                 : lowKey(lowKey), highKey(highKey), value(value) { }
489
490         Key lowKey, highKey;
491         TransAp *value;
492 };
493
494 struct CmpKey
495 {
496         static int compare( const Key key1, const Key key2 )
497         {
498                 if ( key1 < key2 )
499                         return -1;
500                 else if ( key1 > key2 )
501                         return 1;
502                 else
503                         return 0;
504         }
505 };
506
507 /* Vector based set of key items. */
508 typedef BstSet<Key, CmpKey> KeySet;
509
510 struct MinPartition 
511 {
512         MinPartition() : active(false) { }
513
514         StateList list;
515         bool active;
516
517         MinPartition *prev, *next;
518 };
519
520 /* Epsilon transition stored in a state. Specifies the target */
521 typedef Vector<int> EpsilonTrans;
522
523 /* List of states that are to be drawn into this. */
524 struct EptVectEl
525 {
526         EptVectEl( StateAp *targ, bool leaving ) 
527                 : targ(targ), leaving(leaving) { }
528
529         StateAp *targ;
530         bool leaving;
531 };
532 typedef Vector<EptVectEl> EptVect;
533
534 /* Set of entry ids that go into this state. */
535 typedef BstSet<int> EntryIdSet;
536
537 /* Set of longest match items that may be active in a given state. */
538 typedef BstSet<LongestMatchPart*> LmItemSet;
539
540 /* A Conditions which is to be 
541  * transfered on pending out transitions. */
542 struct OutCond
543 {
544         OutCond( Action *action, bool sense )
545                 : action(action), sense(sense) {}
546
547         Action *action;
548         bool sense;
549 };
550
551 struct CmpOutCond
552 {
553         static int compare( const OutCond &outCond1, const OutCond &outCond2 )
554         {
555                 if ( outCond1.action < outCond2.action )
556                         return -1;
557                 else if ( outCond1.action > outCond2.action )
558                         return 1;
559                 else if ( outCond1.sense < outCond2.sense )
560                         return -1;
561                 else if ( outCond1.sense > outCond2.sense )
562                         return 1;
563                 return 0;
564         }
565 };
566
567 /* Set of conditions to be transfered to on pending out transitions. */
568 typedef SBstSet< OutCond, CmpOutCond > OutCondSet;
569 typedef CmpSTable< OutCond, CmpOutCond > CmpOutCondSet;
570
571 /* Conditions. */
572 typedef BstSet< Action*, CmpCondId > CondSet;
573 typedef CmpTable< Action*, CmpCondId > CmpCondSet;
574
575 struct CondSpace
576         : public AvlTreeEl<CondSpace>
577 {
578         CondSpace( const CondSet &condSet )
579                 : condSet(condSet) {}
580         
581         const CondSet &getKey() { return condSet; }
582
583         CondSet condSet;
584         Key baseKey;
585         long condSpaceId;
586 };
587
588 typedef Vector<CondSpace*> CondSpaceVect;
589
590 typedef AvlTree<CondSpace, CondSet, CmpCondSet> CondSpaceMap;
591
592 struct StateCond
593 {
594         StateCond( Key lowKey, Key highKey ) :
595                 lowKey(lowKey), highKey(highKey) {}
596
597         Key lowKey;
598         Key highKey;
599         CondSpace *condSpace;
600
601         StateCond *prev, *next;
602 };
603
604 typedef DList<StateCond> StateCondList;
605 typedef Vector<long> LongVect;
606
607 struct Expansion
608 {
609         Expansion( Key lowKey, Key highKey ) :
610                 lowKey(lowKey), highKey(highKey),
611                 fromTrans(0), fromCondSpace(0), 
612                 toCondSpace(0) {}
613         
614         ~Expansion()
615         {
616                 if ( fromTrans != 0 )
617                         delete fromTrans;
618         }
619
620         Key lowKey;
621         Key highKey;
622
623         TransAp *fromTrans;
624         CondSpace *fromCondSpace;
625         long fromVals;
626
627         CondSpace *toCondSpace;
628         LongVect toValsList;
629
630         Expansion *prev, *next;
631 };
632
633 typedef DList<Expansion> ExpansionList;
634
635 struct Removal
636 {
637         Key lowKey;
638         Key highKey;
639
640         Removal *next;
641 };
642
643 struct CondData
644 {
645         CondData() : lastCondKey(0) {}
646
647         /* Condition info. */
648         Key lastCondKey;
649
650         CondSpaceMap condSpaceMap;
651 };
652
653 extern CondData *condData;
654
655 struct FsmConstructFail
656 {
657         enum Reason
658         {
659                 CondNoKeySpace
660         };
661
662         FsmConstructFail( Reason reason ) 
663                 : reason(reason) {}
664         Reason reason;
665 };
666
667 /* State class that implements actions and priorities. */
668 struct StateAp 
669 {
670         StateAp();
671         StateAp(const StateAp &other);
672         ~StateAp();
673
674         /* Is the state final? */
675         bool isFinState() { return stateBits & SB_ISFINAL; }
676
677         /* Out transition list and the pointer for the default out trans. */
678         TransList outList;
679
680         /* In transition Lists. */
681         TransInList inList;
682
683         /* Set only during scanner construction when actions are added. NFA to DFA
684          * code can ignore this. */
685         StateAp *eofTarget;
686
687         /* Entry points into the state. */
688         EntryIdSet entryIds;
689
690         /* Epsilon transitions. */
691         EpsilonTrans epsilonTrans;
692
693         /* Condition info. */
694         StateCondList stateCondList;
695
696         /* Number of in transitions from states other than ourselves. */
697         int foreignInTrans;
698
699         /* Temporary data for various algorithms. */
700         union {
701                 /* When duplicating the fsm we need to map each 
702                  * state to the new state representing it. */
703                 StateAp *stateMap;
704
705                 /* When minimizing machines by partitioning, this maps to the group
706                  * the state is in. */
707                 MinPartition *partition;
708
709                 /* When merging states (state machine operations) this next pointer is
710                  * used for the list of states that need to be filled in. */
711                 StateAp *next;
712
713                 /* Identification for printing and stable minimization. */
714                 int stateNum;
715
716         } alg;
717
718         /* Data used in epsilon operation, maybe fit into alg? */
719         StateAp *isolatedShadow;
720         int owningGraph;
721
722         /* A pointer to a dict element that contains the set of states this state
723          * represents. This cannot go into alg, because alg.next is used during
724          * the merging process. */
725         StateDictEl *stateDictEl;
726
727         /* When drawing epsilon transitions, holds the list of states to merge
728          * with. */
729         EptVect *eptVect;
730
731         /* Bits controlling the behaviour of the state during collapsing to dfa. */
732         int stateBits;
733
734         /* State list elements. */
735         StateAp *next, *prev;
736
737         /* 
738          * Priority and Action data.
739          */
740
741         /* Out priorities transfered to out transitions. */
742         PriorTable outPriorTable;
743
744         /* The following two action tables are distinguished by the fact that when
745          * toState actions are executed immediatly after transition actions of
746          * incoming transitions and the current character will be the same as the
747          * one available then. The fromState actions are executed immediately
748          * before the transition actions of outgoing transitions and the current
749          * character is same as the one available then. */
750
751         /* Actions to execute upon entering into a state. */
752         ActionTable toStateActionTable;
753
754         /* Actions to execute when going from the state to the transition. */
755         ActionTable fromStateActionTable;
756
757         /* Actions to add to any future transitions that leave via this state. */
758         ActionTable outActionTable;
759
760         /* Conditions to add to any future transiions that leave via this sttate. */
761         OutCondSet outCondSet;
762
763         /* Error action tables. */
764         ErrActionTable errActionTable;
765
766         /* Actions to execute on eof. */
767         ActionTable eofActionTable;
768
769         /* Set of longest match items that may be active in this state. */
770         LmItemSet lmItemSet;
771 };
772
773 template <class ListItem> struct NextTrans
774 {
775         Key lowKey, highKey;
776         ListItem *trans;
777         ListItem *next;
778
779         void load() {
780                 if ( trans == 0 )
781                         next = 0;
782                 else {
783                         next = trans->next;
784                         lowKey = trans->lowKey;
785                         highKey = trans->highKey;
786                 }
787         }
788
789         void set( ListItem *t ) {
790                 trans = t;
791                 load();
792         }
793
794         void increment() {
795                 trans = next;
796                 load();
797         }
798 };
799
800
801 /* Encodes the different states that are meaningful to the of the iterator. */
802 enum PairIterUserState
803 {
804         RangeInS1, RangeInS2,
805         RangeOverlap,
806         BreakS1, BreakS2
807 };
808
809 template <class ListItem1, class ListItem2 = ListItem1> struct PairIter
810 {
811         /* Encodes the different states that an fsm iterator can be in. */
812         enum IterState {
813                 Begin,
814                 ConsumeS1Range, ConsumeS2Range,
815                 OnlyInS1Range,  OnlyInS2Range,
816                 S1SticksOut,    S1SticksOutBreak,
817                 S2SticksOut,    S2SticksOutBreak,
818                 S1DragsBehind,  S1DragsBehindBreak,
819                 S2DragsBehind,  S2DragsBehindBreak,
820                 ExactOverlap,   End
821         };
822
823         PairIter( ListItem1 *list1, ListItem2 *list2 );
824         
825         /* Query iterator. */
826         bool lte() { return itState != End; }
827         bool end() { return itState == End; }
828         void operator++(int) { findNext(); }
829         void operator++()    { findNext(); }
830
831         /* Iterator state. */
832         ListItem1 *list1;
833         ListItem2 *list2;
834         IterState itState;
835         PairIterUserState userState;
836
837         NextTrans<ListItem1> s1Tel;
838         NextTrans<ListItem2> s2Tel;
839         Key bottomLow, bottomHigh;
840         ListItem1 *bottomTrans1;
841         ListItem2 *bottomTrans2;
842
843 private:
844         void findNext();
845 };
846
847 /* Init the iterator by advancing to the first item. */
848 template <class ListItem1, class ListItem2> PairIter<ListItem1, ListItem2>::PairIter( 
849                 ListItem1 *list1, ListItem2 *list2 )
850 :
851         list1(list1),
852         list2(list2),
853         itState(Begin)
854 {
855         findNext();
856 }
857
858 /* Return and re-entry for the co-routine iterators. This should ALWAYS be
859  * used inside of a block. */
860 #define CO_RETURN(label) \
861         itState = label; \
862         return; \
863         entry##label: backIn = true
864
865 /* Return and re-entry for the co-routine iterators. This should ALWAYS be
866  * used inside of a block. */
867 #define CO_RETURN2(label, uState) \
868         itState = label; \
869         userState = uState; \
870         return; \
871         entry##label: backIn = true
872
873 /* Advance to the next transition. When returns, trans points to the next
874  * transition, unless there are no more, in which case end() returns true. */
875 template <class ListItem1, class ListItem2> void PairIter<ListItem1, ListItem2>::findNext()
876 {
877         /* This variable is used in dummy statements that follow the entry
878          * goto labels. The compiler needs some statement to follow the label. */
879         bool backIn;
880
881         /* Jump into the iterator routine base on the iterator state. */
882         switch ( itState ) {
883                 case Begin:              goto entryBegin;
884                 case ConsumeS1Range:     goto entryConsumeS1Range;
885                 case ConsumeS2Range:     goto entryConsumeS2Range;
886                 case OnlyInS1Range:      goto entryOnlyInS1Range;
887                 case OnlyInS2Range:      goto entryOnlyInS2Range;
888                 case S1SticksOut:        goto entryS1SticksOut;
889                 case S1SticksOutBreak:   goto entryS1SticksOutBreak;
890                 case S2SticksOut:        goto entryS2SticksOut;
891                 case S2SticksOutBreak:   goto entryS2SticksOutBreak;
892                 case S1DragsBehind:      goto entryS1DragsBehind;
893                 case S1DragsBehindBreak: goto entryS1DragsBehindBreak;
894                 case S2DragsBehind:      goto entryS2DragsBehind;
895                 case S2DragsBehindBreak: goto entryS2DragsBehindBreak;
896                 case ExactOverlap:       goto entryExactOverlap;
897                 case End:                goto entryEnd;
898         }
899
900 entryBegin:
901         /* Set up the next structs at the head of the transition lists. */
902         s1Tel.set( list1 );
903         s2Tel.set( list2 );
904
905         /* Concurrently scan both out ranges. */
906         while ( true ) {
907                 if ( s1Tel.trans == 0 ) {
908                         /* We are at the end of state1's ranges. Process the rest of
909                          * state2's ranges. */
910                         while ( s2Tel.trans != 0 ) {
911                                 /* Range is only in s2. */
912                                 CO_RETURN2( ConsumeS2Range, RangeInS2 );
913                                 s2Tel.increment();
914                         }
915                         break;
916                 }
917                 else if ( s2Tel.trans == 0 ) {
918                         /* We are at the end of state2's ranges. Process the rest of
919                          * state1's ranges. */
920                         while ( s1Tel.trans != 0 ) {
921                                 /* Range is only in s1. */
922                                 CO_RETURN2( ConsumeS1Range, RangeInS1 );
923                                 s1Tel.increment();
924                         }
925                         break;
926                 }
927                 /* Both state1's and state2's transition elements are good.
928                  * The signiture of no overlap is a back key being in front of a
929                  * front key. */
930                 else if ( s1Tel.highKey < s2Tel.lowKey ) {
931                         /* A range exists in state1 that does not overlap with state2. */
932                         CO_RETURN2( OnlyInS1Range, RangeInS1 );
933                         s1Tel.increment();
934                 }
935                 else if ( s2Tel.highKey < s1Tel.lowKey ) {
936                         /* A range exists in state2 that does not overlap with state1. */
937                         CO_RETURN2( OnlyInS2Range, RangeInS2 );
938                         s2Tel.increment();
939                 }
940                 /* There is overlap, must mix the ranges in some way. */
941                 else if ( s1Tel.lowKey < s2Tel.lowKey ) {
942                         /* Range from state1 sticks out front. Must break it into
943                          * non-overlaping and overlaping segments. */
944                         bottomLow = s2Tel.lowKey;
945                         bottomHigh = s1Tel.highKey;
946                         s1Tel.highKey = s2Tel.lowKey;
947                         s1Tel.highKey.decrement();
948                         bottomTrans1 = s1Tel.trans;
949
950                         /* Notify the caller that we are breaking s1. This gives them a
951                          * chance to duplicate s1Tel[0,1].value. */
952                         CO_RETURN2( S1SticksOutBreak, BreakS1 );
953
954                         /* Broken off range is only in s1. */
955                         CO_RETURN2( S1SticksOut, RangeInS1 );
956
957                         /* Advance over the part sticking out front. */
958                         s1Tel.lowKey = bottomLow;
959                         s1Tel.highKey = bottomHigh;
960                         s1Tel.trans = bottomTrans1;
961                 }
962                 else if ( s2Tel.lowKey < s1Tel.lowKey ) {
963                         /* Range from state2 sticks out front. Must break it into
964                          * non-overlaping and overlaping segments. */
965                         bottomLow = s1Tel.lowKey;
966                         bottomHigh = s2Tel.highKey;
967                         s2Tel.highKey = s1Tel.lowKey;
968                         s2Tel.highKey.decrement();
969                         bottomTrans2 = s2Tel.trans;
970
971                         /* Notify the caller that we are breaking s2. This gives them a
972                          * chance to duplicate s2Tel[0,1].value. */
973                         CO_RETURN2( S2SticksOutBreak, BreakS2 );
974
975                         /* Broken off range is only in s2. */
976                         CO_RETURN2( S2SticksOut, RangeInS2 );
977
978                         /* Advance over the part sticking out front. */
979                         s2Tel.lowKey = bottomLow;
980                         s2Tel.highKey = bottomHigh;
981                         s2Tel.trans = bottomTrans2;
982                 }
983                 /* Low ends are even. Are the high ends even? */
984                 else if ( s1Tel.highKey < s2Tel.highKey ) {
985                         /* Range from state2 goes longer than the range from state1. We
986                          * must break the range from state2 into an evenly overlaping
987                          * segment. */
988                         bottomLow = s1Tel.highKey;
989                         bottomLow.increment();
990                         bottomHigh = s2Tel.highKey;
991                         s2Tel.highKey = s1Tel.highKey;
992                         bottomTrans2 = s2Tel.trans;
993
994                         /* Notify the caller that we are breaking s2. This gives them a
995                          * chance to duplicate s2Tel[0,1].value. */
996                         CO_RETURN2( S2DragsBehindBreak, BreakS2 );
997
998                         /* Breaking s2 produces exact overlap. */
999                         CO_RETURN2( S2DragsBehind, RangeOverlap );
1000
1001                         /* Advance over the front we just broke off of range 2. */
1002                         s2Tel.lowKey = bottomLow;
1003                         s2Tel.highKey = bottomHigh;
1004                         s2Tel.trans = bottomTrans2;
1005
1006                         /* Advance over the entire s1Tel. We have consumed it. */
1007                         s1Tel.increment();
1008                 }
1009                 else if ( s2Tel.highKey < s1Tel.highKey ) {
1010                         /* Range from state1 goes longer than the range from state2. We
1011                          * must break the range from state1 into an evenly overlaping
1012                          * segment. */
1013                         bottomLow = s2Tel.highKey;
1014                         bottomLow.increment();
1015                         bottomHigh = s1Tel.highKey;
1016                         s1Tel.highKey = s2Tel.highKey;
1017                         bottomTrans1 = s1Tel.trans;
1018
1019                         /* Notify the caller that we are breaking s1. This gives them a
1020                          * chance to duplicate s2Tel[0,1].value. */
1021                         CO_RETURN2( S1DragsBehindBreak, BreakS1 );
1022
1023                         /* Breaking s1 produces exact overlap. */
1024                         CO_RETURN2( S1DragsBehind, RangeOverlap );
1025
1026                         /* Advance over the front we just broke off of range 1. */
1027                         s1Tel.lowKey = bottomLow;
1028                         s1Tel.highKey = bottomHigh;
1029                         s1Tel.trans = bottomTrans1;
1030
1031                         /* Advance over the entire s2Tel. We have consumed it. */
1032                         s2Tel.increment();
1033                 }
1034                 else {
1035                         /* There is an exact overlap. */
1036                         CO_RETURN2( ExactOverlap, RangeOverlap );
1037
1038                         s1Tel.increment();
1039                         s2Tel.increment();
1040                 }
1041         }
1042
1043         /* Done, go into end state. */
1044         CO_RETURN( End );
1045 }
1046
1047
1048 /* Compare lists of epsilon transitions. Entries are name ids of targets. */
1049 typedef CmpTable< int, CmpOrd<int> > CmpEpsilonTrans;
1050
1051 /* Compare class for the Approximate minimization. */
1052 class ApproxCompare
1053 {
1054 public:
1055         ApproxCompare() { }
1056         int compare( const StateAp *pState1, const StateAp *pState2 );
1057 };
1058
1059 /* Compare class for the initial partitioning of a partition minimization. */
1060 class InitPartitionCompare
1061 {
1062 public:
1063         InitPartitionCompare() { }
1064         int compare( const StateAp *pState1, const StateAp *pState2 );
1065 };
1066
1067 /* Compare class for the regular partitioning of a partition minimization. */
1068 class PartitionCompare
1069 {
1070 public:
1071         PartitionCompare() { }
1072         int compare( const StateAp *pState1, const StateAp *pState2 );
1073 };
1074
1075 /* Compare class for a minimization that marks pairs. Provides the shouldMark
1076  * routine. */
1077 class MarkCompare
1078 {
1079 public:
1080         MarkCompare() { }
1081         bool shouldMark( MarkIndex &markIndex, const StateAp *pState1, 
1082                         const StateAp *pState2 );
1083 };
1084
1085 /* List of partitions. */
1086 typedef DList< MinPartition > PartitionList;
1087
1088 /* List of transtions out of a state. */
1089 typedef Vector<TransEl> TransListVect;
1090
1091 /* Entry point map used for keeping track of entry points in a machine. */
1092 typedef BstSet< int > EntryIdSet;
1093 typedef BstMapEl< int, StateAp* > EntryMapEl;
1094 typedef BstMap< int, StateAp* > EntryMap;
1095 typedef Vector<EntryMapEl> EntryMapBase;
1096
1097 /* Graph class that implements actions and priorities. */
1098 struct FsmAp 
1099 {
1100         /* Constructors/Destructors. */
1101         FsmAp( );
1102         FsmAp( const FsmAp &graph );
1103         ~FsmAp();
1104
1105         /* The list of states. */
1106         StateList stateList;
1107         StateList misfitList;
1108
1109         /* The map of entry points. */
1110         EntryMap entryPoints;
1111
1112         /* The start state. */
1113         StateAp *startState;
1114
1115         /* Error state, possibly created only when the final machine has been
1116          * created and the XML machine is about to be written. No transitions
1117          * point to this state. */
1118         StateAp *errState;
1119
1120         /* The set of final states. */
1121         StateSet finStateSet;
1122
1123         /* Misfit Accounting. Are misfits put on a separate list. */
1124         bool misfitAccounting;
1125
1126         /*
1127          * Transition actions and priorities.
1128          */
1129
1130         /* Set priorities on transtions. */
1131         void startFsmPrior( int ordering, PriorDesc *prior );
1132         void allTransPrior( int ordering, PriorDesc *prior );
1133         void finishFsmPrior( int ordering, PriorDesc *prior );
1134         void leaveFsmPrior( int ordering, PriorDesc *prior );
1135
1136         /* Action setting support. */
1137         void transferOutActions( StateAp *state );
1138         void transferErrorActions( StateAp *state, int transferPoint );
1139         void setErrorAction( StateAp *state, int ordering, Action *action );
1140
1141         /* Fill all spaces in a transition list with an error transition. */
1142         void fillGaps( StateAp *state );
1143
1144         /* Similar to setErrorAction, instead gives a state to go to on error. */
1145         void setErrorTarget( StateAp *state, StateAp *target, int *orderings, 
1146                         Action **actions, int nActs );
1147
1148         /* Set actions to execute. */
1149         void startFsmAction( int ordering, Action *action );
1150         void allTransAction( int ordering, Action *action );
1151         void finishFsmAction( int ordering, Action *action );
1152         void leaveFsmAction( int ordering, Action *action );
1153         void longMatchAction( int ordering, LongestMatchPart *lmPart );
1154
1155         /* Set conditions. */
1156         CondSpace *addCondSpace( const CondSet &condSet );
1157
1158         void findEmbedExpansions( ExpansionList &expansionList, 
1159                 StateAp *destState, Action *condAction, bool sense );
1160         void embedCondition( MergeData &md, StateAp *state, Action *condAction, bool sense );
1161         void embedCondition( StateAp *state, Action *condAction, bool sense );
1162
1163         void startFsmCondition( Action *condAction, bool sense );
1164         void allTransCondition( Action *condAction, bool sense );
1165         void leaveFsmCondition( Action *condAction, bool sense );
1166
1167         /* Set error actions to execute. */
1168         void startErrorAction( int ordering, Action *action, int transferPoint );
1169         void allErrorAction( int ordering, Action *action, int transferPoint );
1170         void finalErrorAction( int ordering, Action *action, int transferPoint );
1171         void notStartErrorAction( int ordering, Action *action, int transferPoint );
1172         void notFinalErrorAction( int ordering, Action *action, int transferPoint );
1173         void middleErrorAction( int ordering, Action *action, int transferPoint );
1174
1175         /* Set EOF actions. */
1176         void startEOFAction( int ordering, Action *action );
1177         void allEOFAction( int ordering, Action *action );
1178         void finalEOFAction( int ordering, Action *action );
1179         void notStartEOFAction( int ordering, Action *action );
1180         void notFinalEOFAction( int ordering, Action *action );
1181         void middleEOFAction( int ordering, Action *action );
1182
1183         /* Set To State actions. */
1184         void startToStateAction( int ordering, Action *action );
1185         void allToStateAction( int ordering, Action *action );
1186         void finalToStateAction( int ordering, Action *action );
1187         void notStartToStateAction( int ordering, Action *action );
1188         void notFinalToStateAction( int ordering, Action *action );
1189         void middleToStateAction( int ordering, Action *action );
1190
1191         /* Set From State actions. */
1192         void startFromStateAction( int ordering, Action *action );
1193         void allFromStateAction( int ordering, Action *action );
1194         void finalFromStateAction( int ordering, Action *action );
1195         void notStartFromStateAction( int ordering, Action *action );
1196         void notFinalFromStateAction( int ordering, Action *action );
1197         void middleFromStateAction( int ordering, Action *action );
1198
1199         /* Shift the action ordering of the start transitions to start at
1200          * fromOrder and increase in units of 1. Useful before kleene star
1201          * operation.  */
1202         int shiftStartActionOrder( int fromOrder );
1203
1204         /* Clear all priorities from the fsm to so they won't affcet minimization
1205          * of the final fsm. */
1206         void clearAllPriorities();
1207
1208         /* Zero out all the function keys. */
1209         void nullActionKeys();
1210
1211         /* Walk the list of states and verify state properties. */
1212         void verifyStates();
1213
1214         /* Misfit Accounting. Are misfits put on a separate list. */
1215         void setMisfitAccounting( bool val ) 
1216                 { misfitAccounting = val; }
1217
1218         /* Set and Unset a state as final. */
1219         void setFinState( StateAp *state );
1220         void unsetFinState( StateAp *state );
1221
1222         void setStartState( StateAp *state );
1223         void unsetStartState( );
1224         
1225         /* Set and unset a state as an entry point. */
1226         void setEntry( int id, StateAp *state );
1227         void changeEntry( int id, StateAp *to, StateAp *from );
1228         void unsetEntry( int id, StateAp *state );
1229         void unsetEntry( int id );
1230         void unsetAllEntryPoints();
1231
1232         /* Epsilon transitions. */
1233         void epsilonTrans( int id );
1234         void shadowReadWriteStates( MergeData &md );
1235
1236         /*
1237          * Basic attaching and detaching.
1238          */
1239
1240         /* Common to attaching/detaching list and default. */
1241         void attachToInList( StateAp *from, StateAp *to, TransAp *&head, TransAp *trans );
1242         void detachFromInList( StateAp *from, StateAp *to, TransAp *&head, TransAp *trans );
1243
1244         /* Attach with a new transition. */
1245         TransAp *attachNewTrans( StateAp *from, StateAp *to,
1246                         Key onChar1, Key onChar2 );
1247
1248         /* Attach with an existing transition that already in an out list. */
1249         void attachTrans( StateAp *from, StateAp *to, TransAp *trans );
1250         
1251         /* Redirect a transition away from error and towards some state. */
1252         void redirectErrorTrans( StateAp *from, StateAp *to, TransAp *trans );
1253
1254         /* Detach a transition from a target state. */
1255         void detachTrans( StateAp *from, StateAp *to, TransAp *trans );
1256
1257         /* Detach a state from the graph. */
1258         void detachState( StateAp *state );
1259
1260         /*
1261          * NFA to DFA conversion routines.
1262          */
1263
1264         /* Duplicate a transition that will dropin to a free spot. */
1265         TransAp *dupTrans( StateAp *from, TransAp *srcTrans );
1266
1267         /* In crossing, two transitions both go to real states. */
1268         TransAp *fsmAttachStates( MergeData &md, StateAp *from,
1269                         TransAp *destTrans, TransAp *srcTrans );
1270
1271         /* Two transitions are to be crossed, handle the possibility of either
1272          * going to the error state. */
1273         TransAp *mergeTrans( MergeData &md, StateAp *from,
1274                         TransAp *destTrans, TransAp *srcTrans );
1275
1276         /* Compare deterimne relative priorities of two transition tables. */
1277         int comparePrior( const PriorTable &priorTable1, const PriorTable &priorTable2 );
1278
1279         /* Cross a src transition with one that is already occupying a spot. */
1280         TransAp *crossTransitions( MergeData &md, StateAp *from,
1281                         TransAp *destTrans, TransAp *srcTrans );
1282
1283         void outTransCopy( MergeData &md, StateAp *dest, TransAp *srcList );
1284
1285         void doRemove( MergeData &md, StateAp *destState, ExpansionList &expList1 );
1286         void doExpand( MergeData &md, StateAp *destState, ExpansionList &expList1 );
1287         void findCondExpInTrans( ExpansionList &expansionList, StateAp *state, 
1288                         Key lowKey, Key highKey, CondSpace *fromCondSpace, CondSpace *toCondSpace,
1289                         long destVals, LongVect &toValsList );
1290         void findTransExpansions( ExpansionList &expansionList, 
1291                         StateAp *destState, StateAp *srcState );
1292         void findCondExpansions( ExpansionList &expansionList, 
1293                         StateAp *destState, StateAp *srcState );
1294         void mergeStateConds( StateAp *destState, StateAp *srcState );
1295
1296         /* Merge a set of states into newState. */
1297         void mergeStates( MergeData &md, StateAp *destState, 
1298                         StateAp **srcStates, int numSrc );
1299         void mergeStatesLeaving( MergeData &md, StateAp *destState, StateAp *srcState );
1300         void mergeStates( MergeData &md, StateAp *destState, StateAp *srcState );
1301
1302         /* Make all states that are combinations of other states and that
1303          * have not yet had their out transitions filled in. This will 
1304          * empty out stateDict and stFil. */
1305         void fillInStates( MergeData &md );
1306
1307         /*
1308          * Transition Comparison.
1309          */
1310
1311         /* Compare transition data. Either of the pointers may be null. */
1312         static inline int compareDataPtr( TransAp *trans1, TransAp *trans2 );
1313
1314         /* Compare target state and transition data. Either pointer may be null. */
1315         static inline int compareFullPtr( TransAp *trans1, TransAp *trans2 );
1316
1317         /* Compare target partitions. Either pointer may be null. */
1318         static inline int comparePartPtr( TransAp *trans1, TransAp *trans2 );
1319
1320         /* Check marked status of target states. Either pointer may be null. */
1321         static inline bool shouldMarkPtr( MarkIndex &markIndex, 
1322                         TransAp *trans1, TransAp *trans2 );
1323
1324         /*
1325          * Callbacks.
1326          */
1327
1328         /* Compare priority and function table of transitions. */
1329         static int compareTransData( TransAp *trans1, TransAp *trans2 );
1330
1331         /* Add in the properties of srcTrans into this. */
1332         void addInTrans( TransAp *destTrans, TransAp *srcTrans );
1333
1334         /* Compare states on data stored in the states. */
1335         static int compareStateData( const StateAp *state1, const StateAp *state2 );
1336
1337         /* Out transition data. */
1338         void clearOutData( StateAp *state );
1339         bool hasOutData( StateAp *state );
1340         void transferOutData( StateAp *destState, StateAp *srcState );
1341
1342         /*
1343          * Allocation.
1344          */
1345
1346         /* New up a state and add it to the graph. */
1347         StateAp *addState();
1348
1349         /*
1350          * Building basic machines
1351          */
1352
1353         void concatFsm( Key c );
1354         void concatFsm( Key *str, int len );
1355         void concatFsmCI( Key *str, int len );
1356         void orFsm( Key *set, int len );
1357         void rangeFsm( Key low, Key high );
1358         void rangeStarFsm( Key low, Key high );
1359         void emptyFsm( );
1360         void lambdaFsm( );
1361
1362         /*
1363          * Fsm operators.
1364          */
1365
1366         void starOp( );
1367         void repeatOp( int times );
1368         void optionalRepeatOp( int times );
1369         void concatOp( FsmAp *other );
1370         void unionOp( FsmAp *other );
1371         void intersectOp( FsmAp *other );
1372         void subtractOp( FsmAp *other );
1373         void epsilonOp();
1374         void joinOp( int startId, int finalId, FsmAp **others, int numOthers );
1375         void globOp( FsmAp **others, int numOthers );
1376         void deterministicEntry();
1377
1378         /*
1379          * Operator workers
1380          */
1381
1382         /* Determine if there are any entry points into a start state other than
1383          * the start state. */
1384         bool isStartStateIsolated();
1385
1386         /* Make a new start state that has no entry points. Will not change the
1387          * identity of the fsm. */
1388         void isolateStartState();
1389
1390         /* Workers for resolving epsilon transitions. */
1391         bool inEptVect( EptVect *eptVect, StateAp *targ );
1392         void epsilonFillEptVectFrom( StateAp *root, StateAp *from, bool parentLeaving );
1393         void resolveEpsilonTrans( MergeData &md );
1394
1395         /* Workers for concatenation and union. */
1396         void doConcat( FsmAp *other, StateSet *fromStates, bool optional );
1397         void doOr( FsmAp *other );
1398
1399         /*
1400          * Final states
1401          */
1402
1403         /* Unset any final states that are no longer to be final 
1404          * due to final bits. */
1405         void unsetIncompleteFinals();
1406         void unsetKilledFinals();
1407
1408         /* Bring in other's entry points. Assumes others states are going to be
1409          * copied into this machine. */
1410         void copyInEntryPoints( FsmAp *other );
1411
1412         /* Ordering states. */
1413         void depthFirstOrdering( StateAp *state );
1414         void depthFirstOrdering();
1415         void sortStatesByFinal();
1416
1417         /* Set sqequential state numbers starting at 0. */
1418         void setStateNumbers( int base );
1419
1420         /* Unset all final states. */
1421         void unsetAllFinStates();
1422
1423         /* Set the bits of final states and clear the bits of non final states. */
1424         void setFinBits( int finStateBits );
1425
1426         /*
1427          * Self-consistency checks.
1428          */
1429
1430         /* Run a sanity check on the machine. */
1431         void verifyIntegrity();
1432
1433         /* Verify that there are no unreachable states, or dead end states. */
1434         void verifyReachability();
1435         void verifyNoDeadEndStates();
1436
1437         /*
1438          * Path pruning
1439          */
1440
1441         /* Mark all states reachable from state. */
1442         void markReachableFromHereReverse( StateAp *state );
1443
1444         /* Mark all states reachable from state. */
1445         void markReachableFromHere( StateAp *state );
1446         void markReachableFromHereStopFinal( StateAp *state );
1447
1448         /* Removes states that cannot be reached by any path in the fsm and are
1449          * thus wasted silicon. */
1450         void removeDeadEndStates();
1451
1452         /* Removes states that cannot be reached by any path in the fsm and are
1453          * thus wasted silicon. */
1454         void removeUnreachableStates();
1455
1456         /* Remove error actions from states on which the error transition will
1457          * never be taken. */
1458         bool outListCovers( StateAp *state );
1459         bool anyErrorRange( StateAp *state );
1460
1461         /* Remove states that are on the misfit list. */
1462         void removeMisfits();
1463
1464         /*
1465          * FSM Minimization
1466          */
1467
1468         /* Minimization by partitioning. */
1469         void minimizePartition1();
1470         void minimizePartition2();
1471
1472         /* Minimize the final state Machine. The result is the minimal fsm. Slow
1473          * but stable, correct minimization. Uses n^2 space (lookout) and average
1474          * n^2 time. Worst case n^3 time, but a that is a very rare case. */
1475         void minimizeStable();
1476
1477         /* Minimize the final state machine. Does not find the minimal fsm, but a
1478          * pretty good approximation. Does not use any extra space. Average n^2
1479          * time. Worst case n^3 time, but a that is a very rare case. */
1480         void minimizeApproximate();
1481
1482         /* This is the worker for the minimize approximate solution. It merges
1483          * states that have identical out transitions. */
1484         bool minimizeRound( );
1485
1486         /* Given an intial partioning of states, split partitions that have out trans
1487          * to differing partitions. */
1488         int partitionRound( StateAp **statePtrs, MinPartition *parts, int numParts );
1489
1490         /* Split partitions that have a transition to a previously split partition, until
1491          * there are no more partitions to split. */
1492         int splitCandidates( StateAp **statePtrs, MinPartition *parts, int numParts );
1493
1494         /* Fuse together states in the same partition. */
1495         void fusePartitions( MinPartition *parts, int numParts );
1496
1497         /* Mark pairs where out final stateness differs, out trans data differs,
1498          * trans pairs go to a marked pair or trans data differs. Should get 
1499          * alot of pairs. */
1500         void initialMarkRound( MarkIndex &markIndex );
1501
1502         /* One marking round on all state pairs. Considers if trans pairs go
1503          * to a marked state only. Returns whether or not a pair was marked. */
1504         bool markRound( MarkIndex &markIndex );
1505
1506         /* Move the in trans into src into dest. */
1507         void inTransMove(StateAp *dest, StateAp *src);
1508         
1509         /* Make state src and dest the same state. */
1510         void fuseEquivStates(StateAp *dest, StateAp *src);
1511
1512         /* Find any states that didn't get marked by the marking algorithm and
1513          * merge them into the primary states of their equivalence class. */
1514         void fuseUnmarkedPairs( MarkIndex &markIndex );
1515
1516         /* Merge neighboring transitions go to the same state and have the same
1517          * transitions data. */
1518         void compressTransitions();
1519
1520         /* Returns true if there is a transtion (either explicit or by a gap) to
1521          * the error state. */
1522         bool checkErrTrans( StateAp *state, TransAp *trans );
1523         bool checkErrTransFinish( StateAp *state );
1524         bool hasErrorTrans();
1525
1526         /* Check if a machine defines a single character. This is useful in
1527          * validating ranges and machines to export. */
1528         bool checkSingleCharMachine( );
1529 };
1530
1531
1532 #endif /* _FSMGRAPH_H */