2 * Copyright 2001-2006 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
38 #include "mergesort.h"
41 #include "sbsttable.h"
43 #define TRANS_ERR_TRANS 0
44 #define STATE_ERR_STATE 0
45 #define FUNC_NO_FUNC 0
53 /* Location in an input file. */
67 Text
, Goto
, Call
, Next
, GotoExpr
, CallExpr
, NextExpr
, Ret
,
68 PChar
, Char
, Hold
, Exec
, Curs
, Targs
, Entry
,
69 LmSwitch
, LmSetActId
, LmSetTokEnd
, LmGetTokEnd
, LmInitTokStart
,
70 LmInitAct
, LmSetTokStart
, SubAction
, Break
73 InlineItem( const InputLoc
&loc
, Type type
) :
74 loc(loc
), data(0), targId(0), targState(0),
75 lmId(0), children(0), offset(0),
81 RedStateAp
*targState
;
87 InlineItem
*prev
, *next
;
90 /* Normally this would be atypedef, but that would entail including DList from
91 * ptreetypes, which should be just typedef forwards. */
92 struct InlineList
: public DList
<InlineItem
> { };
94 /* Element in list of actions. Contains the string for the code to exectute. */
97 public DListEl
<Action
>
111 /* Data collected during parse. */
114 InlineList
*inlineList
;
119 /* Number of references in the final machine. */
121 { return numTransRefs
+ numToStateRefs
+ numFromStateRefs
+ numEofRefs
; }
124 int numFromStateRefs
;
133 /* Transistion Action Element. */
134 typedef SBstMapEl
< int, Action
* > ActionTableEl
;
136 /* Transition Action Table. */
138 : public SBstMap
< int, Action
*, CmpOrd
<int> >
140 void setAction( int ordering
, Action
*action
);
141 void setActions( int *orderings
, Action
**actions
, int nActs
);
142 void setActions( const ActionTable
&other
);
145 /* Compare of a whole action table element (key & value). */
146 struct CmpActionTableEl
148 static int compare( const ActionTableEl
&action1
,
149 const ActionTableEl
&action2
)
151 if ( action1
.key
< action2
.key
)
153 else if ( action1
.key
> action2
.key
)
155 else if ( action1
.value
< action2
.value
)
157 else if ( action1
.value
> action2
.value
)
163 /* Compare for ActionTable. */
164 typedef CmpSTable
< ActionTableEl
, CmpActionTableEl
> CmpActionTable
;
167 typedef BstSet
<RedStateAp
*> RedStateSet
;
168 typedef BstSet
<int> IntSet
;
170 /* Reduced action. */
173 public AvlTreeEl
<RedAction
>
184 bAnyCurStateRef(false),
188 const ActionTable
&getKey()
196 /* Number of references in the final machine. */
198 { return numTransRefs
+ numToStateRefs
+ numFromStateRefs
+ numEofRefs
; }
201 int numFromStateRefs
;
204 bool anyNextStmt() { return bAnyNextStmt
; }
205 bool anyCurStateRef() { return bAnyCurStateRef
; }
206 bool anyBreakStmt() { return bAnyBreakStmt
; }
209 bool bAnyCurStateRef
;
212 typedef AvlTree
<RedAction
, ActionTable
, CmpActionTable
> ActionTableMap
;
214 /* Reduced transition. */
217 public AvlTreeEl
<RedTransAp
>
219 RedTransAp( RedStateAp
*targ
, RedAction
*action
, int id
)
220 : targ(targ
), action(action
), id(id
), labelNeeded(true) { }
225 bool partitionBoundary
;
229 /* Compare of transitions for the final reduction of transitions. Comparison
230 * is on target and the pointer to the shared action table. It is assumed that
231 * when this is used the action tables have been reduced. */
234 static int compare( const RedTransAp
&t1
, const RedTransAp
&t2
)
236 if ( t1
.targ
< t2
.targ
)
238 else if ( t1
.targ
> t2
.targ
)
240 else if ( t1
.action
< t2
.action
)
242 else if ( t1
.action
> t2
.action
)
249 typedef AvlBasic
<RedTransAp
, CmpRedTransAp
> TransApSet
;
251 /* Element in out range. */
255 RedTransEl( Key lowKey
, Key highKey
, RedTransAp
*value
)
256 : lowKey(lowKey
), highKey(highKey
), value(value
) { }
262 typedef Vector
<RedTransEl
> RedTransList
;
263 typedef Vector
<RedStateAp
*> RedStateVect
;
265 typedef BstMapEl
<RedStateAp
*, unsigned long long> RedSpanMapEl
;
266 typedef BstMap
<RedStateAp
*, unsigned long long> RedSpanMap
;
268 /* Compare used by span map sort. Reverse sorts by the span. */
269 struct CmpRedSpanMapEl
271 static int compare( const RedSpanMapEl
&smel1
, const RedSpanMapEl
&smel2
)
273 if ( smel1
.value
> smel2
.value
)
275 else if ( smel1
.value
< smel2
.value
)
282 /* Sorting state-span map entries by span. */
283 typedef MergeSort
<RedSpanMapEl
, CmpRedSpanMapEl
> RedSpanMapSort
;
285 /* Set of entry ids that go into this state. */
286 typedef Vector
<int> EntryIdVect
;
287 typedef Vector
<char*> EntryNameVect
;
289 typedef Vector
< Action
* > CondSet
;
294 : key(0), baseKey(0) {}
300 Condition
*next
, *prev
;
302 typedef DList
<Condition
> ConditionList
;
310 CondSpace
*next
, *prev
;
312 typedef DList
<CondSpace
> CondSpaceList
;
319 CondSpace
*condSpace
;
321 StateCond
*prev
, *next
;
323 typedef DList
<StateCond
> StateCondList
;
324 typedef Vector
<StateCond
*> StateCondVect
;
343 bAnyRegCurStateRef(false),
344 partitionBoundary(false),
349 /* Transitions out. */
350 RedTransList outSingle
;
351 RedTransList outRange
;
352 RedTransAp
*defTrans
;
354 /* For flat conditions. */
355 Key condLowKey
, condHighKey
;
356 CondSpace
**condList
;
360 RedTransAp
**transList
;
362 /* The list of states that transitions from this state go to. */
363 RedStateVect targStates
;
369 RedAction
*toStateAction
;
370 RedAction
*fromStateAction
;
371 RedAction
*eofAction
;
372 RedTransAp
*eofTrans
;
374 StateCondList stateCondList
;
375 StateCondVect stateCondVect
;
377 /* Pointers for the list of states. */
378 RedStateAp
*prev
, *next
;
380 bool anyRegCurStateRef() { return bAnyRegCurStateRef
; }
381 bool bAnyRegCurStateRef
;
384 bool partitionBoundary
;
386 RedTransAp
**inTrans
;
390 /* List of states. */
391 typedef DList
<RedStateAp
> RedStateList
;
393 /* Set of reduced transitons. Comparison is by pointer. */
394 typedef BstSet
< RedTransAp
*, CmpOrd
<RedTransAp
*> > RedTransSet
;
396 /* Next version of the fsm machine. */
401 bool forcedErrorState
;
406 /* Next State Id doubles as the total number of state ids. */
410 ActionTableMap actionMap
;
411 RedStateList stateList
;
412 RedStateSet entryPoints
;
413 RedStateAp
*startState
;
414 RedStateAp
*errState
;
415 RedTransAp
*errTrans
;
416 RedTransAp
*errActionTrans
;
417 RedStateAp
*firstFinState
;
421 bool bAnyToStateActions
;
422 bool bAnyFromStateActions
;
426 bool bAnyActionGotos
;
427 bool bAnyActionCalls
;
429 bool bAnyRegActionRets
;
430 bool bAnyRegActionByValControl
;
431 bool bAnyRegNextStmt
;
432 bool bAnyRegCurStateRef
;
445 unsigned long long maxSpan
;
446 unsigned long long maxCondSpan
;
447 int maxFlatIndexOffset
;
452 int maxCondIndexOffset
;
456 bool anyToStateActions() { return bAnyToStateActions
; }
457 bool anyFromStateActions() { return bAnyFromStateActions
; }
458 bool anyRegActions() { return bAnyRegActions
; }
459 bool anyEofActions() { return bAnyEofActions
; }
460 bool anyEofTrans() { return bAnyEofTrans
; }
461 bool anyActionGotos() { return bAnyActionGotos
; }
462 bool anyActionCalls() { return bAnyActionCalls
; }
463 bool anyActionRets() { return bAnyActionRets
; }
464 bool anyRegActionRets() { return bAnyRegActionRets
; }
465 bool anyRegActionByValControl() { return bAnyRegActionByValControl
; }
466 bool anyRegNextStmt() { return bAnyRegNextStmt
; }
467 bool anyRegCurStateRef() { return bAnyRegCurStateRef
; }
468 bool anyRegBreak() { return bAnyRegBreak
; }
469 bool anyConditions() { return bAnyConditions
; }
472 /* Is is it possible to extend a range by bumping ranges that span only
473 * one character to the singles array. */
474 bool canExtend( const RedTransList
&list
, int pos
);
476 /* Pick single transitions from the ranges. */
477 void moveTransToSingle( RedStateAp
*state
);
482 /* Move a selected transition from ranges to default. */
483 void moveToDefault( RedTransAp
*defTrans
, RedStateAp
*state
);
485 /* Pick a default transition by largest span. */
486 RedTransAp
*chooseDefaultSpan( RedStateAp
*state
);
487 void chooseDefaultSpan();
489 /* Pick a default transition by most number of ranges. */
490 RedTransAp
*chooseDefaultNumRanges( RedStateAp
*state
);
491 void chooseDefaultNumRanges();
493 /* Pick a default transition tailored towards goto driven machine. */
494 RedTransAp
*chooseDefaultGoto( RedStateAp
*state
);
495 void chooseDefaultGoto();
497 /* Ordering states by transition connections. */
498 void optimizeStateOrdering( RedStateAp
*state
);
499 void optimizeStateOrdering();
501 /* Ordering states by transition connections. */
502 void depthFirstOrdering( RedStateAp
*state
);
503 void depthFirstOrdering();
506 void sequentialStateIds();
507 void sortStateIdsByFinal();
509 /* Arrange states in by final id. This is a stable sort. */
510 void sortStatesByFinal();
512 /* Sorting states by id. */
513 void sortByStateId();
515 /* Locating the first final state. This is the final state with the lowest
517 void findFirstFinState();
519 void assignActionLocs();
521 RedTransAp
*getErrorTrans();
522 RedStateAp
*getErrorState();
524 /* Is every char in the alphabet covered? */
525 bool alphabetCovered( RedTransList
&outRange
);
527 RedTransAp
*allocateTrans( RedStateAp
*targState
, RedAction
*actionTable
);
529 void partitionFsm( int nParts
);
535 #endif /* _REDFSM_H */