fsmgraph.h 41 KB

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