redfsm.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532
  1. /*
  2. * Copyright 2001-2006 Adrian Thurston <thurston@complang.org>
  3. */
  4. /* This file is part of Ragel.
  5. *
  6. * Ragel is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * Ragel is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with Ragel; if not, write to the Free Software
  18. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  19. */
  20. #ifndef _REDFSM_H
  21. #define _REDFSM_H
  22. #include <assert.h>
  23. #include <string.h>
  24. #include <string>
  25. #include "config.h"
  26. #include "common.h"
  27. #include "vector.h"
  28. #include "dlist.h"
  29. #include "compare.h"
  30. #include "bstmap.h"
  31. #include "bstset.h"
  32. #include "avlmap.h"
  33. #include "avltree.h"
  34. #include "avlbasic.h"
  35. #include "mergesort.h"
  36. #include "sbstmap.h"
  37. #include "sbstset.h"
  38. #include "sbsttable.h"
  39. #define TRANS_ERR_TRANS 0
  40. #define STATE_ERR_STATE 0
  41. #define FUNC_NO_FUNC 0
  42. using std::string;
  43. struct RedStateAp;
  44. struct GenInlineList;
  45. struct GenAction;
  46. /*
  47. * Inline code tree
  48. */
  49. struct GenInlineItem
  50. {
  51. enum Type
  52. {
  53. Text, Goto, Call, Next, GotoExpr, CallExpr, NextExpr, Ret,
  54. PChar, Char, Hold, Exec, Curs, Targs, Entry,
  55. LmSwitch, LmSetActId, LmSetTokEnd, LmGetTokEnd, LmInitTokStart,
  56. LmInitAct, LmSetTokStart, SubAction, Break
  57. };
  58. GenInlineItem( const InputLoc &loc, Type type ) :
  59. loc(loc), data(0), targId(0), targState(0),
  60. lmId(0), children(0), offset(0),
  61. type(type) { }
  62. InputLoc loc;
  63. char *data;
  64. int targId;
  65. RedStateAp *targState;
  66. int lmId;
  67. GenInlineList *children;
  68. int offset;
  69. Type type;
  70. GenInlineItem *prev, *next;
  71. };
  72. /* Normally this would be atypedef, but that would entail including DList from
  73. * ptreetypes, which should be just typedef forwards. */
  74. struct GenInlineList : public DList<GenInlineItem> { };
  75. /* Element in list of actions. Contains the string for the code to exectute. */
  76. struct GenAction
  77. :
  78. public DListEl<GenAction>
  79. {
  80. GenAction( )
  81. :
  82. name(0),
  83. inlineList(0),
  84. actionId(0),
  85. numTransRefs(0),
  86. numToStateRefs(0),
  87. numFromStateRefs(0),
  88. numEofRefs(0)
  89. {
  90. }
  91. /* Data collected during parse. */
  92. InputLoc loc;
  93. const char *name;
  94. GenInlineList *inlineList;
  95. int actionId;
  96. string nameOrLoc();
  97. /* Number of references in the final machine. */
  98. int numRefs()
  99. { return numTransRefs + numToStateRefs + numFromStateRefs + numEofRefs; }
  100. int numTransRefs;
  101. int numToStateRefs;
  102. int numFromStateRefs;
  103. int numEofRefs;
  104. };
  105. /* Forwards. */
  106. struct RedStateAp;
  107. struct StateAp;
  108. /* Transistion GenAction Element. */
  109. typedef SBstMapEl< int, GenAction* > GenActionTableEl;
  110. /* Transition GenAction Table. */
  111. struct GenActionTable
  112. : public SBstMap< int, GenAction*, CmpOrd<int> >
  113. {
  114. void setAction( int ordering, GenAction *action );
  115. void setActions( int *orderings, GenAction **actions, int nActs );
  116. void setActions( const GenActionTable &other );
  117. };
  118. /* Compare of a whole action table element (key & value). */
  119. struct CmpGenActionTableEl
  120. {
  121. static int compare( const GenActionTableEl &action1,
  122. const GenActionTableEl &action2 )
  123. {
  124. if ( action1.key < action2.key )
  125. return -1;
  126. else if ( action1.key > action2.key )
  127. return 1;
  128. else if ( action1.value < action2.value )
  129. return -1;
  130. else if ( action1.value > action2.value )
  131. return 1;
  132. return 0;
  133. }
  134. };
  135. /* Compare for GenActionTable. */
  136. typedef CmpSTable< GenActionTableEl, CmpGenActionTableEl > CmpGenActionTable;
  137. /* Set of states. */
  138. typedef BstSet<RedStateAp*> RedStateSet;
  139. typedef BstSet<int> IntSet;
  140. /* Reduced action. */
  141. struct RedAction
  142. :
  143. public AvlTreeEl<RedAction>
  144. {
  145. RedAction( )
  146. :
  147. key(),
  148. eofRefs(0),
  149. numTransRefs(0),
  150. numToStateRefs(0),
  151. numFromStateRefs(0),
  152. numEofRefs(0),
  153. bAnyNextStmt(false),
  154. bAnyCurStateRef(false),
  155. bAnyBreakStmt(false)
  156. { }
  157. const GenActionTable &getKey()
  158. { return key; }
  159. GenActionTable key;
  160. int actListId;
  161. int location;
  162. IntSet *eofRefs;
  163. /* Number of references in the final machine. */
  164. int numRefs()
  165. { return numTransRefs + numToStateRefs + numFromStateRefs + numEofRefs; }
  166. int numTransRefs;
  167. int numToStateRefs;
  168. int numFromStateRefs;
  169. int numEofRefs;
  170. bool anyNextStmt() { return bAnyNextStmt; }
  171. bool anyCurStateRef() { return bAnyCurStateRef; }
  172. bool anyBreakStmt() { return bAnyBreakStmt; }
  173. bool bAnyNextStmt;
  174. bool bAnyCurStateRef;
  175. bool bAnyBreakStmt;
  176. };
  177. typedef AvlTree<RedAction, GenActionTable, CmpGenActionTable> GenActionTableMap;
  178. /* Reduced transition. */
  179. struct RedTransAp
  180. :
  181. public AvlTreeEl<RedTransAp>
  182. {
  183. RedTransAp( RedStateAp *targ, RedAction *action, int id )
  184. : targ(targ), action(action), id(id), pos(-1), labelNeeded(true) { }
  185. RedStateAp *targ;
  186. RedAction *action;
  187. int id;
  188. int pos;
  189. bool partitionBoundary;
  190. bool labelNeeded;
  191. };
  192. /* Compare of transitions for the final reduction of transitions. Comparison
  193. * is on target and the pointer to the shared action table. It is assumed that
  194. * when this is used the action tables have been reduced. */
  195. struct CmpRedTransAp
  196. {
  197. static int compare( const RedTransAp &t1, const RedTransAp &t2 )
  198. {
  199. if ( t1.targ < t2.targ )
  200. return -1;
  201. else if ( t1.targ > t2.targ )
  202. return 1;
  203. else if ( t1.action < t2.action )
  204. return -1;
  205. else if ( t1.action > t2.action )
  206. return 1;
  207. else
  208. return 0;
  209. }
  210. };
  211. typedef AvlBasic<RedTransAp, CmpRedTransAp> TransApSet;
  212. /* Element in out range. */
  213. struct RedTransEl
  214. {
  215. /* Constructors. */
  216. RedTransEl( Key lowKey, Key highKey, RedTransAp *value )
  217. : lowKey(lowKey), highKey(highKey), value(value) { }
  218. Key lowKey, highKey;
  219. RedTransAp *value;
  220. };
  221. typedef Vector<RedTransEl> RedTransList;
  222. typedef Vector<RedStateAp*> RedStateVect;
  223. typedef BstMapEl<RedStateAp*, unsigned long long> RedSpanMapEl;
  224. typedef BstMap<RedStateAp*, unsigned long long> RedSpanMap;
  225. /* Compare used by span map sort. Reverse sorts by the span. */
  226. struct CmpRedSpanMapEl
  227. {
  228. static int compare( const RedSpanMapEl &smel1, const RedSpanMapEl &smel2 )
  229. {
  230. if ( smel1.value > smel2.value )
  231. return -1;
  232. else if ( smel1.value < smel2.value )
  233. return 1;
  234. else
  235. return 0;
  236. }
  237. };
  238. /* Sorting state-span map entries by span. */
  239. typedef MergeSort<RedSpanMapEl, CmpRedSpanMapEl> RedSpanMapSort;
  240. /* Set of entry ids that go into this state. */
  241. typedef Vector<int> EntryIdVect;
  242. typedef Vector<char*> EntryNameVect;
  243. typedef Vector< GenAction* > GenCondSet;
  244. struct Condition
  245. {
  246. Condition( )
  247. : key(0), baseKey(0) {}
  248. Key key;
  249. Key baseKey;
  250. GenCondSet condSet;
  251. Condition *next, *prev;
  252. };
  253. typedef DList<Condition> ConditionList;
  254. struct GenCondSpace
  255. {
  256. Key baseKey;
  257. GenCondSet condSet;
  258. int condSpaceId;
  259. GenCondSpace *next, *prev;
  260. };
  261. typedef DList<GenCondSpace> CondSpaceList;
  262. struct GenStateCond
  263. {
  264. Key lowKey;
  265. Key highKey;
  266. GenCondSpace *condSpace;
  267. GenStateCond *prev, *next;
  268. };
  269. typedef DList<GenStateCond> GenStateCondList;
  270. typedef Vector<GenStateCond*> StateCondVect;
  271. /* Reduced state. */
  272. struct RedStateAp
  273. {
  274. RedStateAp()
  275. :
  276. defTrans(0),
  277. condList(0),
  278. transList(0),
  279. isFinal(false),
  280. labelNeeded(false),
  281. outNeeded(false),
  282. onStateList(false),
  283. toStateAction(0),
  284. fromStateAction(0),
  285. eofAction(0),
  286. eofTrans(0),
  287. id(0),
  288. bAnyRegCurStateRef(false),
  289. partitionBoundary(false),
  290. inTrans(0),
  291. numInTrans(0)
  292. { }
  293. /* Transitions out. */
  294. RedTransList outSingle;
  295. RedTransList outRange;
  296. RedTransAp *defTrans;
  297. /* For flat conditions. */
  298. Key condLowKey, condHighKey;
  299. GenCondSpace **condList;
  300. /* For flat keys. */
  301. Key lowKey, highKey;
  302. RedTransAp **transList;
  303. /* The list of states that transitions from this state go to. */
  304. RedStateVect targStates;
  305. bool isFinal;
  306. bool labelNeeded;
  307. bool outNeeded;
  308. bool onStateList;
  309. RedAction *toStateAction;
  310. RedAction *fromStateAction;
  311. RedAction *eofAction;
  312. RedTransAp *eofTrans;
  313. int id;
  314. GenStateCondList stateCondList;
  315. StateCondVect stateCondVect;
  316. /* Pointers for the list of states. */
  317. RedStateAp *prev, *next;
  318. bool anyRegCurStateRef() { return bAnyRegCurStateRef; }
  319. bool bAnyRegCurStateRef;
  320. int partition;
  321. bool partitionBoundary;
  322. RedTransAp **inTrans;
  323. int numInTrans;
  324. };
  325. /* List of states. */
  326. typedef DList<RedStateAp> RedStateList;
  327. /* Set of reduced transitons. Comparison is by pointer. */
  328. typedef BstSet< RedTransAp*, CmpOrd<RedTransAp*> > RedTransSet;
  329. /* Next version of the fsm machine. */
  330. struct RedFsmAp
  331. {
  332. RedFsmAp();
  333. bool forcedErrorState;
  334. int nextActionId;
  335. int nextTransId;
  336. /* Next State Id doubles as the total number of state ids. */
  337. int nextStateId;
  338. TransApSet transSet;
  339. GenActionTableMap actionMap;
  340. RedStateList stateList;
  341. RedStateSet entryPoints;
  342. RedStateAp *startState;
  343. RedStateAp *errState;
  344. RedTransAp *errTrans;
  345. RedTransAp *errActionTrans;
  346. RedStateAp *firstFinState;
  347. int numFinStates;
  348. int nParts;
  349. bool bAnyToStateActions;
  350. bool bAnyFromStateActions;
  351. bool bAnyRegActions;
  352. bool bAnyEofActions;
  353. bool bAnyEofTrans;
  354. bool bAnyActionGotos;
  355. bool bAnyActionCalls;
  356. bool bAnyActionRets;
  357. bool bAnyActionByValControl;
  358. bool bAnyRegActionRets;
  359. bool bAnyRegActionByValControl;
  360. bool bAnyRegNextStmt;
  361. bool bAnyRegCurStateRef;
  362. bool bAnyRegBreak;
  363. bool bAnyConditions;
  364. int maxState;
  365. int maxSingleLen;
  366. int maxRangeLen;
  367. int maxKeyOffset;
  368. int maxIndexOffset;
  369. int maxIndex;
  370. int maxActListId;
  371. int maxActionLoc;
  372. int maxActArrItem;
  373. unsigned long long maxSpan;
  374. unsigned long long maxCondSpan;
  375. int maxFlatIndexOffset;
  376. Key maxKey;
  377. int maxCondOffset;
  378. int maxCondLen;
  379. int maxCondSpaceId;
  380. int maxCondIndexOffset;
  381. int maxCond;
  382. bool anyActions();
  383. bool anyToStateActions() { return bAnyToStateActions; }
  384. bool anyFromStateActions() { return bAnyFromStateActions; }
  385. bool anyRegActions() { return bAnyRegActions; }
  386. bool anyEofActions() { return bAnyEofActions; }
  387. bool anyEofTrans() { return bAnyEofTrans; }
  388. bool anyActionGotos() { return bAnyActionGotos; }
  389. bool anyActionCalls() { return bAnyActionCalls; }
  390. bool anyActionRets() { return bAnyActionRets; }
  391. bool anyActionByValControl() { return bAnyActionByValControl; }
  392. bool anyRegActionRets() { return bAnyRegActionRets; }
  393. bool anyRegActionByValControl() { return bAnyRegActionByValControl; }
  394. bool anyRegNextStmt() { return bAnyRegNextStmt; }
  395. bool anyRegCurStateRef() { return bAnyRegCurStateRef; }
  396. bool anyRegBreak() { return bAnyRegBreak; }
  397. bool anyConditions() { return bAnyConditions; }
  398. /* Is is it possible to extend a range by bumping ranges that span only
  399. * one character to the singles array. */
  400. bool canExtend( const RedTransList &list, int pos );
  401. /* Pick single transitions from the ranges. */
  402. void moveTransToSingle( RedStateAp *state );
  403. void chooseSingle();
  404. void makeFlat();
  405. /* Move a selected transition from ranges to default. */
  406. void moveToDefault( RedTransAp *defTrans, RedStateAp *state );
  407. /* Pick a default transition by largest span. */
  408. RedTransAp *chooseDefaultSpan( RedStateAp *state );
  409. void chooseDefaultSpan();
  410. /* Pick a default transition by most number of ranges. */
  411. RedTransAp *chooseDefaultNumRanges( RedStateAp *state );
  412. void chooseDefaultNumRanges();
  413. /* Pick a default transition tailored towards goto driven machine. */
  414. RedTransAp *chooseDefaultGoto( RedStateAp *state );
  415. void chooseDefaultGoto();
  416. /* Ordering states by transition connections. */
  417. void optimizeStateOrdering( RedStateAp *state );
  418. void optimizeStateOrdering();
  419. /* Ordering states by transition connections. */
  420. void depthFirstOrdering( RedStateAp *state );
  421. void depthFirstOrdering();
  422. /* Set state ids. */
  423. void sequentialStateIds();
  424. void sortStateIdsByFinal();
  425. /* Arrange states in by final id. This is a stable sort. */
  426. void sortStatesByFinal();
  427. /* Sorting states by id. */
  428. void sortByStateId();
  429. /* Locating the first final state. This is the final state with the lowest
  430. * id. */
  431. void findFirstFinState();
  432. void assignActionLocs();
  433. RedTransAp *getErrorTrans();
  434. RedStateAp *getErrorState();
  435. /* Is every char in the alphabet covered? */
  436. bool alphabetCovered( RedTransList &outRange );
  437. RedTransAp *allocateTrans( RedStateAp *targState, RedAction *actionTable );
  438. void partitionFsm( int nParts );
  439. void setInTrans();
  440. };
  441. #endif