fsmgraph.cpp 45 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434
  1. /*
  2. * Copyright 2001, 2002, 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. #include <assert.h>
  21. #include <iostream>
  22. #include "fsmgraph.h"
  23. #include "mergesort.h"
  24. #include "parsedata.h"
  25. using std::cerr;
  26. using std::endl;
  27. /* Make a new state. The new state will be put on the graph's
  28. * list of state. The new state can be created final or non final. */
  29. StateAp *FsmAp::addState()
  30. {
  31. /* Make the new state to return. */
  32. StateAp *state = new StateAp();
  33. if ( misfitAccounting ) {
  34. /* Create the new state on the misfit list. All states are created
  35. * with no foreign in transitions. */
  36. misfitList.append( state );
  37. }
  38. else {
  39. /* Create the new state. */
  40. stateList.append( state );
  41. }
  42. return state;
  43. }
  44. /* Construct an FSM that is the concatenation of an array of characters. A new
  45. * machine will be made that has len+1 states with one transition between each
  46. * state for each integer in str. IsSigned determines if the integers are to
  47. * be considered as signed or unsigned ints. */
  48. void FsmAp::concatFsm( Key *str, int len )
  49. {
  50. /* Make the first state and set it as the start state. */
  51. StateAp *last = addState();
  52. setStartState( last );
  53. /* Attach subsequent states. */
  54. for ( int i = 0; i < len; i++ ) {
  55. StateAp *newState = addState();
  56. attachNewTrans( last, newState, str[i], str[i] );
  57. last = newState;
  58. }
  59. /* Make the last state the final state. */
  60. setFinState( last );
  61. }
  62. /* Case insensitive version of concatFsm. */
  63. void FsmAp::concatFsmCI( Key *str, int len )
  64. {
  65. /* Make the first state and set it as the start state. */
  66. StateAp *last = addState();
  67. setStartState( last );
  68. /* Attach subsequent states. */
  69. for ( int i = 0; i < len; i++ ) {
  70. StateAp *newState = addState();
  71. KeySet keySet;
  72. if ( str[i].isLower() )
  73. keySet.insert( str[i].toUpper() );
  74. if ( str[i].isUpper() )
  75. keySet.insert( str[i].toLower() );
  76. keySet.insert( str[i] );
  77. for ( int i = 0; i < keySet.length(); i++ )
  78. attachNewTrans( last, newState, keySet[i], keySet[i] );
  79. last = newState;
  80. }
  81. /* Make the last state the final state. */
  82. setFinState( last );
  83. }
  84. /* Construct a machine that matches one character. A new machine will be made
  85. * that has two states with a single transition between the states. IsSigned
  86. * determines if the integers are to be considered as signed or unsigned ints. */
  87. void FsmAp::concatFsm( Key chr )
  88. {
  89. /* Two states first start, second final. */
  90. setStartState( addState() );
  91. StateAp *end = addState();
  92. setFinState( end );
  93. /* Attach on the character. */
  94. attachNewTrans( startState, end, chr, chr );
  95. }
  96. /* Construct a machine that matches any character in set. A new machine will
  97. * be made that has two states and len transitions between the them. The set
  98. * should be ordered correctly accroding to KeyOps and should not contain
  99. * any duplicates. */
  100. void FsmAp::orFsm( Key *set, int len )
  101. {
  102. /* Two states first start, second final. */
  103. setStartState( addState() );
  104. StateAp *end = addState();
  105. setFinState( end );
  106. for ( int i = 1; i < len; i++ )
  107. assert( set[i-1] < set[i] );
  108. /* Attach on all the integers in the given string of ints. */
  109. for ( int i = 0; i < len; i++ )
  110. attachNewTrans( startState, end, set[i], set[i] );
  111. }
  112. /* Construct a machine that matches a range of characters. A new machine will
  113. * be made with two states and a range transition between them. The range will
  114. * match any characters from low to high inclusive. Low should be less than or
  115. * equal to high otherwise undefined behaviour results. IsSigned determines
  116. * if the integers are to be considered as signed or unsigned ints. */
  117. void FsmAp::rangeFsm( Key low, Key high )
  118. {
  119. /* Two states first start, second final. */
  120. setStartState( addState() );
  121. StateAp *end = addState();
  122. setFinState( end );
  123. /* Attach using the range of characters. */
  124. attachNewTrans( startState, end, low, high );
  125. }
  126. /* Construct a machine that a repeated range of characters. */
  127. void FsmAp::rangeStarFsm( Key low, Key high)
  128. {
  129. /* One state which is final and is the start state. */
  130. setStartState( addState() );
  131. setFinState( startState );
  132. /* Attach start to start using range of characters. */
  133. attachNewTrans( startState, startState, low, high );
  134. }
  135. /* Construct a machine that matches the empty string. A new machine will be
  136. * made with only one state. The new state will be both a start and final
  137. * state. IsSigned determines if the machine has a signed or unsigned
  138. * alphabet. Fsm operations must be done on machines with the same alphabet
  139. * signedness. */
  140. void FsmAp::lambdaFsm( )
  141. {
  142. /* Give it one state with no transitions making it
  143. * the start state and final state. */
  144. setStartState( addState() );
  145. setFinState( startState );
  146. }
  147. /* Construct a machine that matches nothing at all. A new machine will be
  148. * made with only one state. It will not be final. */
  149. void FsmAp::emptyFsm( )
  150. {
  151. /* Give it one state with no transitions making it
  152. * the start state and final state. */
  153. setStartState( addState() );
  154. }
  155. void FsmAp::transferOutData( StateAp *destState, StateAp *srcState )
  156. {
  157. for ( TransList::Iter trans = destState->outList; trans.lte(); trans++ ) {
  158. if ( trans->toState != 0 ) {
  159. /* Get the actions data from the outActionTable. */
  160. trans->actionTable.setActions( srcState->outActionTable );
  161. /* Get the priorities from the outPriorTable. */
  162. trans->priorTable.setPriors( srcState->outPriorTable );
  163. }
  164. }
  165. }
  166. /* Kleene star operator. Makes this machine the kleene star of itself. Any
  167. * transitions made going out of the machine and back into itself will be
  168. * notified that they are leaving transitions by having the leavingFromState
  169. * callback invoked. */
  170. void FsmAp::starOp( )
  171. {
  172. /* For the merging process. */
  173. MergeData md;
  174. /* Turn on misfit accounting to possibly catch the old start state. */
  175. setMisfitAccounting( true );
  176. /* Create the new new start state. It will be set final after the merging
  177. * of the final states with the start state is complete. */
  178. StateAp *prevStartState = startState;
  179. unsetStartState();
  180. setStartState( addState() );
  181. /* Merge the new start state with the old one to isolate it. */
  182. mergeStates( md, startState, prevStartState );
  183. /* Merge the start state into all final states. Except the start state on
  184. * the first pass. If the start state is set final we will be doubling up
  185. * its transitions, which will get transfered to any final states that
  186. * follow it in the final state set. This will be determined by the order
  187. * of items in the final state set. To prevent this we just merge with the
  188. * start on a second pass. */
  189. for ( StateSet::Iter st = finStateSet; st.lte(); st++ ) {
  190. if ( *st != startState )
  191. mergeStatesLeaving( md, *st, startState );
  192. }
  193. /* Now it is safe to merge the start state with itself (provided it
  194. * is set final). */
  195. if ( startState->isFinState() )
  196. mergeStatesLeaving( md, startState, startState );
  197. /* Now ensure the new start state is a final state. */
  198. setFinState( startState );
  199. /* Fill in any states that were newed up as combinations of others. */
  200. fillInStates( md );
  201. /* Remove the misfits and turn off misfit accounting. */
  202. removeMisfits();
  203. setMisfitAccounting( false );
  204. }
  205. void FsmAp::repeatOp( int times )
  206. {
  207. /* Must be 1 and up. 0 produces null machine and requires deleting this. */
  208. assert( times > 0 );
  209. /* A repeat of one does absolutely nothing. */
  210. if ( times == 1 )
  211. return;
  212. /* Make a machine to make copies from. */
  213. FsmAp *copyFrom = new FsmAp( *this );
  214. /* Concatentate duplicates onto the end up until before the last. */
  215. for ( int i = 1; i < times-1; i++ ) {
  216. FsmAp *dup = new FsmAp( *copyFrom );
  217. doConcat( dup, 0, false );
  218. }
  219. /* Now use the copyFrom on the end. */
  220. doConcat( copyFrom, 0, false );
  221. }
  222. void FsmAp::optionalRepeatOp( int times )
  223. {
  224. /* Must be 1 and up. 0 produces null machine and requires deleting this. */
  225. assert( times > 0 );
  226. /* A repeat of one optional merely allows zero string. */
  227. if ( times == 1 ) {
  228. setFinState( startState );
  229. return;
  230. }
  231. /* Make a machine to make copies from. */
  232. FsmAp *copyFrom = new FsmAp( *this );
  233. /* The state set used in the from end of the concatentation. Starts with
  234. * the initial final state set, then after each concatenation, gets set to
  235. * the the final states that come from the the duplicate. */
  236. StateSet lastFinSet( finStateSet );
  237. /* Set the initial state to zero to allow zero copies. */
  238. setFinState( startState );
  239. /* Concatentate duplicates onto the end up until before the last. */
  240. for ( int i = 1; i < times-1; i++ ) {
  241. /* Make a duplicate for concating and set the fin bits to graph 2 so we
  242. * can pick out it's final states after the optional style concat. */
  243. FsmAp *dup = new FsmAp( *copyFrom );
  244. dup->setFinBits( STB_GRAPH2 );
  245. doConcat( dup, &lastFinSet, true );
  246. /* Clear the last final state set and make the new one by taking only
  247. * the final states that come from graph 2.*/
  248. lastFinSet.empty();
  249. for ( int i = 0; i < finStateSet.length(); i++ ) {
  250. /* If the state came from graph 2, add it to the last set and clear
  251. * the bits. */
  252. StateAp *fs = finStateSet[i];
  253. if ( fs->stateBits & STB_GRAPH2 ) {
  254. lastFinSet.insert( fs );
  255. fs->stateBits &= ~STB_GRAPH2;
  256. }
  257. }
  258. }
  259. /* Now use the copyFrom on the end, no bits set, no bits to clear. */
  260. doConcat( copyFrom, &lastFinSet, true );
  261. }
  262. /* Fsm concatentation worker. Supports treating the concatentation as optional,
  263. * which essentially leaves the final states of machine one as final. */
  264. void FsmAp::doConcat( FsmAp *other, StateSet *fromStates, bool optional )
  265. {
  266. /* For the merging process. */
  267. StateSet finStateSetCopy, startStateSet;
  268. MergeData md;
  269. /* Turn on misfit accounting for both graphs. */
  270. setMisfitAccounting( true );
  271. other->setMisfitAccounting( true );
  272. /* Get the other's start state. */
  273. StateAp *otherStartState = other->startState;
  274. /* Unset other's start state before bringing in the entry points. */
  275. other->unsetStartState();
  276. /* Bring in the rest of other's entry points. */
  277. copyInEntryPoints( other );
  278. other->entryPoints.empty();
  279. /* Bring in other's states into our state lists. */
  280. stateList.append( other->stateList );
  281. misfitList.append( other->misfitList );
  282. /* If from states is not set, then get a copy of our final state set before
  283. * we clobber it and use it instead. */
  284. if ( fromStates == 0 ) {
  285. finStateSetCopy = finStateSet;
  286. fromStates = &finStateSetCopy;
  287. }
  288. /* Unset all of our final states and get the final states from other. */
  289. if ( !optional )
  290. unsetAllFinStates();
  291. finStateSet.insert( other->finStateSet );
  292. /* Since other's lists are empty, we can delete the fsm without
  293. * affecting any states. */
  294. delete other;
  295. /* Merge our former final states with the start state of other. */
  296. for ( int i = 0; i < fromStates->length(); i++ ) {
  297. StateAp *state = fromStates->data[i];
  298. /* Merge the former final state with other's start state. */
  299. mergeStatesLeaving( md, state, otherStartState );
  300. /* If the former final state was not reset final then we must clear
  301. * the state's out trans data. If it got reset final then it gets to
  302. * keep its out trans data. This must be done before fillInStates gets
  303. * called to prevent the data from being sourced. */
  304. if ( ! state->isFinState() )
  305. clearOutData( state );
  306. }
  307. /* Fill in any new states made from merging. */
  308. fillInStates( md );
  309. /* Remove the misfits and turn off misfit accounting. */
  310. removeMisfits();
  311. setMisfitAccounting( false );
  312. }
  313. /* Concatenates other to the end of this machine. Other is deleted. Any
  314. * transitions made leaving this machine and entering into other are notified
  315. * that they are leaving transitions by having the leavingFromState callback
  316. * invoked. */
  317. void FsmAp::concatOp( FsmAp *other )
  318. {
  319. /* Assert same signedness and return graph concatenation op. */
  320. doConcat( other, 0, false );
  321. }
  322. void FsmAp::doOr( FsmAp *other )
  323. {
  324. /* For the merging process. */
  325. MergeData md;
  326. /* Build a state set consisting of both start states */
  327. StateSet startStateSet;
  328. startStateSet.insert( startState );
  329. startStateSet.insert( other->startState );
  330. /* Both of the original start states loose their start state status. */
  331. unsetStartState();
  332. other->unsetStartState();
  333. /* Bring in the rest of other's entry points. */
  334. copyInEntryPoints( other );
  335. other->entryPoints.empty();
  336. /* Merge the lists. This will move all the states from other
  337. * into this. No states will be deleted. */
  338. stateList.append( other->stateList );
  339. misfitList.append( other->misfitList );
  340. /* Move the final set data from other into this. */
  341. finStateSet.insert(other->finStateSet);
  342. other->finStateSet.empty();
  343. /* Since other's list is empty, we can delete the fsm without
  344. * affecting any states. */
  345. delete other;
  346. /* Create a new start state. */
  347. setStartState( addState() );
  348. /* Merge the start states. */
  349. mergeStates( md, startState, startStateSet.data, startStateSet.length() );
  350. /* Fill in any new states made from merging. */
  351. fillInStates( md );
  352. }
  353. /* Unions other with this machine. Other is deleted. */
  354. void FsmAp::unionOp( FsmAp *other )
  355. {
  356. /* Turn on misfit accounting for both graphs. */
  357. setMisfitAccounting( true );
  358. other->setMisfitAccounting( true );
  359. /* Call Worker routine. */
  360. doOr( other );
  361. /* Remove the misfits and turn off misfit accounting. */
  362. removeMisfits();
  363. setMisfitAccounting( false );
  364. }
  365. /* Intersects other with this machine. Other is deleted. */
  366. void FsmAp::intersectOp( FsmAp *other )
  367. {
  368. /* Turn on misfit accounting for both graphs. */
  369. setMisfitAccounting( true );
  370. other->setMisfitAccounting( true );
  371. /* Set the fin bits on this and other to want each other. */
  372. setFinBits( STB_GRAPH1 );
  373. other->setFinBits( STB_GRAPH2 );
  374. /* Call worker Or routine. */
  375. doOr( other );
  376. /* Unset any final states that are no longer to
  377. * be final due to final bits. */
  378. unsetIncompleteFinals();
  379. /* Remove the misfits and turn off misfit accounting. */
  380. removeMisfits();
  381. setMisfitAccounting( false );
  382. /* Remove states that have no path to a final state. */
  383. removeDeadEndStates();
  384. }
  385. /* Set subtracts other machine from this machine. Other is deleted. */
  386. void FsmAp::subtractOp( FsmAp *other )
  387. {
  388. /* Turn on misfit accounting for both graphs. */
  389. setMisfitAccounting( true );
  390. other->setMisfitAccounting( true );
  391. /* Set the fin bits of other to be killers. */
  392. other->setFinBits( STB_GRAPH1 );
  393. /* Call worker Or routine. */
  394. doOr( other );
  395. /* Unset any final states that are no longer to
  396. * be final due to final bits. */
  397. unsetKilledFinals();
  398. /* Remove the misfits and turn off misfit accounting. */
  399. removeMisfits();
  400. setMisfitAccounting( false );
  401. /* Remove states that have no path to a final state. */
  402. removeDeadEndStates();
  403. }
  404. bool FsmAp::inEptVect( EptVect *eptVect, StateAp *state )
  405. {
  406. if ( eptVect != 0 ) {
  407. /* Vect is there, walk it looking for state. */
  408. for ( int i = 0; i < eptVect->length(); i++ ) {
  409. if ( eptVect->data[i].targ == state )
  410. return true;
  411. }
  412. }
  413. return false;
  414. }
  415. /* Fill epsilon vectors in a root state from a given starting point. Epmploys
  416. * a depth first search through the graph of epsilon transitions. */
  417. void FsmAp::epsilonFillEptVectFrom( StateAp *root, StateAp *from, bool parentLeaving )
  418. {
  419. /* Walk the epsilon transitions out of the state. */
  420. for ( EpsilonTrans::Iter ep = from->epsilonTrans; ep.lte(); ep++ ) {
  421. /* Find the entry point, if the it does not resove, ignore it. */
  422. EntryMapEl *enLow, *enHigh;
  423. if ( entryPoints.findMulti( *ep, enLow, enHigh ) ) {
  424. /* Loop the targets. */
  425. for ( EntryMapEl *en = enLow; en <= enHigh; en++ ) {
  426. /* Do not add the root or states already in eptVect. */
  427. StateAp *targ = en->value;
  428. if ( targ != from && !inEptVect(root->eptVect, targ) ) {
  429. /* Maybe need to create the eptVect. */
  430. if ( root->eptVect == 0 )
  431. root->eptVect = new EptVect();
  432. /* If moving to a different graph or if any parent is
  433. * leaving then we are leaving. */
  434. bool leaving = parentLeaving ||
  435. root->owningGraph != targ->owningGraph;
  436. /* All ok, add the target epsilon and recurse. */
  437. root->eptVect->append( EptVectEl(targ, leaving) );
  438. epsilonFillEptVectFrom( root, targ, leaving );
  439. }
  440. }
  441. }
  442. }
  443. }
  444. void FsmAp::shadowReadWriteStates( MergeData &md )
  445. {
  446. /* Init isolatedShadow algorithm data. */
  447. for ( StateList::Iter st = stateList; st.lte(); st++ )
  448. st->isolatedShadow = 0;
  449. /* Any states that may be both read from and written to must
  450. * be shadowed. */
  451. for ( StateList::Iter st = stateList; st.lte(); st++ ) {
  452. /* Find such states by looping through stateVect lists, which give us
  453. * the states that will be read from. May cause us to visit the states
  454. * that we are interested in more than once. */
  455. if ( st->eptVect != 0 ) {
  456. /* For all states that will be read from. */
  457. for ( EptVect::Iter ept = *st->eptVect; ept.lte(); ept++ ) {
  458. /* Check for read and write to the same state. */
  459. StateAp *targ = ept->targ;
  460. if ( targ->eptVect != 0 ) {
  461. /* State is to be written to, if the shadow is not already
  462. * there, create it. */
  463. if ( targ->isolatedShadow == 0 ) {
  464. StateAp *shadow = addState();
  465. mergeStates( md, shadow, targ );
  466. targ->isolatedShadow = shadow;
  467. }
  468. /* Write shadow into the state vector so that it is the
  469. * state that the epsilon transition will read from. */
  470. ept->targ = targ->isolatedShadow;
  471. }
  472. }
  473. }
  474. }
  475. }
  476. void FsmAp::resolveEpsilonTrans( MergeData &md )
  477. {
  478. /* Walk the state list and invoke recursive worker on each state. */
  479. for ( StateList::Iter st = stateList; st.lte(); st++ )
  480. epsilonFillEptVectFrom( st, st, false );
  481. /* Prevent reading from and writing to of the same state. */
  482. shadowReadWriteStates( md );
  483. /* For all states that have epsilon transitions out, draw the transitions,
  484. * clear the epsilon transitions. */
  485. for ( StateList::Iter st = stateList; st.lte(); st++ ) {
  486. /* If there is a state vector, then create the pre-merge state. */
  487. if ( st->eptVect != 0 ) {
  488. /* Merge all the epsilon targets into the state. */
  489. for ( EptVect::Iter ept = *st->eptVect; ept.lte(); ept++ ) {
  490. if ( ept->leaving )
  491. mergeStatesLeaving( md, st, ept->targ );
  492. else
  493. mergeStates( md, st, ept->targ );
  494. }
  495. /* Clean up the target list. */
  496. delete st->eptVect;
  497. st->eptVect = 0;
  498. }
  499. /* Clear the epsilon transitions vector. */
  500. st->epsilonTrans.empty();
  501. }
  502. }
  503. void FsmAp::epsilonOp()
  504. {
  505. /* For merging process. */
  506. MergeData md;
  507. setMisfitAccounting( true );
  508. for ( StateList::Iter st = stateList; st.lte(); st++ )
  509. st->owningGraph = 0;
  510. /* Perform merges. */
  511. resolveEpsilonTrans( md );
  512. /* Epsilons can caused merges which leave behind unreachable states. */
  513. fillInStates( md );
  514. /* Remove the misfits and turn off misfit accounting. */
  515. removeMisfits();
  516. setMisfitAccounting( false );
  517. }
  518. /* Make a new maching by joining together a bunch of machines without making
  519. * any transitions between them. A negative finalId results in there being no
  520. * final id. */
  521. void FsmAp::joinOp( int startId, int finalId, FsmAp **others, int numOthers )
  522. {
  523. /* For the merging process. */
  524. MergeData md;
  525. /* Set the owning machines. Start at one. Zero is reserved for the start
  526. * and final states. */
  527. for ( StateList::Iter st = stateList; st.lte(); st++ )
  528. st->owningGraph = 1;
  529. for ( int m = 0; m < numOthers; m++ ) {
  530. for ( StateList::Iter st = others[m]->stateList; st.lte(); st++ )
  531. st->owningGraph = 2+m;
  532. }
  533. /* All machines loose start state status. */
  534. unsetStartState();
  535. for ( int m = 0; m < numOthers; m++ )
  536. others[m]->unsetStartState();
  537. /* Bring the other machines into this. */
  538. for ( int m = 0; m < numOthers; m++ ) {
  539. /* Bring in the rest of other's entry points. */
  540. copyInEntryPoints( others[m] );
  541. others[m]->entryPoints.empty();
  542. /* Merge the lists. This will move all the states from other into
  543. * this. No states will be deleted. */
  544. stateList.append( others[m]->stateList );
  545. assert( others[m]->misfitList.length() == 0 );
  546. /* Move the final set data from other into this. */
  547. finStateSet.insert( others[m]->finStateSet );
  548. others[m]->finStateSet.empty();
  549. /* Since other's list is empty, we can delete the fsm without
  550. * affecting any states. */
  551. delete others[m];
  552. }
  553. /* Look up the start entry point. */
  554. EntryMapEl *enLow = 0, *enHigh = 0;
  555. bool findRes = entryPoints.findMulti( startId, enLow, enHigh );
  556. if ( ! findRes ) {
  557. /* No start state. Set a default one and proceed with the join. Note
  558. * that the result of the join will be a very uninteresting machine. */
  559. setStartState( addState() );
  560. }
  561. else {
  562. /* There is at least one start state, create a state that will become
  563. * the new start state. */
  564. StateAp *newStart = addState();
  565. setStartState( newStart );
  566. /* The start state is in an owning machine class all it's own. */
  567. newStart->owningGraph = 0;
  568. /* Create the set of states to merge from. */
  569. StateSet stateSet;
  570. for ( EntryMapEl *en = enLow; en <= enHigh; en++ )
  571. stateSet.insert( en->value );
  572. /* Merge in the set of start states into the new start state. */
  573. mergeStates( md, newStart, stateSet.data, stateSet.length() );
  574. }
  575. /* Take a copy of the final state set, before unsetting them all. This
  576. * will allow us to call clearOutData on the states that don't get
  577. * final state status back back. */
  578. StateSet finStateSetCopy = finStateSet;
  579. /* Now all final states are unset. */
  580. unsetAllFinStates();
  581. if ( finalId >= 0 ) {
  582. /* Create the implicit final state. */
  583. StateAp *finState = addState();
  584. setFinState( finState );
  585. /* Assign an entry into the final state on the final state entry id. Note
  586. * that there may already be an entry on this id. That's ok. Also set the
  587. * final state owning machine id. It's in a class all it's own. */
  588. setEntry( finalId, finState );
  589. finState->owningGraph = 0;
  590. }
  591. /* Hand over to workers for resolving epsilon trans. This will merge states
  592. * with the targets of their epsilon transitions. */
  593. resolveEpsilonTrans( md );
  594. /* Invoke the relinquish final callback on any states that did not get
  595. * final state status back. */
  596. for ( StateSet::Iter st = finStateSetCopy; st.lte(); st++ ) {
  597. if ( !((*st)->stateBits & STB_ISFINAL) )
  598. clearOutData( *st );
  599. }
  600. /* Fill in any new states made from merging. */
  601. fillInStates( md );
  602. /* Joining can be messy. Instead of having misfit accounting on (which is
  603. * tricky here) do a full cleaning. */
  604. removeUnreachableStates();
  605. }
  606. void FsmAp::globOp( FsmAp **others, int numOthers )
  607. {
  608. /* All other machines loose start states status. */
  609. for ( int m = 0; m < numOthers; m++ )
  610. others[m]->unsetStartState();
  611. /* Bring the other machines into this. */
  612. for ( int m = 0; m < numOthers; m++ ) {
  613. /* Bring in the rest of other's entry points. */
  614. copyInEntryPoints( others[m] );
  615. others[m]->entryPoints.empty();
  616. /* Merge the lists. This will move all the states from other into
  617. * this. No states will be deleted. */
  618. stateList.append( others[m]->stateList );
  619. assert( others[m]->misfitList.length() == 0 );
  620. /* Move the final set data from other into this. */
  621. finStateSet.insert( others[m]->finStateSet );
  622. others[m]->finStateSet.empty();
  623. /* Since other's list is empty, we can delete the fsm without
  624. * affecting any states. */
  625. delete others[m];
  626. }
  627. }
  628. void FsmAp::deterministicEntry()
  629. {
  630. /* For the merging process. */
  631. MergeData md;
  632. /* States may loose their entry points, turn on misfit accounting. */
  633. setMisfitAccounting( true );
  634. /* Get a copy of the entry map then clear all the entry points. As we
  635. * iterate the old entry map finding duplicates we will add the entry
  636. * points for the new states that we create. */
  637. EntryMap prevEntry = entryPoints;
  638. unsetAllEntryPoints();
  639. for ( int enId = 0; enId < prevEntry.length(); ) {
  640. /* Count the number of states on this entry key. */
  641. int highId = enId;
  642. while ( highId < prevEntry.length() && prevEntry[enId].key == prevEntry[highId].key )
  643. highId += 1;
  644. int numIds = highId - enId;
  645. if ( numIds == 1 ) {
  646. /* Only a single entry point, just set the entry. */
  647. setEntry( prevEntry[enId].key, prevEntry[enId].value );
  648. }
  649. else {
  650. /* Multiple entry points, need to create a new state and merge in
  651. * all the targets of entry points. */
  652. StateAp *newEntry = addState();
  653. for ( int en = enId; en < highId; en++ )
  654. mergeStates( md, newEntry, prevEntry[en].value );
  655. /* Add the new state as the single entry point. */
  656. setEntry( prevEntry[enId].key, newEntry );
  657. }
  658. enId += numIds;
  659. }
  660. /* The old start state may be unreachable. Remove the misfits and turn off
  661. * misfit accounting. */
  662. removeMisfits();
  663. setMisfitAccounting( false );
  664. }
  665. /* Unset any final states that are no longer to be final due to final bits. */
  666. void FsmAp::unsetKilledFinals()
  667. {
  668. /* Duplicate the final state set before we begin modifying it. */
  669. StateSet fin( finStateSet );
  670. for ( int s = 0; s < fin.length(); s++ ) {
  671. /* Check for killing bit. */
  672. StateAp *state = fin.data[s];
  673. if ( state->stateBits & STB_GRAPH1 ) {
  674. /* One final state is a killer, set to non-final. */
  675. unsetFinState( state );
  676. }
  677. /* Clear all killing bits. Non final states should never have had those
  678. * state bits set in the first place. */
  679. state->stateBits &= ~STB_GRAPH1;
  680. }
  681. }
  682. /* Unset any final states that are no longer to be final due to final bits. */
  683. void FsmAp::unsetIncompleteFinals()
  684. {
  685. /* Duplicate the final state set before we begin modifying it. */
  686. StateSet fin( finStateSet );
  687. for ( int s = 0; s < fin.length(); s++ ) {
  688. /* Check for one set but not the other. */
  689. StateAp *state = fin.data[s];
  690. if ( state->stateBits & STB_BOTH &&
  691. (state->stateBits & STB_BOTH) != STB_BOTH )
  692. {
  693. /* One state wants the other but it is not there. */
  694. unsetFinState( state );
  695. }
  696. /* Clear wanting bits. Non final states should never have had those
  697. * state bits set in the first place. */
  698. state->stateBits &= ~STB_BOTH;
  699. }
  700. }
  701. /* Ensure that the start state is free of entry points (aside from the fact
  702. * that it is the start state). If the start state has entry points then Make a
  703. * new start state by merging with the old one. Useful before modifying start
  704. * transitions. If the existing start state has any entry points other than the
  705. * start state entry then modifying its transitions changes more than the start
  706. * transitions. So isolate the start state by separating it out such that it
  707. * only has start stateness as it's entry point. */
  708. void FsmAp::isolateStartState( )
  709. {
  710. /* For the merging process. */
  711. MergeData md;
  712. /* Bail out if the start state is already isolated. */
  713. if ( isStartStateIsolated() )
  714. return;
  715. /* Turn on misfit accounting to possibly catch the old start state. */
  716. setMisfitAccounting( true );
  717. /* This will be the new start state. The existing start
  718. * state is merged with it. */
  719. StateAp *prevStartState = startState;
  720. unsetStartState();
  721. setStartState( addState() );
  722. /* Merge the new start state with the old one to isolate it. */
  723. mergeStates( md, startState, prevStartState );
  724. /* Stfil and stateDict will be empty because the merging of the old start
  725. * state into the new one will not have any conflicting transitions. */
  726. assert( md.stateDict.treeSize == 0 );
  727. assert( md.stfillHead == 0 );
  728. /* The old start state may be unreachable. Remove the misfits and turn off
  729. * misfit accounting. */
  730. removeMisfits();
  731. setMisfitAccounting( false );
  732. }
  733. #ifdef LOG_CONDS
  734. void logCondSpace( CondSpace *condSpace )
  735. {
  736. if ( condSpace == 0 )
  737. cerr << "<empty>";
  738. else {
  739. for ( CondSet::Iter csi = condSpace->condSet.last(); csi.gtb(); csi-- ) {
  740. if ( ! csi.last() )
  741. cerr << ',';
  742. (*csi)->actionName( cerr );
  743. }
  744. }
  745. }
  746. void logNewExpansion( Expansion *exp )
  747. {
  748. cerr << "created expansion:" << endl;
  749. cerr << " range: " << exp->lowKey.getVal() << " .. " <<
  750. exp->highKey.getVal() << endl;
  751. cerr << " fromCondSpace: ";
  752. logCondSpace( exp->fromCondSpace );
  753. cerr << endl;
  754. cerr << " fromVals: " << exp->fromVals << endl;
  755. cerr << " toCondSpace: ";
  756. logCondSpace( exp->toCondSpace );
  757. cerr << endl;
  758. cerr << " toValsList: ";
  759. for ( LongVect::Iter to = exp->toValsList; to.lte(); to++ )
  760. cerr << " " << *to;
  761. cerr << endl;
  762. }
  763. #endif
  764. void FsmAp::findTransExpansions( ExpansionList &expansionList,
  765. StateAp *destState, StateAp *srcState )
  766. {
  767. PairIter<TransAp, StateCond> transCond( destState->outList.head,
  768. srcState->stateCondList.head );
  769. for ( ; !transCond.end(); transCond++ ) {
  770. if ( transCond.userState == RangeOverlap ) {
  771. Expansion *expansion = new Expansion( transCond.s1Tel.lowKey,
  772. transCond.s1Tel.highKey );
  773. expansion->fromTrans = new TransAp(*transCond.s1Tel.trans);
  774. expansion->fromTrans->fromState = 0;
  775. expansion->fromTrans->toState = transCond.s1Tel.trans->toState;
  776. expansion->fromCondSpace = 0;
  777. expansion->fromVals = 0;
  778. CondSpace *srcCS = transCond.s2Tel.trans->condSpace;
  779. expansion->toCondSpace = srcCS;
  780. long numTargVals = (1 << srcCS->condSet.length());
  781. for ( long targVals = 0; targVals < numTargVals; targVals++ )
  782. expansion->toValsList.append( targVals );
  783. #ifdef LOG_CONDS
  784. logNewExpansion( expansion );
  785. #endif
  786. expansionList.append( expansion );
  787. }
  788. }
  789. }
  790. void FsmAp::findCondExpInTrans( ExpansionList &expansionList, StateAp *state,
  791. Key lowKey, Key highKey, CondSpace *fromCondSpace, CondSpace *toCondSpace,
  792. long fromVals, LongVect &toValsList )
  793. {
  794. /* Make condition-space low and high keys for searching. */
  795. TransAp searchTrans;
  796. searchTrans.lowKey = fromCondSpace->baseKey + fromVals * keyOps->alphSize() +
  797. (lowKey - keyOps->minKey);
  798. searchTrans.highKey = fromCondSpace->baseKey + fromVals * keyOps->alphSize() +
  799. (highKey - keyOps->minKey);
  800. searchTrans.prev = searchTrans.next = 0;
  801. PairIter<TransAp> pairIter( state->outList.head, &searchTrans );
  802. for ( ; !pairIter.end(); pairIter++ ) {
  803. if ( pairIter.userState == RangeOverlap ) {
  804. /* Need to make character-space low and high keys from the range
  805. * overlap for the expansion object. */
  806. Key expLowKey = pairIter.s1Tel.lowKey - fromCondSpace->baseKey - fromVals *
  807. keyOps->alphSize() + keyOps->minKey;
  808. Key expHighKey = pairIter.s1Tel.highKey - fromCondSpace->baseKey - fromVals *
  809. keyOps->alphSize() + keyOps->minKey;
  810. Expansion *expansion = new Expansion( expLowKey, expHighKey );
  811. expansion->fromTrans = new TransAp(*pairIter.s1Tel.trans);
  812. expansion->fromTrans->fromState = 0;
  813. expansion->fromTrans->toState = pairIter.s1Tel.trans->toState;
  814. expansion->fromCondSpace = fromCondSpace;
  815. expansion->fromVals = fromVals;
  816. expansion->toCondSpace = toCondSpace;
  817. expansion->toValsList = toValsList;
  818. expansionList.append( expansion );
  819. #ifdef LOG_CONDS
  820. logNewExpansion( expansion );
  821. #endif
  822. }
  823. }
  824. }
  825. void FsmAp::findCondExpansions( ExpansionList &expansionList,
  826. StateAp *destState, StateAp *srcState )
  827. {
  828. PairIter<StateCond, StateCond> condCond( destState->stateCondList.head,
  829. srcState->stateCondList.head );
  830. for ( ; !condCond.end(); condCond++ ) {
  831. if ( condCond.userState == RangeOverlap ) {
  832. /* Loop over all existing condVals . */
  833. CondSet &destCS = condCond.s1Tel.trans->condSpace->condSet;
  834. long destLen = destCS.length();
  835. /* Find the items in src cond set that are not in dest
  836. * cond set. These are the items that we must expand. */
  837. CondSet srcOnlyCS = condCond.s2Tel.trans->condSpace->condSet;
  838. for ( CondSet::Iter dcsi = destCS; dcsi.lte(); dcsi++ )
  839. srcOnlyCS.remove( *dcsi );
  840. long srcOnlyLen = srcOnlyCS.length();
  841. if ( srcOnlyCS.length() > 0 ) {
  842. #ifdef LOG_CONDS
  843. cerr << "there are " << srcOnlyCS.length() << " item(s) that are "
  844. "only in the srcCS" << endl;
  845. #endif
  846. CondSet mergedCS = destCS;
  847. mergedCS.insert( condCond.s2Tel.trans->condSpace->condSet );
  848. CondSpace *fromCondSpace = addCondSpace( destCS );
  849. CondSpace *toCondSpace = addCondSpace( mergedCS );
  850. /* Loop all values in the dest space. */
  851. for ( long destVals = 0; destVals < (1 << destLen); destVals++ ) {
  852. long basicVals = 0;
  853. for ( CondSet::Iter csi = destCS; csi.lte(); csi++ ) {
  854. if ( destVals & (1 << csi.pos()) ) {
  855. Action **cim = mergedCS.find( *csi );
  856. long bitPos = (cim - mergedCS.data);
  857. basicVals |= 1 << bitPos;
  858. }
  859. }
  860. /* Loop all new values. */
  861. LongVect expandToVals;
  862. for ( long soVals = 0; soVals < (1 << srcOnlyLen); soVals++ ) {
  863. long targVals = basicVals;
  864. for ( CondSet::Iter csi = srcOnlyCS; csi.lte(); csi++ ) {
  865. if ( soVals & (1 << csi.pos()) ) {
  866. Action **cim = mergedCS.find( *csi );
  867. long bitPos = (cim - mergedCS.data);
  868. targVals |= 1 << bitPos;
  869. }
  870. }
  871. expandToVals.append( targVals );
  872. }
  873. findCondExpInTrans( expansionList, destState,
  874. condCond.s1Tel.lowKey, condCond.s1Tel.highKey,
  875. fromCondSpace, toCondSpace, destVals, expandToVals );
  876. }
  877. }
  878. }
  879. }
  880. }
  881. void FsmAp::doExpand( MergeData &md, StateAp *destState, ExpansionList &expList1 )
  882. {
  883. for ( ExpansionList::Iter exp = expList1; exp.lte(); exp++ ) {
  884. for ( LongVect::Iter to = exp->toValsList; to.lte(); to++ ) {
  885. long targVals = *to;
  886. /* We will use the copy of the transition that was made when the
  887. * expansion was created. It will get used multiple times. Each
  888. * time we must set up the keys, everything else is constant and
  889. * and already prepared. */
  890. TransAp *srcTrans = exp->fromTrans;
  891. srcTrans->lowKey = exp->toCondSpace->baseKey +
  892. targVals * keyOps->alphSize() + (exp->lowKey - keyOps->minKey);
  893. srcTrans->highKey = exp->toCondSpace->baseKey +
  894. targVals * keyOps->alphSize() + (exp->highKey - keyOps->minKey);
  895. TransList srcList;
  896. srcList.append( srcTrans );
  897. outTransCopy( md, destState, srcList.head );
  898. srcList.abandon();
  899. }
  900. }
  901. }
  902. void FsmAp::doRemove( MergeData &md, StateAp *destState, ExpansionList &expList1 )
  903. {
  904. for ( ExpansionList::Iter exp = expList1; exp.lte(); exp++ ) {
  905. Removal removal;
  906. if ( exp->fromCondSpace == 0 ) {
  907. removal.lowKey = exp->lowKey;
  908. removal.highKey = exp->highKey;
  909. }
  910. else {
  911. removal.lowKey = exp->fromCondSpace->baseKey +
  912. exp->fromVals * keyOps->alphSize() + (exp->lowKey - keyOps->minKey);
  913. removal.highKey = exp->fromCondSpace->baseKey +
  914. exp->fromVals * keyOps->alphSize() + (exp->highKey - keyOps->minKey);
  915. }
  916. removal.next = 0;
  917. TransList destList;
  918. PairIter<TransAp, Removal> pairIter( destState->outList.head, &removal );
  919. for ( ; !pairIter.end(); pairIter++ ) {
  920. switch ( pairIter.userState ) {
  921. case RangeInS1: {
  922. TransAp *destTrans = pairIter.s1Tel.trans;
  923. destTrans->lowKey = pairIter.s1Tel.lowKey;
  924. destTrans->highKey = pairIter.s1Tel.highKey;
  925. destList.append( destTrans );
  926. break;
  927. }
  928. case RangeInS2:
  929. break;
  930. case RangeOverlap: {
  931. TransAp *trans = pairIter.s1Tel.trans;
  932. detachTrans( trans->fromState, trans->toState, trans );
  933. delete trans;
  934. break;
  935. }
  936. case BreakS1: {
  937. pairIter.s1Tel.trans = dupTrans( destState,
  938. pairIter.s1Tel.trans );
  939. break;
  940. }
  941. case BreakS2:
  942. break;
  943. }
  944. }
  945. destState->outList.transfer( destList );
  946. }
  947. }
  948. void FsmAp::mergeStateConds( StateAp *destState, StateAp *srcState )
  949. {
  950. StateCondList destList;
  951. PairIter<StateCond> pairIter( destState->stateCondList.head,
  952. srcState->stateCondList.head );
  953. for ( ; !pairIter.end(); pairIter++ ) {
  954. switch ( pairIter.userState ) {
  955. case RangeInS1: {
  956. StateCond *destCond = pairIter.s1Tel.trans;
  957. destCond->lowKey = pairIter.s1Tel.lowKey;
  958. destCond->highKey = pairIter.s1Tel.highKey;
  959. destList.append( destCond );
  960. break;
  961. }
  962. case RangeInS2: {
  963. StateCond *newCond = new StateCond( *pairIter.s2Tel.trans );
  964. newCond->lowKey = pairIter.s2Tel.lowKey;
  965. newCond->highKey = pairIter.s2Tel.highKey;
  966. destList.append( newCond );
  967. break;
  968. }
  969. case RangeOverlap: {
  970. StateCond *destCond = pairIter.s1Tel.trans;
  971. StateCond *srcCond = pairIter.s2Tel.trans;
  972. CondSet mergedCondSet;
  973. mergedCondSet.insert( destCond->condSpace->condSet );
  974. mergedCondSet.insert( srcCond->condSpace->condSet );
  975. destCond->condSpace = addCondSpace( mergedCondSet );
  976. destCond->lowKey = pairIter.s1Tel.lowKey;
  977. destCond->highKey = pairIter.s1Tel.highKey;
  978. destList.append( destCond );
  979. break;
  980. }
  981. case BreakS1:
  982. pairIter.s1Tel.trans = new StateCond( *pairIter.s1Tel.trans );
  983. break;
  984. case BreakS2:
  985. break;
  986. }
  987. }
  988. destState->stateCondList.transfer( destList );
  989. }
  990. /* A state merge which represents the drawing in of leaving transitions. If
  991. * there is any out data then we duplicate the source state, transfer the out
  992. * data, then merge in the state. The new state will be reaped because it will
  993. * not be given any in transitions. */
  994. void FsmAp::mergeStatesLeaving( MergeData &md, StateAp *destState, StateAp *srcState )
  995. {
  996. if ( !hasOutData( destState ) )
  997. mergeStates( md, destState, srcState );
  998. else {
  999. StateAp *ssMutable = addState();
  1000. mergeStates( md, ssMutable, srcState );
  1001. transferOutData( ssMutable, destState );
  1002. for ( OutCondSet::Iter cond = destState->outCondSet; cond.lte(); cond++ )
  1003. embedCondition( md, ssMutable, cond->action, cond->sense );
  1004. mergeStates( md, destState, ssMutable );
  1005. }
  1006. }
  1007. void FsmAp::mergeStates( MergeData &md, StateAp *destState,
  1008. StateAp **srcStates, int numSrc )
  1009. {
  1010. for ( int s = 0; s < numSrc; s++ )
  1011. mergeStates( md, destState, srcStates[s] );
  1012. }
  1013. void FsmAp::mergeStates( MergeData &md, StateAp *destState, StateAp *srcState )
  1014. {
  1015. ExpansionList expList1;
  1016. ExpansionList expList2;
  1017. findTransExpansions( expList1, destState, srcState );
  1018. findCondExpansions( expList1, destState, srcState );
  1019. findTransExpansions( expList2, srcState, destState );
  1020. findCondExpansions( expList2, srcState, destState );
  1021. mergeStateConds( destState, srcState );
  1022. outTransCopy( md, destState, srcState->outList.head );
  1023. doExpand( md, destState, expList1 );
  1024. doExpand( md, destState, expList2 );
  1025. doRemove( md, destState, expList1 );
  1026. doRemove( md, destState, expList2 );
  1027. expList1.empty();
  1028. expList2.empty();
  1029. /* Get its bits and final state status. */
  1030. destState->stateBits |= ( srcState->stateBits & ~STB_ISFINAL );
  1031. if ( srcState->isFinState() )
  1032. setFinState( destState );
  1033. /* Draw in any properties of srcState into destState. */
  1034. if ( srcState == destState ) {
  1035. /* Duplicate the list to protect against write to source. The
  1036. * priorities sets are not copied in because that would have no
  1037. * effect. */
  1038. destState->epsilonTrans.append( EpsilonTrans( srcState->epsilonTrans ) );
  1039. /* Get all actions, duplicating to protect against write to source. */
  1040. destState->toStateActionTable.setActions(
  1041. ActionTable( srcState->toStateActionTable ) );
  1042. destState->fromStateActionTable.setActions(
  1043. ActionTable( srcState->fromStateActionTable ) );
  1044. destState->outActionTable.setActions( ActionTable( srcState->outActionTable ) );
  1045. destState->outCondSet.insert( OutCondSet( srcState->outCondSet ) );
  1046. destState->errActionTable.setActions( ErrActionTable( srcState->errActionTable ) );
  1047. destState->eofActionTable.setActions( ActionTable( srcState->eofActionTable ) );
  1048. }
  1049. else {
  1050. /* Get the epsilons, out priorities. */
  1051. destState->epsilonTrans.append( srcState->epsilonTrans );
  1052. destState->outPriorTable.setPriors( srcState->outPriorTable );
  1053. /* Get all actions. */
  1054. destState->toStateActionTable.setActions( srcState->toStateActionTable );
  1055. destState->fromStateActionTable.setActions( srcState->fromStateActionTable );
  1056. destState->outActionTable.setActions( srcState->outActionTable );
  1057. destState->outCondSet.insert( srcState->outCondSet );
  1058. destState->errActionTable.setActions( srcState->errActionTable );
  1059. destState->eofActionTable.setActions( srcState->eofActionTable );
  1060. }
  1061. }
  1062. void FsmAp::fillInStates( MergeData &md )
  1063. {
  1064. /* Merge any states that are awaiting merging. This will likey cause
  1065. * other states to be added to the stfil list. */
  1066. StateAp *state = md.stfillHead;
  1067. while ( state != 0 ) {
  1068. StateSet *stateSet = &state->stateDictEl->stateSet;
  1069. mergeStates( md, state, stateSet->data, stateSet->length() );
  1070. state = state->alg.next;
  1071. }
  1072. /* Delete the state sets of all states that are on the fill list. */
  1073. state = md.stfillHead;
  1074. while ( state != 0 ) {
  1075. /* Delete and reset the state set. */
  1076. delete state->stateDictEl;
  1077. state->stateDictEl = 0;
  1078. /* Next state in the stfill list. */
  1079. state = state->alg.next;
  1080. }
  1081. /* StateDict will still have its ptrs/size set but all of it's element
  1082. * will be deleted so we don't need to clean it up. */
  1083. }
  1084. void FsmAp::findEmbedExpansions( ExpansionList &expansionList,
  1085. StateAp *destState, Action *condAction, bool sense )
  1086. {
  1087. StateCondList destList;
  1088. PairIter<TransAp, StateCond> transCond( destState->outList.head,
  1089. destState->stateCondList.head );
  1090. for ( ; !transCond.end(); transCond++ ) {
  1091. switch ( transCond.userState ) {
  1092. case RangeInS1: {
  1093. if ( transCond.s1Tel.lowKey <= keyOps->maxKey ) {
  1094. assert( transCond.s1Tel.highKey <= keyOps->maxKey );
  1095. /* Make a new state cond. */
  1096. StateCond *newStateCond = new StateCond( transCond.s1Tel.lowKey,
  1097. transCond.s1Tel.highKey );
  1098. newStateCond->condSpace = addCondSpace( CondSet( condAction ) );
  1099. destList.append( newStateCond );
  1100. /* Create the expansion. */
  1101. Expansion *expansion = new Expansion( transCond.s1Tel.lowKey,
  1102. transCond.s1Tel.highKey );
  1103. expansion->fromTrans = new TransAp(*transCond.s1Tel.trans);
  1104. expansion->fromTrans->fromState = 0;
  1105. expansion->fromTrans->toState = transCond.s1Tel.trans->toState;
  1106. expansion->fromCondSpace = 0;
  1107. expansion->fromVals = 0;
  1108. expansion->toCondSpace = newStateCond->condSpace;
  1109. expansion->toValsList.append( sense?1:0 );
  1110. #ifdef LOG_CONDS
  1111. logNewExpansion( expansion );
  1112. #endif
  1113. expansionList.append( expansion );
  1114. }
  1115. break;
  1116. }
  1117. case RangeInS2: {
  1118. /* Enhance state cond and find the expansion. */
  1119. StateCond *stateCond = transCond.s2Tel.trans;
  1120. stateCond->lowKey = transCond.s2Tel.lowKey;
  1121. stateCond->highKey = transCond.s2Tel.highKey;
  1122. CondSet &destCS = stateCond->condSpace->condSet;
  1123. long destLen = destCS.length();
  1124. CondSpace *fromCondSpace = stateCond->condSpace;
  1125. CondSet mergedCS = destCS;
  1126. mergedCS.insert( condAction );
  1127. CondSpace *toCondSpace = addCondSpace( mergedCS );
  1128. stateCond->condSpace = toCondSpace;
  1129. destList.append( stateCond );
  1130. /* Loop all values in the dest space. */
  1131. for ( long destVals = 0; destVals < (1 << destLen); destVals++ ) {
  1132. long basicVals = 0;
  1133. for ( CondSet::Iter csi = destCS; csi.lte(); csi++ ) {
  1134. if ( destVals & (1 << csi.pos()) ) {
  1135. Action **cim = mergedCS.find( *csi );
  1136. long bitPos = (cim - mergedCS.data);
  1137. basicVals |= 1 << bitPos;
  1138. }
  1139. }
  1140. long targVals = basicVals;
  1141. Action **cim = mergedCS.find( condAction );
  1142. long bitPos = (cim - mergedCS.data);
  1143. targVals |= (sense?1:0) << bitPos;
  1144. LongVect expandToVals( targVals );
  1145. findCondExpInTrans( expansionList, destState,
  1146. transCond.s2Tel.lowKey, transCond.s2Tel.highKey,
  1147. fromCondSpace, toCondSpace, destVals, expandToVals );
  1148. }
  1149. break;
  1150. }
  1151. case RangeOverlap:
  1152. case BreakS1:
  1153. case BreakS2:
  1154. assert( false );
  1155. break;
  1156. }
  1157. }
  1158. destState->stateCondList.transfer( destList );
  1159. }
  1160. void FsmAp::embedCondition( StateAp *state, Action *condAction, bool sense )
  1161. {
  1162. MergeData md;
  1163. ExpansionList expList;
  1164. /* Turn on misfit accounting to possibly catch the old start state. */
  1165. setMisfitAccounting( true );
  1166. /* Worker. */
  1167. embedCondition( md, state, condAction, sense );
  1168. /* Fill in any states that were newed up as combinations of others. */
  1169. fillInStates( md );
  1170. /* Remove the misfits and turn off misfit accounting. */
  1171. removeMisfits();
  1172. setMisfitAccounting( false );
  1173. }
  1174. void FsmAp::embedCondition( MergeData &md, StateAp *state, Action *condAction, bool sense )
  1175. {
  1176. ExpansionList expList;
  1177. findEmbedExpansions( expList, state, condAction, sense );
  1178. doExpand( md, state, expList );
  1179. doRemove( md, state, expList );
  1180. expList.empty();
  1181. }
  1182. /* Check if a machine defines a single character. This is useful in validating
  1183. * ranges and machines to export. */
  1184. bool FsmAp::checkSingleCharMachine()
  1185. {
  1186. /* Must have two states. */
  1187. if ( stateList.length() != 2 )
  1188. return false;
  1189. /* The start state cannot be final. */
  1190. if ( startState->isFinState() )
  1191. return false;
  1192. /* There should be only one final state. */
  1193. if ( finStateSet.length() != 1 )
  1194. return false;
  1195. /* The final state cannot have any transitions out. */
  1196. if ( finStateSet[0]->outList.length() != 0 )
  1197. return false;
  1198. /* The start state should have only one transition out. */
  1199. if ( startState->outList.length() != 1 )
  1200. return false;
  1201. /* The singe transition out of the start state should not be a range. */
  1202. TransAp *startTrans = startState->outList.head;
  1203. if ( startTrans->lowKey != startTrans->highKey )
  1204. return false;
  1205. return true;
  1206. }