cdtable.cpp 27 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132
  1. /*
  2. * Copyright 2001-2006 Adrian Thurston <thurston@complang.org>
  3. * 2004 Erich Ocean <eric.ocean@ampede.com>
  4. * 2005 Alan West <alan@alanz.com>
  5. */
  6. /* This file is part of Ragel.
  7. *
  8. * Ragel is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 2 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * Ragel is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with Ragel; if not, write to the Free Software
  20. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  21. */
  22. #include "ragel.h"
  23. #include "cdtable.h"
  24. #include "redfsm.h"
  25. #include "gendata.h"
  26. /* Determine if we should use indicies or not. */
  27. void TabCodeGen::calcIndexSize()
  28. {
  29. int sizeWithInds = 0, sizeWithoutInds = 0;
  30. /* Calculate cost of using with indicies. */
  31. for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
  32. int totalIndex = st->outSingle.length() + st->outRange.length() +
  33. (st->defTrans == 0 ? 0 : 1);
  34. sizeWithInds += arrayTypeSize(redFsm->maxIndex) * totalIndex;
  35. }
  36. sizeWithInds += arrayTypeSize(redFsm->maxState) * redFsm->transSet.length();
  37. if ( redFsm->anyActions() )
  38. sizeWithInds += arrayTypeSize(redFsm->maxActionLoc) * redFsm->transSet.length();
  39. /* Calculate the cost of not using indicies. */
  40. for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
  41. int totalIndex = st->outSingle.length() + st->outRange.length() +
  42. (st->defTrans == 0 ? 0 : 1);
  43. sizeWithoutInds += arrayTypeSize(redFsm->maxState) * totalIndex;
  44. if ( redFsm->anyActions() )
  45. sizeWithoutInds += arrayTypeSize(redFsm->maxActionLoc) * totalIndex;
  46. }
  47. /* If using indicies reduces the size, use them. */
  48. useIndicies = sizeWithInds < sizeWithoutInds;
  49. }
  50. std::ostream &TabCodeGen::TO_STATE_ACTION( RedStateAp *state )
  51. {
  52. int act = 0;
  53. if ( state->toStateAction != 0 )
  54. act = state->toStateAction->location+1;
  55. out << act;
  56. return out;
  57. }
  58. std::ostream &TabCodeGen::FROM_STATE_ACTION( RedStateAp *state )
  59. {
  60. int act = 0;
  61. if ( state->fromStateAction != 0 )
  62. act = state->fromStateAction->location+1;
  63. out << act;
  64. return out;
  65. }
  66. std::ostream &TabCodeGen::EOF_ACTION( RedStateAp *state )
  67. {
  68. int act = 0;
  69. if ( state->eofAction != 0 )
  70. act = state->eofAction->location+1;
  71. out << act;
  72. return out;
  73. }
  74. std::ostream &TabCodeGen::TRANS_ACTION( RedTransAp *trans )
  75. {
  76. /* If there are actions, emit them. Otherwise emit zero. */
  77. int act = 0;
  78. if ( trans->action != 0 )
  79. act = trans->action->location+1;
  80. out << act;
  81. return out;
  82. }
  83. std::ostream &TabCodeGen::TO_STATE_ACTION_SWITCH()
  84. {
  85. /* Walk the list of functions, printing the cases. */
  86. for ( GenActionList::Iter act = actionList; act.lte(); act++ ) {
  87. /* Write out referenced actions. */
  88. if ( act->numToStateRefs > 0 ) {
  89. /* Write the case label, the action and the case break. */
  90. out << "\tcase " << act->actionId << ":\n";
  91. ACTION( out, act, 0, false, false );
  92. out << "\tbreak;\n";
  93. }
  94. }
  95. genLineDirective( out );
  96. return out;
  97. }
  98. std::ostream &TabCodeGen::FROM_STATE_ACTION_SWITCH()
  99. {
  100. /* Walk the list of functions, printing the cases. */
  101. for ( GenActionList::Iter act = actionList; act.lte(); act++ ) {
  102. /* Write out referenced actions. */
  103. if ( act->numFromStateRefs > 0 ) {
  104. /* Write the case label, the action and the case break. */
  105. out << "\tcase " << act->actionId << ":\n";
  106. ACTION( out, act, 0, false, false );
  107. out << "\tbreak;\n";
  108. }
  109. }
  110. genLineDirective( out );
  111. return out;
  112. }
  113. std::ostream &TabCodeGen::EOF_ACTION_SWITCH()
  114. {
  115. /* Walk the list of functions, printing the cases. */
  116. for ( GenActionList::Iter act = actionList; act.lte(); act++ ) {
  117. /* Write out referenced actions. */
  118. if ( act->numEofRefs > 0 ) {
  119. /* Write the case label, the action and the case break. */
  120. out << "\tcase " << act->actionId << ":\n";
  121. ACTION( out, act, 0, true, false );
  122. out << "\tbreak;\n";
  123. }
  124. }
  125. genLineDirective( out );
  126. return out;
  127. }
  128. std::ostream &TabCodeGen::ACTION_SWITCH()
  129. {
  130. /* Walk the list of functions, printing the cases. */
  131. for ( GenActionList::Iter act = actionList; act.lte(); act++ ) {
  132. /* Write out referenced actions. */
  133. if ( act->numTransRefs > 0 ) {
  134. /* Write the case label, the action and the case break. */
  135. out << "\tcase " << act->actionId << ":\n";
  136. ACTION( out, act, 0, false, false );
  137. out << "\tbreak;\n";
  138. }
  139. }
  140. genLineDirective( out );
  141. return out;
  142. }
  143. std::ostream &TabCodeGen::COND_OFFSETS()
  144. {
  145. out << "\t";
  146. int totalStateNum = 0, curKeyOffset = 0;
  147. for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
  148. /* Write the key offset. */
  149. out << curKeyOffset;
  150. if ( !st.last() ) {
  151. out << ", ";
  152. if ( ++totalStateNum % IALL == 0 )
  153. out << "\n\t";
  154. }
  155. /* Move the key offset ahead. */
  156. curKeyOffset += st->stateCondList.length();
  157. }
  158. out << "\n";
  159. return out;
  160. }
  161. std::ostream &TabCodeGen::KEY_OFFSETS()
  162. {
  163. out << "\t";
  164. int totalStateNum = 0, curKeyOffset = 0;
  165. for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
  166. /* Write the key offset. */
  167. out << curKeyOffset;
  168. if ( !st.last() ) {
  169. out << ", ";
  170. if ( ++totalStateNum % IALL == 0 )
  171. out << "\n\t";
  172. }
  173. /* Move the key offset ahead. */
  174. curKeyOffset += st->outSingle.length() + st->outRange.length()*2;
  175. }
  176. out << "\n";
  177. return out;
  178. }
  179. std::ostream &TabCodeGen::INDEX_OFFSETS()
  180. {
  181. out << "\t";
  182. int totalStateNum = 0, curIndOffset = 0;
  183. for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
  184. /* Write the index offset. */
  185. out << curIndOffset;
  186. if ( !st.last() ) {
  187. out << ", ";
  188. if ( ++totalStateNum % IALL == 0 )
  189. out << "\n\t";
  190. }
  191. /* Move the index offset ahead. */
  192. curIndOffset += st->outSingle.length() + st->outRange.length();
  193. if ( st->defTrans != 0 )
  194. curIndOffset += 1;
  195. }
  196. out << "\n";
  197. return out;
  198. }
  199. std::ostream &TabCodeGen::COND_LENS()
  200. {
  201. out << "\t";
  202. int totalStateNum = 0;
  203. for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
  204. /* Write singles length. */
  205. out << st->stateCondList.length();
  206. if ( !st.last() ) {
  207. out << ", ";
  208. if ( ++totalStateNum % IALL == 0 )
  209. out << "\n\t";
  210. }
  211. }
  212. out << "\n";
  213. return out;
  214. }
  215. std::ostream &TabCodeGen::SINGLE_LENS()
  216. {
  217. out << "\t";
  218. int totalStateNum = 0;
  219. for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
  220. /* Write singles length. */
  221. out << st->outSingle.length();
  222. if ( !st.last() ) {
  223. out << ", ";
  224. if ( ++totalStateNum % IALL == 0 )
  225. out << "\n\t";
  226. }
  227. }
  228. out << "\n";
  229. return out;
  230. }
  231. std::ostream &TabCodeGen::RANGE_LENS()
  232. {
  233. out << "\t";
  234. int totalStateNum = 0;
  235. for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
  236. /* Emit length of range index. */
  237. out << st->outRange.length();
  238. if ( !st.last() ) {
  239. out << ", ";
  240. if ( ++totalStateNum % IALL == 0 )
  241. out << "\n\t";
  242. }
  243. }
  244. out << "\n";
  245. return out;
  246. }
  247. std::ostream &TabCodeGen::TO_STATE_ACTIONS()
  248. {
  249. out << "\t";
  250. int totalStateNum = 0;
  251. for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
  252. /* Write any eof action. */
  253. TO_STATE_ACTION(st);
  254. if ( !st.last() ) {
  255. out << ", ";
  256. if ( ++totalStateNum % IALL == 0 )
  257. out << "\n\t";
  258. }
  259. }
  260. out << "\n";
  261. return out;
  262. }
  263. std::ostream &TabCodeGen::FROM_STATE_ACTIONS()
  264. {
  265. out << "\t";
  266. int totalStateNum = 0;
  267. for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
  268. /* Write any eof action. */
  269. FROM_STATE_ACTION(st);
  270. if ( !st.last() ) {
  271. out << ", ";
  272. if ( ++totalStateNum % IALL == 0 )
  273. out << "\n\t";
  274. }
  275. }
  276. out << "\n";
  277. return out;
  278. }
  279. std::ostream &TabCodeGen::EOF_ACTIONS()
  280. {
  281. out << "\t";
  282. int totalStateNum = 0;
  283. for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
  284. /* Write any eof action. */
  285. EOF_ACTION(st);
  286. if ( !st.last() ) {
  287. out << ", ";
  288. if ( ++totalStateNum % IALL == 0 )
  289. out << "\n\t";
  290. }
  291. }
  292. out << "\n";
  293. return out;
  294. }
  295. std::ostream &TabCodeGen::EOF_TRANS()
  296. {
  297. out << "\t";
  298. int totalStateNum = 0;
  299. for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
  300. /* Write any eof action. */
  301. long trans = 0;
  302. if ( st->eofTrans != 0 ) {
  303. assert( st->eofTrans->pos >= 0 );
  304. trans = st->eofTrans->pos+1;
  305. }
  306. out << trans;
  307. if ( !st.last() ) {
  308. out << ", ";
  309. if ( ++totalStateNum % IALL == 0 )
  310. out << "\n\t";
  311. }
  312. }
  313. out << "\n";
  314. return out;
  315. }
  316. std::ostream &TabCodeGen::COND_KEYS()
  317. {
  318. out << '\t';
  319. int totalTrans = 0;
  320. for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
  321. /* Loop the state's transitions. */
  322. for ( GenStateCondList::Iter sc = st->stateCondList; sc.lte(); sc++ ) {
  323. /* Lower key. */
  324. out << KEY( sc->lowKey ) << ", ";
  325. if ( ++totalTrans % IALL == 0 )
  326. out << "\n\t";
  327. /* Upper key. */
  328. out << KEY( sc->highKey ) << ", ";
  329. if ( ++totalTrans % IALL == 0 )
  330. out << "\n\t";
  331. }
  332. }
  333. /* Output one last number so we don't have to figure out when the last
  334. * entry is and avoid writing a comma. */
  335. out << 0 << "\n";
  336. return out;
  337. }
  338. std::ostream &TabCodeGen::COND_SPACES()
  339. {
  340. out << '\t';
  341. int totalTrans = 0;
  342. for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
  343. /* Loop the state's transitions. */
  344. for ( GenStateCondList::Iter sc = st->stateCondList; sc.lte(); sc++ ) {
  345. /* Cond Space id. */
  346. out << sc->condSpace->condSpaceId << ", ";
  347. if ( ++totalTrans % IALL == 0 )
  348. out << "\n\t";
  349. }
  350. }
  351. /* Output one last number so we don't have to figure out when the last
  352. * entry is and avoid writing a comma. */
  353. out << 0 << "\n";
  354. return out;
  355. }
  356. std::ostream &TabCodeGen::KEYS()
  357. {
  358. out << '\t';
  359. int totalTrans = 0;
  360. for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
  361. /* Loop the singles. */
  362. for ( RedTransList::Iter stel = st->outSingle; stel.lte(); stel++ ) {
  363. out << KEY( stel->lowKey ) << ", ";
  364. if ( ++totalTrans % IALL == 0 )
  365. out << "\n\t";
  366. }
  367. /* Loop the state's transitions. */
  368. for ( RedTransList::Iter rtel = st->outRange; rtel.lte(); rtel++ ) {
  369. /* Lower key. */
  370. out << KEY( rtel->lowKey ) << ", ";
  371. if ( ++totalTrans % IALL == 0 )
  372. out << "\n\t";
  373. /* Upper key. */
  374. out << KEY( rtel->highKey ) << ", ";
  375. if ( ++totalTrans % IALL == 0 )
  376. out << "\n\t";
  377. }
  378. }
  379. /* Output one last number so we don't have to figure out when the last
  380. * entry is and avoid writing a comma. */
  381. out << 0 << "\n";
  382. return out;
  383. }
  384. std::ostream &TabCodeGen::INDICIES()
  385. {
  386. int totalTrans = 0;
  387. out << '\t';
  388. for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
  389. /* Walk the singles. */
  390. for ( RedTransList::Iter stel = st->outSingle; stel.lte(); stel++ ) {
  391. out << stel->value->id << ", ";
  392. if ( ++totalTrans % IALL == 0 )
  393. out << "\n\t";
  394. }
  395. /* Walk the ranges. */
  396. for ( RedTransList::Iter rtel = st->outRange; rtel.lte(); rtel++ ) {
  397. out << rtel->value->id << ", ";
  398. if ( ++totalTrans % IALL == 0 )
  399. out << "\n\t";
  400. }
  401. /* The state's default index goes next. */
  402. if ( st->defTrans != 0 ) {
  403. out << st->defTrans->id << ", ";
  404. if ( ++totalTrans % IALL == 0 )
  405. out << "\n\t";
  406. }
  407. }
  408. /* Output one last number so we don't have to figure out when the last
  409. * entry is and avoid writing a comma. */
  410. out << 0 << "\n";
  411. return out;
  412. }
  413. std::ostream &TabCodeGen::TRANS_TARGS()
  414. {
  415. int totalTrans = 0;
  416. out << '\t';
  417. for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
  418. /* Walk the singles. */
  419. for ( RedTransList::Iter stel = st->outSingle; stel.lte(); stel++ ) {
  420. RedTransAp *trans = stel->value;
  421. out << trans->targ->id << ", ";
  422. if ( ++totalTrans % IALL == 0 )
  423. out << "\n\t";
  424. }
  425. /* Walk the ranges. */
  426. for ( RedTransList::Iter rtel = st->outRange; rtel.lte(); rtel++ ) {
  427. RedTransAp *trans = rtel->value;
  428. out << trans->targ->id << ", ";
  429. if ( ++totalTrans % IALL == 0 )
  430. out << "\n\t";
  431. }
  432. /* The state's default target state. */
  433. if ( st->defTrans != 0 ) {
  434. RedTransAp *trans = st->defTrans;
  435. out << trans->targ->id << ", ";
  436. if ( ++totalTrans % IALL == 0 )
  437. out << "\n\t";
  438. }
  439. }
  440. /* Add any eof transitions that have not yet been written out above. */
  441. for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
  442. if ( st->eofTrans != 0 ) {
  443. RedTransAp *trans = st->eofTrans;
  444. trans->pos = totalTrans;
  445. out << trans->targ->id << ", ";
  446. if ( ++totalTrans % IALL == 0 )
  447. out << "\n\t";
  448. }
  449. }
  450. /* Output one last number so we don't have to figure out when the last
  451. * entry is and avoid writing a comma. */
  452. out << 0 << "\n";
  453. return out;
  454. }
  455. std::ostream &TabCodeGen::TRANS_ACTIONS()
  456. {
  457. int totalTrans = 0;
  458. out << '\t';
  459. for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
  460. /* Walk the singles. */
  461. for ( RedTransList::Iter stel = st->outSingle; stel.lte(); stel++ ) {
  462. RedTransAp *trans = stel->value;
  463. TRANS_ACTION( trans ) << ", ";
  464. if ( ++totalTrans % IALL == 0 )
  465. out << "\n\t";
  466. }
  467. /* Walk the ranges. */
  468. for ( RedTransList::Iter rtel = st->outRange; rtel.lte(); rtel++ ) {
  469. RedTransAp *trans = rtel->value;
  470. TRANS_ACTION( trans ) << ", ";
  471. if ( ++totalTrans % IALL == 0 )
  472. out << "\n\t";
  473. }
  474. /* The state's default index goes next. */
  475. if ( st->defTrans != 0 ) {
  476. RedTransAp *trans = st->defTrans;
  477. TRANS_ACTION( trans ) << ", ";
  478. if ( ++totalTrans % IALL == 0 )
  479. out << "\n\t";
  480. }
  481. }
  482. /* Add any eof transitions that have not yet been written out above. */
  483. for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
  484. if ( st->eofTrans != 0 ) {
  485. RedTransAp *trans = st->eofTrans;
  486. TRANS_ACTION( trans ) << ", ";
  487. if ( ++totalTrans % IALL == 0 )
  488. out << "\n\t";
  489. }
  490. }
  491. /* Output one last number so we don't have to figure out when the last
  492. * entry is and avoid writing a comma. */
  493. out << 0 << "\n";
  494. return out;
  495. }
  496. std::ostream &TabCodeGen::TRANS_TARGS_WI()
  497. {
  498. /* Transitions must be written ordered by their id. */
  499. RedTransAp **transPtrs = new RedTransAp*[redFsm->transSet.length()];
  500. for ( TransApSet::Iter trans = redFsm->transSet; trans.lte(); trans++ )
  501. transPtrs[trans->id] = trans;
  502. /* Keep a count of the num of items in the array written. */
  503. out << '\t';
  504. int totalStates = 0;
  505. for ( int t = 0; t < redFsm->transSet.length(); t++ ) {
  506. /* Record the position, need this for eofTrans. */
  507. RedTransAp *trans = transPtrs[t];
  508. trans->pos = t;
  509. /* Write out the target state. */
  510. out << trans->targ->id;
  511. if ( t < redFsm->transSet.length()-1 ) {
  512. out << ", ";
  513. if ( ++totalStates % IALL == 0 )
  514. out << "\n\t";
  515. }
  516. }
  517. out << "\n";
  518. delete[] transPtrs;
  519. return out;
  520. }
  521. std::ostream &TabCodeGen::TRANS_ACTIONS_WI()
  522. {
  523. /* Transitions must be written ordered by their id. */
  524. RedTransAp **transPtrs = new RedTransAp*[redFsm->transSet.length()];
  525. for ( TransApSet::Iter trans = redFsm->transSet; trans.lte(); trans++ )
  526. transPtrs[trans->id] = trans;
  527. /* Keep a count of the num of items in the array written. */
  528. out << '\t';
  529. int totalAct = 0;
  530. for ( int t = 0; t < redFsm->transSet.length(); t++ ) {
  531. /* Write the function for the transition. */
  532. RedTransAp *trans = transPtrs[t];
  533. TRANS_ACTION( trans );
  534. if ( t < redFsm->transSet.length()-1 ) {
  535. out << ", ";
  536. if ( ++totalAct % IALL == 0 )
  537. out << "\n\t";
  538. }
  539. }
  540. out << "\n";
  541. delete[] transPtrs;
  542. return out;
  543. }
  544. void TabCodeGen::LOCATE_TRANS()
  545. {
  546. out <<
  547. " _keys = " << ARR_OFF( K(), KO() + "[" + vCS() + "]" ) << ";\n"
  548. " _trans = " << IO() << "[" << vCS() << "];\n"
  549. "\n"
  550. " _klen = " << SL() << "[" << vCS() << "];\n"
  551. " if ( _klen > 0 ) {\n"
  552. " " << PTR_CONST() << WIDE_ALPH_TYPE() << PTR_CONST_END() << POINTER() << "_lower = _keys;\n"
  553. " " << PTR_CONST() << WIDE_ALPH_TYPE() << PTR_CONST_END() << POINTER() << "_mid;\n"
  554. " " << PTR_CONST() << WIDE_ALPH_TYPE() << PTR_CONST_END() << POINTER() << "_upper = _keys + _klen - 1;\n"
  555. " while (1) {\n"
  556. " if ( _upper < _lower )\n"
  557. " break;\n"
  558. "\n"
  559. " _mid = _lower + ((_upper-_lower) >> 1);\n"
  560. " if ( " << GET_WIDE_KEY() << " < *_mid )\n"
  561. " _upper = _mid - 1;\n"
  562. " else if ( " << GET_WIDE_KEY() << " > *_mid )\n"
  563. " _lower = _mid + 1;\n"
  564. " else {\n"
  565. " _trans += " << CAST(UINT()) << "(_mid - _keys);\n"
  566. " goto _match;\n"
  567. " }\n"
  568. " }\n"
  569. " _keys += _klen;\n"
  570. " _trans += _klen;\n"
  571. " }\n"
  572. "\n"
  573. " _klen = " << RL() << "[" << vCS() << "];\n"
  574. " if ( _klen > 0 ) {\n"
  575. " " << PTR_CONST() << WIDE_ALPH_TYPE() << PTR_CONST_END() << POINTER() << "_lower = _keys;\n"
  576. " " << PTR_CONST() << WIDE_ALPH_TYPE() << PTR_CONST_END() << POINTER() << "_mid;\n"
  577. " " << PTR_CONST() << WIDE_ALPH_TYPE() << PTR_CONST_END() << POINTER() << "_upper = _keys + (_klen<<1) - 2;\n"
  578. " while (1) {\n"
  579. " if ( _upper < _lower )\n"
  580. " break;\n"
  581. "\n"
  582. " _mid = _lower + (((_upper-_lower) >> 1) & ~1);\n"
  583. " if ( " << GET_WIDE_KEY() << " < _mid[0] )\n"
  584. " _upper = _mid - 2;\n"
  585. " else if ( " << GET_WIDE_KEY() << " > _mid[1] )\n"
  586. " _lower = _mid + 2;\n"
  587. " else {\n"
  588. " _trans += " << CAST(UINT()) << "((_mid - _keys)>>1);\n"
  589. " goto _match;\n"
  590. " }\n"
  591. " }\n"
  592. " _trans += _klen;\n"
  593. " }\n"
  594. "\n";
  595. }
  596. void TabCodeGen::GOTO( ostream &ret, int gotoDest, bool inFinish )
  597. {
  598. ret << "{";
  599. ret << vCS() << " = " << gotoDest << ";";
  600. if ( inFinish && !noEnd )
  601. EOF_CHECK( ret );
  602. ret << CTRL_FLOW() << "goto _again;";
  603. ret << "}";
  604. }
  605. void TabCodeGen::GOTO_EXPR( ostream &ret, GenInlineItem *ilItem, bool inFinish )
  606. {
  607. ret << "{";
  608. ret << vCS() << " = (";
  609. INLINE_LIST( ret, ilItem->children, 0, inFinish, false );
  610. ret << "); ";
  611. if ( inFinish && !noEnd )
  612. EOF_CHECK( ret );
  613. ret << CTRL_FLOW() << "goto _again;";
  614. ret << "}";
  615. }
  616. void TabCodeGen::CURS( ostream &ret, bool inFinish )
  617. {
  618. ret << "(_ps)";
  619. }
  620. void TabCodeGen::TARGS( ostream &ret, bool inFinish, int targState )
  621. {
  622. ret << "(" << vCS() << ")";
  623. }
  624. void TabCodeGen::NEXT( ostream &ret, int nextDest, bool inFinish )
  625. {
  626. ret << vCS() << " = " << nextDest << ";";
  627. }
  628. void TabCodeGen::NEXT_EXPR( ostream &ret, GenInlineItem *ilItem, bool inFinish )
  629. {
  630. ret << vCS() << " = (";
  631. INLINE_LIST( ret, ilItem->children, 0, inFinish, false );
  632. ret << ");";
  633. }
  634. void TabCodeGen::CALL( ostream &ret, int callDest, int targState, bool inFinish )
  635. {
  636. if ( prePushExpr != 0 ) {
  637. ret << "{";
  638. INLINE_LIST( ret, prePushExpr, 0, false, false );
  639. }
  640. ret << "{" << STACK() << "[" << TOP() << "++] = " << vCS() << "; " << vCS() << " = " << callDest << ";";
  641. if ( inFinish && !noEnd )
  642. EOF_CHECK( ret );
  643. ret << CTRL_FLOW() << "goto _again;";
  644. ret << "}";
  645. if ( prePushExpr != 0 )
  646. ret << "}";
  647. }
  648. void TabCodeGen::CALL_EXPR( ostream &ret, GenInlineItem *ilItem, int targState, bool inFinish )
  649. {
  650. if ( prePushExpr != 0 ) {
  651. ret << "{";
  652. INLINE_LIST( ret, prePushExpr, 0, false, false );
  653. }
  654. ret << "{";
  655. ret << STACK() << "[" << TOP() << "++] = " << vCS() << "; " << vCS() << " = (";
  656. INLINE_LIST( ret, ilItem->children, targState, inFinish, false );
  657. ret << ");";
  658. if ( inFinish && !noEnd )
  659. EOF_CHECK( ret );
  660. ret << CTRL_FLOW() << "goto _again;";
  661. ret << "}";
  662. if ( prePushExpr != 0 )
  663. ret << "}";
  664. }
  665. void TabCodeGen::RET( ostream &ret, bool inFinish )
  666. {
  667. ret << "{" << vCS() << " = " << STACK() << "[--" <<
  668. TOP() << "]; ";
  669. if ( postPopExpr != 0 ) {
  670. ret << "{";
  671. INLINE_LIST( ret, postPopExpr, 0, false, false );
  672. ret << "}";
  673. }
  674. if ( inFinish && !noEnd )
  675. EOF_CHECK( ret );
  676. ret << CTRL_FLOW() << "goto _again;";
  677. ret << "}";
  678. }
  679. void TabCodeGen::BREAK( ostream &ret, int targState, bool csForced )
  680. {
  681. outLabelUsed = true;
  682. ret << "{" << P() << "++; " << CTRL_FLOW() << "goto _out; }";
  683. }
  684. void TabCodeGen::writeData()
  685. {
  686. /* If there are any transtion functions then output the array. If there
  687. * are none, don't bother emitting an empty array that won't be used. */
  688. if ( redFsm->anyActions() ) {
  689. OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActArrItem), A() );
  690. ACTIONS_ARRAY();
  691. CLOSE_ARRAY() <<
  692. "\n";
  693. }
  694. if ( redFsm->anyConditions() ) {
  695. OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCondOffset), CO() );
  696. COND_OFFSETS();
  697. CLOSE_ARRAY() <<
  698. "\n";
  699. OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCondLen), CL() );
  700. COND_LENS();
  701. CLOSE_ARRAY() <<
  702. "\n";
  703. OPEN_ARRAY( WIDE_ALPH_TYPE(), CK() );
  704. COND_KEYS();
  705. CLOSE_ARRAY() <<
  706. "\n";
  707. OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCondSpaceId), C() );
  708. COND_SPACES();
  709. CLOSE_ARRAY() <<
  710. "\n";
  711. }
  712. OPEN_ARRAY( ARRAY_TYPE(redFsm->maxKeyOffset), KO() );
  713. KEY_OFFSETS();
  714. CLOSE_ARRAY() <<
  715. "\n";
  716. OPEN_ARRAY( WIDE_ALPH_TYPE(), K() );
  717. KEYS();
  718. CLOSE_ARRAY() <<
  719. "\n";
  720. OPEN_ARRAY( ARRAY_TYPE(redFsm->maxSingleLen), SL() );
  721. SINGLE_LENS();
  722. CLOSE_ARRAY() <<
  723. "\n";
  724. OPEN_ARRAY( ARRAY_TYPE(redFsm->maxRangeLen), RL() );
  725. RANGE_LENS();
  726. CLOSE_ARRAY() <<
  727. "\n";
  728. OPEN_ARRAY( ARRAY_TYPE(redFsm->maxIndexOffset), IO() );
  729. INDEX_OFFSETS();
  730. CLOSE_ARRAY() <<
  731. "\n";
  732. if ( useIndicies ) {
  733. OPEN_ARRAY( ARRAY_TYPE(redFsm->maxIndex), I() );
  734. INDICIES();
  735. CLOSE_ARRAY() <<
  736. "\n";
  737. OPEN_ARRAY( ARRAY_TYPE(redFsm->maxState), TT() );
  738. TRANS_TARGS_WI();
  739. CLOSE_ARRAY() <<
  740. "\n";
  741. if ( redFsm->anyActions() ) {
  742. OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), TA() );
  743. TRANS_ACTIONS_WI();
  744. CLOSE_ARRAY() <<
  745. "\n";
  746. }
  747. }
  748. else {
  749. OPEN_ARRAY( ARRAY_TYPE(redFsm->maxState), TT() );
  750. TRANS_TARGS();
  751. CLOSE_ARRAY() <<
  752. "\n";
  753. if ( redFsm->anyActions() ) {
  754. OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), TA() );
  755. TRANS_ACTIONS();
  756. CLOSE_ARRAY() <<
  757. "\n";
  758. }
  759. }
  760. if ( redFsm->anyToStateActions() ) {
  761. OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), TSA() );
  762. TO_STATE_ACTIONS();
  763. CLOSE_ARRAY() <<
  764. "\n";
  765. }
  766. if ( redFsm->anyFromStateActions() ) {
  767. OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), FSA() );
  768. FROM_STATE_ACTIONS();
  769. CLOSE_ARRAY() <<
  770. "\n";
  771. }
  772. if ( redFsm->anyEofActions() ) {
  773. OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), EA() );
  774. EOF_ACTIONS();
  775. CLOSE_ARRAY() <<
  776. "\n";
  777. }
  778. if ( redFsm->anyEofTrans() ) {
  779. OPEN_ARRAY( ARRAY_TYPE(redFsm->maxIndexOffset+1), ET() );
  780. EOF_TRANS();
  781. CLOSE_ARRAY() <<
  782. "\n";
  783. }
  784. STATE_IDS();
  785. }
  786. void TabCodeGen::COND_TRANSLATE()
  787. {
  788. out <<
  789. " _widec = " << GET_KEY() << ";\n"
  790. " _klen = " << CL() << "[" << vCS() << "];\n"
  791. " _keys = " << ARR_OFF( CK(), "(" + CO() + "[" + vCS() + "]*2)" ) << ";\n"
  792. " if ( _klen > 0 ) {\n"
  793. " " << PTR_CONST() << WIDE_ALPH_TYPE() << PTR_CONST_END() << POINTER() << "_lower = _keys;\n"
  794. " " << PTR_CONST() << WIDE_ALPH_TYPE() << PTR_CONST_END() << POINTER() << "_mid;\n"
  795. " " << PTR_CONST() << WIDE_ALPH_TYPE() << PTR_CONST_END() << POINTER() << "_upper = _keys + (_klen<<1) - 2;\n"
  796. " while (1) {\n"
  797. " if ( _upper < _lower )\n"
  798. " break;\n"
  799. "\n"
  800. " _mid = _lower + (((_upper-_lower) >> 1) & ~1);\n"
  801. " if ( " << GET_WIDE_KEY() << " < _mid[0] )\n"
  802. " _upper = _mid - 2;\n"
  803. " else if ( " << GET_WIDE_KEY() << " > _mid[1] )\n"
  804. " _lower = _mid + 2;\n"
  805. " else {\n"
  806. " switch ( " << C() << "[" << CO() << "[" << vCS() << "]"
  807. " + ((_mid - _keys)>>1)] ) {\n";
  808. for ( CondSpaceList::Iter csi = condSpaceList; csi.lte(); csi++ ) {
  809. GenCondSpace *condSpace = csi;
  810. out << " case " << condSpace->condSpaceId << ": {\n";
  811. out << TABS(2) << "_widec = " << CAST(WIDE_ALPH_TYPE()) << "(" <<
  812. KEY(condSpace->baseKey) << " + (" << GET_KEY() <<
  813. " - " << KEY(keyOps->minKey) << "));\n";
  814. for ( GenCondSet::Iter csi = condSpace->condSet; csi.lte(); csi++ ) {
  815. out << TABS(2) << "if ( ";
  816. CONDITION( out, *csi );
  817. Size condValOffset = ((1 << csi.pos()) * keyOps->alphSize());
  818. out << " ) _widec += " << condValOffset << ";\n";
  819. }
  820. out <<
  821. " break;\n"
  822. " }\n";
  823. }
  824. SWITCH_DEFAULT();
  825. out <<
  826. " }\n"
  827. " break;\n"
  828. " }\n"
  829. " }\n"
  830. " }\n"
  831. "\n";
  832. }
  833. void TabCodeGen::writeExec()
  834. {
  835. testEofUsed = false;
  836. outLabelUsed = false;
  837. out <<
  838. " {\n"
  839. " int _klen";
  840. if ( redFsm->anyRegCurStateRef() )
  841. out << ", _ps";
  842. out <<
  843. ";\n"
  844. " " << UINT() << " _trans;\n";
  845. if ( redFsm->anyConditions() )
  846. out << " " << WIDE_ALPH_TYPE() << " _widec;\n";
  847. if ( redFsm->anyToStateActions() || redFsm->anyRegActions()
  848. || redFsm->anyFromStateActions() )
  849. {
  850. out <<
  851. " " << PTR_CONST() << ARRAY_TYPE(redFsm->maxActArrItem) << PTR_CONST_END() <<
  852. POINTER() << "_acts;\n"
  853. " " << UINT() << " _nacts;\n";
  854. }
  855. out <<
  856. " " << PTR_CONST() << WIDE_ALPH_TYPE() << PTR_CONST_END() << POINTER() << "_keys;\n"
  857. "\n";
  858. if ( !noEnd ) {
  859. testEofUsed = true;
  860. out <<
  861. " if ( " << P() << " == " << PE() << " )\n"
  862. " goto _test_eof;\n";
  863. }
  864. if ( redFsm->errState != 0 ) {
  865. outLabelUsed = true;
  866. out <<
  867. " if ( " << vCS() << " == " << redFsm->errState->id << " )\n"
  868. " goto _out;\n";
  869. }
  870. out << "_resume:\n";
  871. if ( redFsm->anyFromStateActions() ) {
  872. out <<
  873. " _acts = " << ARR_OFF( A(), FSA() + "[" + vCS() + "]" ) << ";\n"
  874. " _nacts = " << CAST(UINT()) << " *_acts++;\n"
  875. " while ( _nacts-- > 0 ) {\n"
  876. " switch ( *_acts++ ) {\n";
  877. FROM_STATE_ACTION_SWITCH();
  878. SWITCH_DEFAULT() <<
  879. " }\n"
  880. " }\n"
  881. "\n";
  882. }
  883. if ( redFsm->anyConditions() )
  884. COND_TRANSLATE();
  885. LOCATE_TRANS();
  886. out << "_match:\n";
  887. if ( useIndicies )
  888. out << " _trans = " << I() << "[_trans];\n";
  889. if ( redFsm->anyEofTrans() )
  890. out << "_eof_trans:\n";
  891. if ( redFsm->anyRegCurStateRef() )
  892. out << " _ps = " << vCS() << ";\n";
  893. out <<
  894. " " << vCS() << " = " << TT() << "[_trans];\n"
  895. "\n";
  896. if ( redFsm->anyRegActions() ) {
  897. out <<
  898. " if ( " << TA() << "[_trans] == 0 )\n"
  899. " goto _again;\n"
  900. "\n"
  901. " _acts = " << ARR_OFF( A(), TA() + "[_trans]" ) << ";\n"
  902. " _nacts = " << CAST(UINT()) << " *_acts++;\n"
  903. " while ( _nacts-- > 0 )\n {\n"
  904. " switch ( *_acts++ )\n {\n";
  905. ACTION_SWITCH();
  906. SWITCH_DEFAULT() <<
  907. " }\n"
  908. " }\n"
  909. "\n";
  910. }
  911. if ( redFsm->anyRegActions() || redFsm->anyActionGotos() ||
  912. redFsm->anyActionCalls() || redFsm->anyActionRets() )
  913. out << "_again:\n";
  914. if ( redFsm->anyToStateActions() ) {
  915. out <<
  916. " _acts = " << ARR_OFF( A(), TSA() + "[" + vCS() + "]" ) << ";\n"
  917. " _nacts = " << CAST(UINT()) << " *_acts++;\n"
  918. " while ( _nacts-- > 0 ) {\n"
  919. " switch ( *_acts++ ) {\n";
  920. TO_STATE_ACTION_SWITCH();
  921. SWITCH_DEFAULT() <<
  922. " }\n"
  923. " }\n"
  924. "\n";
  925. }
  926. if ( redFsm->errState != 0 ) {
  927. outLabelUsed = true;
  928. out <<
  929. " if ( " << vCS() << " == " << redFsm->errState->id << " )\n"
  930. " goto _out;\n";
  931. }
  932. if ( !noEnd ) {
  933. out <<
  934. " if ( ++" << P() << " != " << PE() << " )\n"
  935. " goto _resume;\n";
  936. }
  937. else {
  938. out <<
  939. " " << P() << " += 1;\n"
  940. " goto _resume;\n";
  941. }
  942. if ( testEofUsed )
  943. out << " _test_eof: {}\n";
  944. if ( redFsm->anyEofTrans() || redFsm->anyEofActions() ) {
  945. out <<
  946. " if ( " << P() << " == " << vEOF() << " )\n"
  947. " {\n";
  948. if ( redFsm->anyEofTrans() ) {
  949. out <<
  950. " if ( " << ET() << "[" << vCS() << "] > 0 ) {\n"
  951. " _trans = " << ET() << "[" << vCS() << "] - 1;\n"
  952. " goto _eof_trans;\n"
  953. " }\n";
  954. }
  955. if ( redFsm->anyEofActions() ) {
  956. out <<
  957. " " << PTR_CONST() << ARRAY_TYPE(redFsm->maxActArrItem) << PTR_CONST_END() <<
  958. POINTER() << "__acts = " <<
  959. ARR_OFF( A(), EA() + "[" + vCS() + "]" ) << ";\n"
  960. " " << UINT() << " __nacts = " << CAST(UINT()) << " *__acts++;\n"
  961. " while ( __nacts-- > 0 ) {\n"
  962. " switch ( *__acts++ ) {\n";
  963. EOF_ACTION_SWITCH();
  964. SWITCH_DEFAULT() <<
  965. " }\n"
  966. " }\n";
  967. }
  968. out <<
  969. " }\n"
  970. "\n";
  971. }
  972. if ( outLabelUsed )
  973. out << " _out: {}\n";
  974. out << " }\n";
  975. }