2 * Copyright 2001-2006 Adrian Thurston <thurston@complang.org>
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
38 #include "mergesort.h"
41 #include "sbsttable.h"
44 #define TRANS_ERR_TRANS 0
45 #define STATE_ERR_STATE 0
46 #define FUNC_NO_FUNC 0
61 Text, Goto, Call, Next, GotoExpr, CallExpr, NextExpr, Ret,
62 PChar, Char, Hold, Exec, Curs, Targs, Entry,
63 LmSwitch, LmSetActId, LmSetTokEnd, LmGetTokEnd, LmInitTokStart,
64 LmInitAct, LmSetTokStart, SubAction, Break
67 GenInlineItem( const InputLoc &loc, Type type ) :
68 loc(loc), data(0), targId(0), targState(0),
69 lmId(0), children(0), offset(0),
75 RedStateAp *targState;
77 GenInlineList *children;
81 GenInlineItem *prev, *next;
84 /* Normally this would be atypedef, but that would entail including DList from
85 * ptreetypes, which should be just typedef forwards. */
86 struct GenInlineList : public DList<GenInlineItem> { };
88 /* Element in list of actions. Contains the string for the code to exectute. */
91 public DListEl<GenAction>
105 /* Data collected during parse. */
108 GenInlineList *inlineList;
113 /* Number of references in the final machine. */
115 { return numTransRefs + numToStateRefs + numFromStateRefs + numEofRefs; }
118 int numFromStateRefs;
127 /* Transistion GenAction Element. */
128 typedef SBstMapEl< int, GenAction* > GenActionTableEl;
130 /* Transition GenAction Table. */
131 struct GenActionTable
132 : public SBstMap< int, GenAction*, CmpOrd<int> >
134 void setAction( int ordering, GenAction *action );
135 void setActions( int *orderings, GenAction **actions, int nActs );
136 void setActions( const GenActionTable &other );
139 /* Compare of a whole action table element (key & value). */
140 struct CmpGenActionTableEl
142 static int compare( const GenActionTableEl &action1,
143 const GenActionTableEl &action2 )
145 if ( action1.key < action2.key )
147 else if ( action1.key > action2.key )
149 else if ( action1.value < action2.value )
151 else if ( action1.value > action2.value )
157 /* Compare for GenActionTable. */
158 typedef CmpSTable< GenActionTableEl, CmpGenActionTableEl > CmpGenActionTable;
161 typedef BstSet<RedStateAp*> RedStateSet;
162 typedef BstSet<int> IntSet;
164 /* Reduced action. */
167 public AvlTreeEl<RedAction>
178 bAnyCurStateRef(false),
182 const GenActionTable &getKey()
190 /* Number of references in the final machine. */
192 { return numTransRefs + numToStateRefs + numFromStateRefs + numEofRefs; }
195 int numFromStateRefs;
198 bool anyNextStmt() { return bAnyNextStmt; }
199 bool anyCurStateRef() { return bAnyCurStateRef; }
200 bool anyBreakStmt() { return bAnyBreakStmt; }
203 bool bAnyCurStateRef;
206 typedef AvlTree<RedAction, GenActionTable, CmpGenActionTable> GenActionTableMap;
208 /* Reduced transition. */
211 public AvlTreeEl<RedTransAp>
213 RedTransAp( RedStateAp *targ, RedAction *action, int id )
214 : targ(targ), action(action), id(id), pos(-1), labelNeeded(true) { }
220 bool partitionBoundary;
224 /* Compare of transitions for the final reduction of transitions. Comparison
225 * is on target and the pointer to the shared action table. It is assumed that
226 * when this is used the action tables have been reduced. */
229 static int compare( const RedTransAp &t1, const RedTransAp &t2 )
231 if ( t1.targ < t2.targ )
233 else if ( t1.targ > t2.targ )
235 else if ( t1.action < t2.action )
237 else if ( t1.action > t2.action )
244 typedef AvlBasic<RedTransAp, CmpRedTransAp> TransApSet;
246 /* Element in out range. */
250 RedTransEl( Key lowKey, Key highKey, RedTransAp *value )
251 : lowKey(lowKey), highKey(highKey), value(value) { }
257 typedef Vector<RedTransEl> RedTransList;
258 typedef Vector<RedStateAp*> RedStateVect;
260 typedef BstMapEl<RedStateAp*, unsigned long long> RedSpanMapEl;
261 typedef BstMap<RedStateAp*, unsigned long long> RedSpanMap;
263 /* Compare used by span map sort. Reverse sorts by the span. */
264 struct CmpRedSpanMapEl
266 static int compare( const RedSpanMapEl &smel1, const RedSpanMapEl &smel2 )
268 if ( smel1.value > smel2.value )
270 else if ( smel1.value < smel2.value )
277 /* Sorting state-span map entries by span. */
278 typedef MergeSort<RedSpanMapEl, CmpRedSpanMapEl> RedSpanMapSort;
280 /* Set of entry ids that go into this state. */
281 typedef Vector<int> EntryIdVect;
282 typedef Vector<char*> EntryNameVect;
284 typedef Vector< GenAction* > GenCondSet;
289 : key(0), baseKey(0) {}
295 Condition *next, *prev;
297 typedef DList<Condition> ConditionList;
305 GenCondSpace *next, *prev;
307 typedef DList<GenCondSpace> CondSpaceList;
314 GenCondSpace *condSpace;
316 GenStateCond *prev, *next;
318 typedef DList<GenStateCond> GenStateCondList;
319 typedef Vector<GenStateCond*> StateCondVect;
338 bAnyRegCurStateRef(false),
339 partitionBoundary(false),
344 /* Transitions out. */
345 RedTransList outSingle;
346 RedTransList outRange;
347 RedTransAp *defTrans;
349 /* For flat conditions. */
350 Key condLowKey, condHighKey;
351 GenCondSpace **condList;
355 RedTransAp **transList;
357 /* The list of states that transitions from this state go to. */
358 RedStateVect targStates;
364 RedAction *toStateAction;
365 RedAction *fromStateAction;
366 RedAction *eofAction;
367 RedTransAp *eofTrans;
369 GenStateCondList stateCondList;
370 StateCondVect stateCondVect;
372 /* Pointers for the list of states. */
373 RedStateAp *prev, *next;
375 bool anyRegCurStateRef() { return bAnyRegCurStateRef; }
376 bool bAnyRegCurStateRef;
379 bool partitionBoundary;
381 RedTransAp **inTrans;
385 /* List of states. */
386 typedef DList<RedStateAp> RedStateList;
388 /* Set of reduced transitons. Comparison is by pointer. */
389 typedef BstSet< RedTransAp*, CmpOrd<RedTransAp*> > RedTransSet;
391 /* Next version of the fsm machine. */
396 bool forcedErrorState;
401 /* Next State Id doubles as the total number of state ids. */
405 GenActionTableMap actionMap;
406 RedStateList stateList;
407 RedStateSet entryPoints;
408 RedStateAp *startState;
409 RedStateAp *errState;
410 RedTransAp *errTrans;
411 RedTransAp *errActionTrans;
412 RedStateAp *firstFinState;
416 bool bAnyToStateActions;
417 bool bAnyFromStateActions;
421 bool bAnyActionGotos;
422 bool bAnyActionCalls;
424 bool bAnyRegActionRets;
425 bool bAnyRegActionByValControl;
426 bool bAnyRegNextStmt;
427 bool bAnyRegCurStateRef;
440 unsigned long long maxSpan;
441 unsigned long long maxCondSpan;
442 int maxFlatIndexOffset;
447 int maxCondIndexOffset;
451 bool anyToStateActions() { return bAnyToStateActions; }
452 bool anyFromStateActions() { return bAnyFromStateActions; }
453 bool anyRegActions() { return bAnyRegActions; }
454 bool anyEofActions() { return bAnyEofActions; }
455 bool anyEofTrans() { return bAnyEofTrans; }
456 bool anyActionGotos() { return bAnyActionGotos; }
457 bool anyActionCalls() { return bAnyActionCalls; }
458 bool anyActionRets() { return bAnyActionRets; }
459 bool anyRegActionRets() { return bAnyRegActionRets; }
460 bool anyRegActionByValControl() { return bAnyRegActionByValControl; }
461 bool anyRegNextStmt() { return bAnyRegNextStmt; }
462 bool anyRegCurStateRef() { return bAnyRegCurStateRef; }
463 bool anyRegBreak() { return bAnyRegBreak; }
464 bool anyConditions() { return bAnyConditions; }
467 /* Is is it possible to extend a range by bumping ranges that span only
468 * one character to the singles array. */
469 bool canExtend( const RedTransList &list, int pos );
471 /* Pick single transitions from the ranges. */
472 void moveTransToSingle( RedStateAp *state );
477 /* Move a selected transition from ranges to default. */
478 void moveToDefault( RedTransAp *defTrans, RedStateAp *state );
480 /* Pick a default transition by largest span. */
481 RedTransAp *chooseDefaultSpan( RedStateAp *state );
482 void chooseDefaultSpan();
484 /* Pick a default transition by most number of ranges. */
485 RedTransAp *chooseDefaultNumRanges( RedStateAp *state );
486 void chooseDefaultNumRanges();
488 /* Pick a default transition tailored towards goto driven machine. */
489 RedTransAp *chooseDefaultGoto( RedStateAp *state );
490 void chooseDefaultGoto();
492 /* Ordering states by transition connections. */
493 void optimizeStateOrdering( RedStateAp *state );
494 void optimizeStateOrdering();
496 /* Ordering states by transition connections. */
497 void depthFirstOrdering( RedStateAp *state );
498 void depthFirstOrdering();
501 void sequentialStateIds();
502 void sortStateIdsByFinal();
504 /* Arrange states in by final id. This is a stable sort. */
505 void sortStatesByFinal();
507 /* Sorting states by id. */
508 void sortByStateId();
510 /* Locating the first final state. This is the final state with the lowest
512 void findFirstFinState();
514 void assignActionLocs();
516 RedTransAp *getErrorTrans();
517 RedStateAp *getErrorState();
519 /* Is every char in the alphabet covered? */
520 bool alphabetCovered( RedTransList &outRange );
522 RedTransAp *allocateTrans( RedStateAp *targState, RedAction *actionTable );
524 void partitionFsm( int nParts );