mltable.cpp 29 KB

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